[インデックス 15770] ファイルの概要
このコミットは、Go言語のランタイムとネットワークパッケージにおけるARMアーキテクチャ向けのビルド問題を修正することを目的としています。具体的には、net/fd_linux.go
ファイルがARM環境で引き続き必要であるため再導入し、ランタイムの再編成に伴ういくつかのタイプミスを修正しています。これにより、ARMベースのシステム上でのGoプログラムの安定性と正しい動作が保証されます。
コミット
commit cf46e561b2be3b15649fe029ffa8dc02fca6459a
Author: Russ Cox <rsc@golang.org>
Date: Thu Mar 14 19:42:25 2013 +0000
runtime, net: fix arm build
Bring net/fd_linux.go back (it was deleted this morning)
because it is still needed for ARM.
Fix a few typos in the runtime reorg.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7759046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cf46e561b2be3b15649fe029ffa8dc02fca6459a
元コミット内容
runtime, net: fix arm build
Bring net/fd_linux.go back (it was deleted this morning)
because it is still needed for ARM.
Fix a few typos in the runtime reorg.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7759046
変更の背景
このコミットの背景には、Go言語のランタイムとネットワークスタックがARMアーキテクチャ上で正しく機能するための継続的な努力があります。コミットメッセージによると、net/fd_linux.go
ファイルがその日の朝に削除されたものの、ARM環境では依然として必要であることが判明したため、このファイルを元に戻す必要がありました。これは、Goのクロスプラットフォーム対応において、特定のアーキテクチャ(この場合はARM)が独自のシステムコールやカーネルインターフェースを必要とすることがあるためです。
また、ランタイムの再編成("runtime reorg")が行われた際に、いくつかのタイプミスが発生したようです。これらのタイプミスは、コードのコンパイルエラーや実行時の誤動作を引き起こす可能性があるため、修正が必要でした。このコミットは、これらの問題を迅速に特定し、修正することで、GoのARMビルドの健全性を維持することを目的としています。
前提知識の解説
ARMアーキテクチャ
ARM(Advanced RISC Machine)は、モバイルデバイス、組み込みシステム、IoTデバイス、さらにはサーバーやデスクトップPCなど、幅広い分野で利用されているRISC(Reduced Instruction Set Computer)ベースのプロセッサアーキテクチャです。低消費電力と高い性能効率が特徴であり、Go言語のようなクロスプラットフォーム対応の言語にとって、ARMサポートは非常に重要です。LinuxカーネルはARMプロセッサを広くサポートしており、GoプログラムがARM Linux上で動作するためには、適切なシステムコールインターフェースとランタイムサポートが必要です。
epoll(7)
epoll
は、Linuxカーネルが提供するI/Oイベント通知メカニズムであり、多数のファイルディスクリプタ(ネットワークソケットなど)を効率的に監視するために使用されます。select
やpoll
といった従来のメカニズムと比較して、epoll
はスケーラビリティに優れており、特に高並行なネットワークアプリケーションでその真価を発揮します。Goのネットワークポーラー(netpoller)は、Linux上ではepoll
を利用して、ノンブロッキングI/Oとゴルーチンのスケジューリングを連携させています。これにより、Go開発者はブロッキングI/Oのように見えるコードを記述しながら、内部的には効率的なイベント駆動型I/Oを実現できます。
Goランタイムとネットワークポーラー
Go言語のランタイムは、ゴルーチン(軽量スレッド)のスケジューリング、ガベージコレクション、システムコールインターフェースなど、Goプログラムの実行環境全体を管理します。ネットワークI/Oに関しては、Goランタイムは「ネットワークポーラー」と呼ばれるコンポーネントを使用します。これは、OSが提供するI/O多重化メカニズム(Linuxではepoll
、macOS/BSDではkqueue
、WindowsではIOCP
)と連携し、ネットワーク操作が完了するまでゴルーチンをブロックせずに、他のゴルーチンが実行できるようにします。これにより、Goは高い並行性と効率的なネットワーク処理を実現しています。
Goにおけるシグナルハンドリング
Goプログラムは、os/signal
パッケージを通じてOSシグナルを処理できます。Goランタイム自体も、SIGSEGV
(セグメンテーション違反)やSIGINT
(Ctrl+Cによる割り込み)などの特定のシグナルに対して独自のハンドラを設定します。ランタイムは、これらのシグナルを捕捉し、必要に応じてパニックを発生させたり、プログラムの正常終了を促したりします。シグナルハンドリングは、プログラムの堅牢性と、外部からのイベント(例えば、システムシャットダウン)への応答性を確保するために不可欠です。ARMアーキテクチャにおいても、Goランタイムは他のUnix系システムと同様のシグナルハンドリングモデルを提供します。
技術的詳細
このコミットは、主に以下の2つの技術的な問題に対処しています。
-
net/fd_linux.go
の再導入:net/fd_linux.go
は、Goのnet
パッケージがLinux上でファイルディスクリプタ(FD)のI/Oイベントを効率的に待機するために使用するepoll
ベースのポーリングメカニズムを実装しています。コミットメッセージによると、このファイルは一時的に削除されたものの、ARMアーキテクチャでは引き続きその機能が必要であることが判明しました。これは、ARM環境におけるGoのネットワークスタックが、特定のepoll
関連の実装に依存していたことを示唆しています。このファイルの再導入により、ARM上でのネットワークI/Oが正しく機能するようになります。fd_linux.go
内のpollster
構造体は、epoll
インスタンス(epfd
)と、監視対象のファイルディスクリプタおよびそれに関連するイベントを管理するためのマップ(events
)を保持します。AddFD
、StopWaiting
、DelFD
、WaitFD
といったメソッドは、epoll_ctl
システムコールを使用してFDの追加、変更、削除を行い、epoll_wait
システムコールを使用してイベントを待機します。特に、+build arm
ディレクティブは、このファイルがARMアーキテクチャ向けにのみビルドされることを示しており、他のアーキテクチャでは異なるポーリングメカニズムが使用される可能性があることを意味します。 -
ランタイム再編成におけるタイプミス修正: Goランタイムのコードベースは複雑であり、大規模な再編成("runtime reorg")は、既存のコードに意図しない変更やタイプミスを導入する可能性があります。このコミットでは、
src/pkg/runtime/defs_linux_arm.h
、src/pkg/runtime/signal_arm.c
、src/pkg/runtime/signal_linux_arm.h
の3つのファイルでタイプミスが修正されています。src/pkg/runtime/defs_linux_arm.h
: このファイルは、ARM Linux環境におけるランタイムの定義(定数など)を含んでいます。修正では、ENOMEM
とEAGAIN
というエラーコードの定義が追加されています。これらは、システムコールがメモリ不足やリソースの一時的な不足を報告する際に使用される重要な定数です。以前のコミットでこれらの定義が欠落していたか、誤っていた可能性があります。src/pkg/runtime/signal_arm.c
: このファイルは、ARMアーキテクチャにおけるシグナルハンドリングのコアロジックを含んでいます。修正では、gp->sigcode1 = SIG_FAULT(info, ctxt);
とruntime·dumpregs(info, ctxt);
の呼び出しが変更されています。これは、シグナル情報(特にフォルトアドレスやレジスタダンプ)の取得方法に関するタイプミスや、ランタイムの再編成に伴うAPIの変更に対応していると考えられます。src/pkg/runtime/signal_linux_arm.h
: このファイルは、ARM Linux環境におけるシグナル関連のマクロ定義を含んでいます。修正では、#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
が追加されています。これは、シグナル情報構造体(siginfo_t
)からシグナルコード(si_code
)を取得するためのマクロであり、シグナルハンドラがシグナルの詳細な原因を特定するために使用されます。
これらの修正は、GoのARMビルドの安定性と正確性を確保するために不可欠であり、特に低レベルのシステムプログラミングと密接に関連するランタイムとネットワークスタックの領域における細心の注意が必要であることを示しています。
コアとなるコードの変更箇所
このコミットによって変更されたファイルは以下の通りです。
src/pkg/net/fd_linux.go
: 194行追加。このファイルは新規追加(実際には再導入)されています。src/pkg/runtime/defs_linux_arm.h
: 7行追加、1行削除。src/pkg/runtime/signal_arm.c
: 2行追加、2行削除。src/pkg/runtime/signal_linux_arm.h
: 1行追加。
src/pkg/net/fd_linux.go
このファイルは、Linux ARM環境におけるepoll
ベースのファイルディスクリプタポーリングメカニズムを実装しています。主な内容は以下の通りです。
+build arm
ディレクティブにより、ARMアーキテクチャでのみビルドされることを指定。pollster
構造体:epoll
インスタンスのファイルディスクリプタ (epfd
)、監視中のイベント (events
マップ)、epoll_wait
およびepoll_ctl
のためのバッファを保持。newpollster()
:epoll_create1
またはepoll_create
システムコールを使用してepoll
インスタンスを作成。AddFD(fd int, mode int, repeat bool)
: 指定されたファイルディスクリプタをepoll
インスタンスに追加または変更。読み取り ('r'
) または書き込み ('w'
) イベントを監視し、EPOLLONESHOT
フラグを設定可能。StopWaiting(fd int, bits uint)
: 指定されたファイルディスクリプタの監視を停止。EPOLLONESHOT
が設定されている場合、イベントを削除または変更。DelFD(fd int, mode int)
: 指定されたファイルディスクリプタの監視を完全に削除。WaitFD(s *pollServer, nsec int64)
:epoll_wait
システムコールを使用してイベントを待機し、準備ができたファイルディスクリプタとイベントモードを返す。Close()
:epoll
インスタンスを閉じる。
src/pkg/runtime/defs_linux_arm.h
このヘッダーファイルは、ARM Linux環境におけるランタイムの定数を定義しています。
--- a/src/pkg/runtime/defs_linux_arm.h
+++ b/src/pkg/runtime/defs_linux_arm.h
@@ -1,9 +1,10 @@
-// godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c
-\
-// MACHINE GENERATED - DO NOT EDIT.
+// TODO: Generate using cgo like defs_linux_{386,amd64}.h
// Constants
enum {
+\tENOMEM = 0xc,\
+\tEAGAIN = 0xb,\
+\
PROT_NONE = 0,\
PROT_READ = 0x1,\
PROT_WRITE = 0x2,
ENOMEM
(0xc) とEAGAIN
(0xb) の定数定義が追加されました。これらは、システムコールが返す可能性のある一般的なエラーコードです。
src/pkg/runtime/signal_arm.c
このファイルは、ARMアーキテクチャにおけるシグナルハンドリングのC言語実装です。
--- a/src/pkg/runtime/signal_arm.c
+++ b/src/pkg/runtime/signal_arm.c
@@ -61,7 +61,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
// the unwinding code.
gp->sig = sig;
gp->sigcode0 = SIG_CODE0(info, ctxt);
-\t\tgp->sigcode1 = SIG_FAULT_ADDRESS(info, ctxt);\
+\t\tgp->sigcode1 = SIG_FAULT(info, ctxt);\
gp->sigpc = SIG_PC(info, ctxt);
// We arrange lr, and pc to pretend the panicking
@@ -113,7 +113,7 @@ Throw:
runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
-\t\truntime·dumpregs(r);\
+\t\truntime·dumpregs(info, ctxt);\
}
runtime·exit(2);
gp->sigcode1
の割り当てがSIG_FAULT_ADDRESS
からSIG_FAULT
に変更されました。これは、シグナル情報からフォルトアドレスを取得する方法の変更に対応している可能性があります。runtime·dumpregs
の呼び出しがruntime·dumpregs(r)
からruntime·dumpregs(info, ctxt)
に変更されました。これは、レジスタダンプ関数に渡す引数の変更であり、シグナルコンテキスト情報が直接渡されるようになったことを示唆しています。
src/pkg/runtime/signal_linux_arm.h
このヘッダーファイルは、ARM Linux環境におけるシグナル関連のマクロ定義です。
--- a/src/pkg/runtime/signal_linux_arm.h
+++ b/src/pkg/runtime/signal_linux_arm.h
@@ -25,3 +25,4 @@
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap_no)
#define SIG_ERROR(info, ctxt) (SIG_REGS(ctxt).error_code)
#define SIG_OLDMASK(info, ctxt) (SIG_REGS(ctxt).oldmask)
+#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
SIG_CODE0(info, ctxt)
マクロが追加されました。これは、siginfo_t
構造体からsi_code
メンバー(シグナルコード)を取得するためのものです。
コアとなるコードの解説
src/pkg/net/fd_linux.go
このファイルは、GoのネットワークポーラーがLinux ARM上でどのように機能するかを示す重要な部分です。epoll
システムコールを直接利用して、ノンブロッキングI/Oを実現しています。
pollster
構造体:epoll
インスタンスのファイルディスクリプタ(epfd
)を保持し、epoll_create1
またはepoll_create
で初期化されます。events
マップは、現在epoll
で監視されているFDとそのイベントフラグを追跡します。AddFD
メソッド:syscall.EpollCtl
をEPOLL_CTL_ADD
またはEPOLL_CTL_MOD
オペレーションで使用して、FDをepoll
インスタンスに追加または既存のFDのイベントを更新します。EPOLLONESHOT
フラグは、イベントが一度発生したら自動的に監視を停止するかどうかを制御します。WaitFD
メソッド:syscall.EpollWait
を呼び出して、イベントが発生するまでブロックします。イベントが発生すると、waitEventBuf
に格納され、処理のために返されます。このメカニズムにより、Goランタイムは多数のネットワーク接続を効率的に処理できます。StopWaiting
およびDelFD
メソッド:syscall.EpollCtl
をEPOLL_CTL_MOD
またはEPOLL_CTL_DEL
オペレーションで使用して、FDの監視を停止または削除します。
このファイルがARMビルドに不可欠であるということは、ARM環境におけるGoのネットワークスタックが、他のアーキテクチャとは異なる、または特定のepoll
関連の挙動に依存していることを示唆しています。
src/pkg/runtime/defs_linux_arm.h
ENOMEM
とEAGAIN
の追加は、Goランタイムがシステムコールからの特定のエラーコードを認識し、適切に処理できるようにするために重要です。これらのエラーは、リソースの枯渇や一時的な利用不可を示すものであり、Goプログラムがこれらの状況に適切に対応することで、より堅牢になります。
src/pkg/runtime/signal_arm.c
シグナルハンドリングの変更は、ARMアーキテクチャにおけるシグナル情報の正確な取得と処理を保証します。
gp->sigcode1 = SIG_FAULT(info, ctxt);
への変更は、シグナルによって引き起こされたフォルト(例えば、メモリ違反)に関する詳細な情報を取得するためのより正確な方法を提供します。これは、デバッグやクラッシュレポートの生成において非常に重要です。runtime·dumpregs(info, ctxt);
への変更は、シグナル発生時のCPUレジスタの状態をダンプする際に、より完全なコンテキスト情報(siginfo_t
とucontext_t
)を利用できるようにします。これにより、クラッシュの原因を特定する際の診断情報が向上します。
src/pkg/runtime/signal_linux_arm.h
SIG_CODE0(info, ctxt)
マクロの追加は、シグナルハンドラがsi_code
フィールドを通じてシグナルのサブコード(例えば、SIGSEGV
がメモリへの無効なアクセスによって発生したのか、それとも他の原因によるものなのか)にアクセスできるようにします。これは、シグナル処理の粒度を高め、より具体的なエラーハンドリングを可能にします。
これらの変更は、GoのARMビルドが、低レベルのシステムイベント(I/Oイベントやシグナル)を正確かつ効率的に処理できるようにするために不可欠であり、Goが多様なハードウェア環境で信頼性の高いパフォーマンスを提供するための基盤を強化します。
関連リンク
参考にした情報源リンク
- Go's networking model, which is built around goroutines and the runtime's network poller, effectively utilizes
epoll
on Linux systems, including those running on ARM architecture. [1] - Epoll Overview:
epoll
is a Linux kernel system call that provides a highly efficient way to monitor multiple file descriptors (such as network sockets) for I/O events. [1] - Go's Netpoller: The Go runtime includes a component called the "netpoller" (network poller). This netpoller is responsible for integrating low-level OS polling mechanisms (like
epoll
on Linux,kqueue
on macOS/BSD, andIOCP
on Windows) with Go's goroutine scheduler. [2][3] - How Go Uses Epoll: When a Go program performs a network I/O operation, the Go runtime intercepts this call. If the operation cannot complete immediately, the goroutine performing the operation is "parked" (suspended), and the file descriptor is registered with the
epoll
instance. [1][2][3] - ARM Architecture Support: Go's runtime is designed to be cross-platform and supports various architectures, including ARM (specifically
arm64
). [4] os/signal
Package: Go programs interact with OS signals using theos/signal
package. [1][2][3][4][5][6][7][8][9]- Runtime-Installed Handlers: The Go runtime installs its own signal handlers for various signals. [10][11][3]
- Signal Stack: The Go runtime sets up an alternate "signal stack" where signal handlers can execute. [11]
- Synchronous vs. Asynchronous Signals: Synchronous signals are triggered by program errors. Asynchronous signals are sent externally. [10][3]
- Architecture-Specific Nuances: While the general design is portable, specific issues or behaviors related to signal handling can sometimes manifest on particular architectures like ARM. [12][13]
[1] medium.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQE662W3lj0QBpHJL1Q1VsccMgIkg9udE73dx2ovRIAJDJk62BnI_aUvBTIQtjmipnRbKLjBQsCmUEc5UQeuDBumQ2GvDPXWPXo5uxLBBvzygsNs1jrlEp7iSUSM1Xk_B87sy2iUBbgnQS3Q9s95mFtvqcHF3i6q4nekm4EJagCM09sI3_zHZGlYpGO_WWqHBpj_QLmRbrh9K3yPrpb9Y22dqOzWFAF_tGFPPWYE2lMzvQ==) [2] goperf.dev (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHmvSpbgCsPwVJoIVaU8g99fDiva3Cey8ttE-U95pMyurrwhvR3b7Go-tir2Oyz6KKdoYA-fPQR_3KF6TWoCSjzm6BLlYQufYW-Rp5RWegRKz_1hwfOSZh8NaMvMON1VsvY1Yg4nCozTm6sV-Pln2qRc1g==) [3] morsmachine.dk (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHoXvYKx7w8JH1VmdedSb9sLl95nkAkCbiXwdBRSKGdU3vl5Dv9l3UN6DoD_SvcTXPu88TX-QvluunHeIBOryhRSnri3IXnMW5XzaIl1R6xmysSdWBAoSxOpFdpkxsWdg==) [4] googlesource.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFJhPGso21F9iuXBt7Eh--EQKVSlofsuB-y6o-pXfXBwHxRZMCPGgSq7m57PsuIqsV31P5EMauYNMWGUAy4XYYQ-QuGoY_5ChNMrkiB3PUKAfUCPmORcb-YSigom3RMIcxvi5u7C5H7CkEBnx6vpxVj4A9OmjzG07Bd8=) [5] medium.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH46bkVsz_zA6G4fO7ZfGeKLmtsH7FR9LynJSvoJOXbKtZARCibqv999tnE7czpj6qE1ODkK_jxIarsSd3DeEeQ6CwhxGaHHEcaOs2RKzS_Qk5uHnfN-Mo8SQLK6yf0dyzWuTO-L7jH1HYVXV8EIEi8kAZKTZbyLXenJIqb9KaZ) [6] dev.to (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH40nYitdjCf3znpvUAXhXoDhfymSZcDYlOnjSQAaYA4NWGfzjGr95KWFYMuDbl1EJw0oA0cuy13E4aDdQZO4B4ix_AjQqdfw9iGCfNPqPRjclASBttfeAVwn-GLlpwlWG0upSw4fp_A78wrr_57b7PVZhy9xHC-9C_6JDB-0hFRiw=) [7] labex.io (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFcsMoi-c9HLjyVnlG4IPKxm_NUpor5f8qQYk1ZvSZDHZvzo_8aPi81jSjGhzg6plEj0S2ADdjEgAKeSOb5qXJH_cDQ3O4ZXKUfSAF4wFgBqWgoQqBOPnnB4f0PlWoNCksmhQXkIw92nR4wMTfK3m8ijzmL3tPW-0R-zXq6XQ5draoHhYc=) [8] stackoverflow.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGOBAP5zo0-sOYUyBI0OhyW6JmYOq32GNdpyMi0bTPc9BSCtd19kZL4j0MFQgcM_VxKjH78m1jcXggwLQGnXyBSZKZz0QqhDKr2YuGUy15tmP84PQ1PMB6h7-EmYGaLMwWBWtk7k1FeW3WFu7-Xl2sqp3491fWYqtqMvw==) [9] tutorialspoint.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQF2mmmcKl92FAEh_WYiI1n5OyWhuXLup6XvAwwdQkYn2guluEfyLbCw7hMndADviwHGJkjQF0rvw5c6Df5wOgusw1z64k2yHpRxIWSgwqH-AqvLUJrCa2MkdR0p2hSPjsrprzS0ryyA6vJQiw-fRQTanzdI6EDazirk) [10] go.dev (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEucW0IOtWsrMfjY7yKx0KFZqCO179NgzK825QencF7rr0dX-60nraoX8EjCM8ectCg4Vs3JSe10XUkeSPM8peBnEPCu8HiqGTiYobFjKSIAxOimamprs8=) [11] dotink.co (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGKcja0cqI-ndVWZPuKrd95H80wMyFhhD7inX5U9Gr_hvGiulovulJZvsc8HqPYBemyr1ydA25KIXGxea17HPQmMPtz4fvqqaHCxwXZOcsJMB9fzGOct_YZa-WC3BcMjQ==) [12] github.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQF0e1p4GHIsC9HlclPWiRNkKeIVbj1TnTBtWGjPB7BD3Pkf_dlXnyfNf6oyQ7LtJXx5-9ewbrxclevwFAEYl1fwCn_DCGjS5EADRykA1cvUYP6Fho5X27yFBt2mNxN84ChcIYxP) [13] github.com (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEpWLBvFxYJzPopAGcbKkessgoc8xif19rxCtzzHXfxAWrnZ1Epnmgdtzlh-BsINd-KR6pgzkRMEtmkaQFA0mKbwqAnWmsPm8WKEKQJ_rC441Nk1ypArvTGRl9WQMN_lDUA3HiZ)