Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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イベント通知メカニズムであり、多数のファイルディスクリプタ(ネットワークソケットなど)を効率的に監視するために使用されます。selectpollといった従来のメカニズムと比較して、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つの技術的な問題に対処しています。

  1. 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)を保持します。AddFDStopWaitingDelFDWaitFDといったメソッドは、epoll_ctlシステムコールを使用してFDの追加、変更、削除を行い、epoll_waitシステムコールを使用してイベントを待機します。特に、+build armディレクティブは、このファイルがARMアーキテクチャ向けにのみビルドされることを示しており、他のアーキテクチャでは異なるポーリングメカニズムが使用される可能性があることを意味します。

  2. ランタイム再編成におけるタイプミス修正: Goランタイムのコードベースは複雑であり、大規模な再編成("runtime reorg")は、既存のコードに意図しない変更やタイプミスを導入する可能性があります。このコミットでは、src/pkg/runtime/defs_linux_arm.hsrc/pkg/runtime/signal_arm.csrc/pkg/runtime/signal_linux_arm.h の3つのファイルでタイプミスが修正されています。

    • src/pkg/runtime/defs_linux_arm.h: このファイルは、ARM Linux環境におけるランタイムの定義(定数など)を含んでいます。修正では、ENOMEMEAGAINというエラーコードの定義が追加されています。これらは、システムコールがメモリ不足やリソースの一時的な不足を報告する際に使用される重要な定数です。以前のコミットでこれらの定義が欠落していたか、誤っていた可能性があります。
    • 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.EpollCtlEPOLL_CTL_ADD または EPOLL_CTL_MOD オペレーションで使用して、FDをepollインスタンスに追加または既存のFDのイベントを更新します。EPOLLONESHOT フラグは、イベントが一度発生したら自動的に監視を停止するかどうかを制御します。
  • WaitFD メソッド: syscall.EpollWait を呼び出して、イベントが発生するまでブロックします。イベントが発生すると、waitEventBuf に格納され、処理のために返されます。このメカニズムにより、Goランタイムは多数のネットワーク接続を効率的に処理できます。
  • StopWaiting および DelFD メソッド: syscall.EpollCtlEPOLL_CTL_MOD または EPOLL_CTL_DEL オペレーションで使用して、FDの監視を停止または削除します。

このファイルがARMビルドに不可欠であるということは、ARM環境におけるGoのネットワークスタックが、他のアーキテクチャとは異なる、または特定のepoll関連の挙動に依存していることを示唆しています。

src/pkg/runtime/defs_linux_arm.h

ENOMEMEAGAINの追加は、Goランタイムがシステムコールからの特定のエラーコードを認識し、適切に処理できるようにするために重要です。これらのエラーは、リソースの枯渇や一時的な利用不可を示すものであり、Goプログラムがこれらの状況に適切に対応することで、より堅牢になります。

src/pkg/runtime/signal_arm.c

シグナルハンドリングの変更は、ARMアーキテクチャにおけるシグナル情報の正確な取得と処理を保証します。

  • gp->sigcode1 = SIG_FAULT(info, ctxt); への変更は、シグナルによって引き起こされたフォルト(例えば、メモリ違反)に関する詳細な情報を取得するためのより正確な方法を提供します。これは、デバッグやクラッシュレポートの生成において非常に重要です。
  • runtime·dumpregs(info, ctxt); への変更は、シグナル発生時のCPUレジスタの状態をダンプする際に、より完全なコンテキスト情報(siginfo_tucontext_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, and IOCP 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 the os/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)