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

[インデックス 1873] ファイルの概要

このコミットは、Goランタイムの初期段階における重要なリファクタリングを示しています。rt1.cという単一のファイルに集約されていたシグナルハンドリングとスレッド関連のロジックが、signal.cthread.cという2つの独立したファイルに分割されました。さらに、これらのファイルはアーキテクチャ固有のディレクトリ(amd64/)からOS固有のディレクトリ(darwin/linux/)に移動され、より汎用的な配置になりました。また、不要になったsys_types.hファイルが削除されています。

コミット

commit 8ee041dc24f46047f6cff0d61bd634d1cacfc380
Author: Russ Cox <rsc@golang.org>
Date:   Tue Mar 24 13:17:10 2009 -0700

    split rt1.c into signal.c and thread.c.
    move out of arch-specific directory: only os-specific.
    rm sys_types.h (unused).
    
    TBR=r
    OCL=26681
    CL=26681

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/8ee041dc24f46047f6cff0d61bd634d1cacfc380

元コミット内容

split rt1.c into signal.c and thread.c.
move out of arch-specific directory: only os-specific.
rm sys_types.h (unused).

TBR=r
OCL=26681
CL=26681

変更の背景

このコミットが行われた2009年3月は、Go言語がまだ一般に公開される前の、活発な開発初期段階にあたります。Goランタイムは、異なるオペレーティングシステム(OS)やCPUアーキテクチャ上でGoプログラムが効率的に動作するための基盤を提供します。初期のランタイムコードは、機能が単一のファイルに集約されていることがよくありました。

rt1.cというファイルは、Goランタイムの初期実装において、シグナルハンドリング(プログラムが外部イベントやエラーに応答するメカニズム)とスレッド管理(並行処理の基本単位)の両方を担当していました。しかし、これらの機能はそれぞれ独立した複雑なサブシステムであり、単一のファイルにまとまっていると、コードの可読性、保守性、および拡張性が低下します。

この変更の背景には、以下の目的があったと考えられます。

  1. コードのモジュール化と責務の分離: シグナル処理とスレッド処理は異なる関心事であり、それぞれを独立したファイルに分離することで、各ファイルの責務が明確になり、コードの理解が容易になります。
  2. 保守性の向上: 機能ごとにファイルが分かれることで、特定の機能にバグが見つかった場合や、新しい機能を追加する際に、影響範囲を限定しやすくなります。
  3. クロスプラットフォーム対応の改善: シグナルハンドリングやスレッド管理はOSに強く依存する部分です。amd64/rt1.cのようなアーキテクチャ固有のディレクトリから、darwin/linux/といったOS固有のディレクトリに移動することで、OSごとの実装の違いをより明確に管理できるようになります。これにより、新しいOSへの対応や既存OSの特定の挙動への対応が容易になります。
  4. 不要なコードの削除: 開発が進むにつれて、初期に作成されたファイルや定義が不要になることがあります。sys_types.hの削除は、コードベースのクリーンアップと効率化の一環です。

これらの変更は、Goランタイムがより堅牢で、スケーラブルで、将来の機能拡張に対応できるような基盤を築くための、初期の重要なステップでした。

前提知識の解説

このコミットを理解するためには、以下の前提知識が必要です。

  1. Goランタイム (Go Runtime): Goプログラムは、Goランタイムと呼ばれる軽量な実行環境上で動作します。Goランタイムは、ガベージコレクション、スケジューラ(goroutineの管理)、メモリ管理、システムコールインターフェース、シグナルハンドリングなど、Goプログラムの実行に必要な低レベルの機能を提供します。C言語で書かれた部分が多く、OSやアーキテクチャに依存する処理を抽象化しています。

  2. シグナルハンドリング (Signal Handling): シグナルは、オペレーティングシステムがプロセスに送信する非同期通知です。これらは、プログラムの異常終了(例: セグメンテーション違反、ゼロ除算)、外部イベント(例: Ctrl+Cによる割り込み)、タイマーの期限切れなど、様々な状況で発生します。プログラムはシグナルを受信した際に、デフォルトの動作(プロセス終了など)を実行するか、カスタムのシグナルハンドラ関数を登録して特定の処理を行うことができます。Goランタイムは、Goプログラムがシグナルを適切に処理し、クラッシュを回避したり、デバッグ情報(スタックトレースなど)を出力したりするために、独自のシグナルハンドリングメカニズムを持っています。

  3. スレッド (Threads): スレッドは、プロセス内で実行される独立した実行パスです。同じプロセス内のスレッドはメモリ空間を共有するため、効率的なデータ共有が可能です。Go言語のgoroutineは、OSスレッド上で多重化される軽量なスレッドであり、GoランタイムのスケジューラがgoroutineをOSスレッドにマッピングして実行を管理します。このコミットにおける「スレッド」は、Goランタイムが内部的に使用するOSスレッドの管理に関連する部分を指します。

  4. Makefile: Makefileは、ソフトウェアプロジェクトのビルドプロセスを自動化するためのファイルです。makeコマンドによって解釈され、ソースファイルのコンパイル順序、依存関係、リンク方法などを定義します。このコミットでは、新しいファイルが追加されたため、ビルドプロセスにそれらを含めるようにMakefileが更新されています。

  5. amd64darwinlinux: これらはそれぞれ、CPUアーキテクチャとオペレーティングシステムを指します。

    • amd64: x86-64ビットアーキテクチャ。
    • darwin: AppleのmacOS(旧OS X)のカーネル。
    • linux: Linuxカーネル。 Goランタイムは、これらの異なる環境で動作するために、それぞれの環境に特化したコードを持つ必要があります。
  6. rt1.c: Goランタイムの初期段階で存在したC言語のソースファイルで、シグナルハンドリングやスレッド関連の低レベルな処理が含まれていました。このコミットで分割・リネームの対象となっています。

  7. sys_types.h: システムコールやデータ型定義など、システムレベルの型定義を含むヘッダーファイル。このコミットでは不要と判断され削除されました。

技術的詳細

このコミットの技術的な詳細は、主に以下の3つの側面から分析できます。

  1. rt1.cの分割: 元のrt1.cファイルは、シグナル処理とスレッド処理の両方のロジックを含んでいました。このコミットでは、これらの機能が明確に分離され、signal.cthread.cという新しいファイルにそれぞれ移動されました。

    • signal.c: シグナルハンドラの登録、シグナル情報の取得、スタックトレースの出力など、シグナル関連の低レベルな処理が含まれるようになりました。DarwinとLinuxでそれぞれ異なる実装が提供されています。
    • thread.c: スレッドの作成、管理、同期プリミティブ(セマフォなど)の初期化といった、スレッド関連の処理が含まれるようになりました。
  2. ディレクトリ構造の変更: 元のrt1.cは、src/runtime/darwin/amd64/rt1.csrc/runtime/linux/amd64/rt1.cのように、OSとアーキテクチャの両方に特化したディレクトリに配置されていました。この変更により、signal.cthread.csrc/runtime/darwin/src/runtime/linux/といったOS固有のディレクトリに移動されました。 これは、シグナルハンドリングやスレッド管理の多くの側面が、CPUアーキテクチャよりもOSのシステムコールインターフェースに強く依存するという認識に基づいています。例えば、sigactionsigaltstackのようなシステムコールはOSによって提供され、そのAPIはOS間で大きく異なりますが、同じOS内であれば異なるアーキテクチャでも共通のインターフェースを持つことが多いです。この変更により、コードの再利用性が向上し、OSごとの差異をより効率的に管理できるようになります。

  3. sys_types.hの削除: src/runtime/sys_types.hは、条件付きコンパイル(#ifdef amd64_linuxなど)を使用して、特定のOS/アーキテクチャ固有のヘッダーファイル(amd64_linux.hamd64_darwin.h)をインクルードしていました。このコミットでsys_types.hが削除されたのは、おそらく、新しいsignal.cthread.cが直接必要なヘッダーをインクルードするようになり、この抽象化レイヤーが不要になったためと考えられます。これは、依存関係をより明示的にし、不要な間接参照を排除するクリーンアップの一環です。

これらの変更は、Goランタイムの内部構造をより整理し、将来の拡張や異なるプラットフォームへの移植を容易にするための基盤を強化するものです。特に、シグナルとスレッドという並行処理の根幹をなす部分の分離は、Goの並行処理モデル(goroutineとチャネル)を支えるランタイムの安定性と効率性を高める上で不可欠なステップでした。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更は、以下のファイルに集中しています。

  1. src/runtime/Makefile:

    • rt1.$Oのビルド対象からの削除。
    • signal.$Othread.$Oのビルド対象への追加。 これにより、ビルドシステムが新しいファイル構成を認識し、正しくコンパイル・リンクされるようになります。
  2. src/runtime/darwin/signal.c (新規追加):

    • Darwin(macOS)環境におけるシグナルハンドリングのロジックが実装されています。
    • _STRUCT_X86_THREAD_STATE64などのDarwin固有の構造体定義が含まれます。
    • print_thread_state関数(デバッグ目的でスレッドの状態レジスタを出力)が定義されています。
    • sighandler関数(実際のシグナル処理ロジック、スタックトレース出力など)が定義されています。
    • initsig関数(シグナルハンドラの初期設定)が定義されています。
    • signalstack関数(代替シグナルスタックの設定)が定義されています。
  3. src/runtime/darwin/{amd64/rt1.c => thread.c} (リネームと内容変更):

    • 元のrt1.cからシグナル関連のコードが削除され、スレッド関連のコードのみが残されました。
    • ファイル名がthread.cに変更され、OS固有のディレクトリに移動されました。
    • initsema(セマフォの初期化)やxadd(アトミック加算)といった、スレッド同期に関連するヘルパー関数が含まれています。
  4. src/runtime/linux/signal.c (新規追加):

    • Linux環境におけるシグナルハンドリングのロジックが実装されています。
    • _fpstate, sigcontext, ucontextなどのLinux固有の構造体定義が含まれます。
    • print_sigcontext関数(デバッグ目的でシグナルコンテキストを出力)が定義されています。
    • sighandler関数(実際のシグナル処理ロジック、スタックトレース出力など)が定義されています。
    • initsig関数(シグナルハンドラの初期設定)が定義されています。
    • signalstack関数(代替シグナルスタックの設定)が定義されています。
  5. src/runtime/linux/{amd64/rt1.c => thread.c} (リネームと内容変更):

    • 元のrt1.cからシグナル関連のコードが削除され、スレッド関連のコードのみが残されました。
    • ファイル名がthread.cに変更され、OS固有のディレクトリに移動されました。
    • Linuxのfutex(Fast Userspace muTEX)に関するコメントが残っており、スレッド同期の低レベルな実装に関連する部分であることが示唆されます。
  6. src/runtime/sys_types.h (削除):

    • このヘッダーファイルは完全に削除されました。これにより、各OS/アーキテクチャ固有のヘッダーは、それらを必要とするファイルによって直接インクルードされるようになりました。

これらの変更により、Goランタイムのシグナルとスレッドに関するコードが、OSごとに整理され、よりモジュール化された構造になりました。

コアとなるコードの解説

このコミットの核心は、GoランタイムがOSからのシグナルをどのように処理し、また内部的なスレッドをどのように管理するかという、低レベルなメカニズムの再編成にあります。

シグナルハンドリング (signal.c): Goランタイムは、プログラムのクラッシュ(例: セグメンテーション違反)や外部からの割り込み(例: Ctrl+C)といったシグナルを捕捉し、適切に処理する必要があります。signal.cファイルは、このシグナル処理のOS固有の実装を含んでいます。

  • sighandler関数: これは、OSがシグナルをプロセスに送信したときに呼び出されるGoランタイムの主要なシグナルハンドラです。
    • panickingフラグをチェックし、既にパニック状態であれば二重パニックを防ぎます。
    • シグナル番号と、シグナルが発生したアドレス(info->si_addr)やプログラムカウンタ(ss->__ripまたはsc->rip)などの情報を出力します。
    • gotraceback()が真の場合、traceback関数を呼び出して現在のgoroutineのスタックトレースを出力します。これはデバッグ時に非常に役立ちます。
    • 最終的にsys_Exit(2)を呼び出してプロセスを終了させます。これは、Goランタイムが捕捉した致命的なシグナルに対するデフォルトの挙動です。
  • initsig関数: Goプログラムの起動時に、Goランタイムが捕捉すべきシグナルに対してカスタムのシグナルハンドラ(sighandlerまたはsigignore)を登録します。
    • sigactionシステムコール(またはrt_sigaction)を使用して、シグナルハンドラ関数、シグナルマスク、およびフラグ(SA_SIGINFO, SA_ONSTACK, SA_RESTARTなど)を設定します。
    • SA_ONSTACKフラグは、シグナルハンドラが通常のスタックではなく、代替シグナルスタック(signalstackで設定)で実行されることを保証し、スタックオーバーフローによるシグナル処理の失敗を防ぎます。
    • sigtrampはアセンブリルーチンで、シグナルハンドラを呼び出す前にレジスタの状態を保存し、スタックを適切に設定する役割を担います。

スレッド管理 (thread.c): Goランタイムは、goroutineをOSスレッド上で実行するために、OSスレッドの作成、管理、および同期を行う必要があります。thread.cファイルは、これらのスレッド関連の低レベルな処理を含んでいます。

  • initsema関数 (Darwin): Machカーネルのセマフォ(mach_semcreate)を初期化します。これは、Goランタイムが内部的な同期プリミティブとして使用するものです。cas (Compare-And-Swap) 操作を使用して、複数のスレッドが同時にセマフォを初期化しようとした場合の競合状態を防ぎます。
  • xadd関数 (Darwin): アトミックな加算操作を実装しています。これは、複数のスレッドから共有変数に安全にアクセスするために使用されます。
  • Linux版のthread.cには、futex(Fast Userspace muTEX)に関するコメントがあり、Linuxにおける低レベルなスレッド同期メカニズムへの言及が見られます。

Makefileの変更: Makefileの変更は、これらの新しいファイルがGoランタイムのビルドプロセスに正しく組み込まれることを保証します。rt1.$Oが削除され、signal.$Othread.$Oが追加されることで、ビルドシステムは分割された新しいモジュールをコンパイルし、最終的なランタイムバイナリにリンクするようになります。

このコミットは、Goランタイムの初期設計において、シグナルとスレッドというOSに密接に関連する機能を、よりクリーンで保守性の高い方法で分離し、Goの並行処理モデルの基盤を強化した重要な一歩と言えます。

関連リンク

  • Go言語の公式ドキュメント: https://go.dev/doc/
  • Goランタイムのソースコード(現在のバージョン): https://github.com/golang/go/tree/master/src/runtime
  • Goのシグナルハンドリングに関する議論(GoのIssueトラッカーなど): Goの初期のシグナルハンドリングに関する具体的なIssueは特定が難しいですが、go.dev/issuesignalruntimeを検索すると関連する議論が見つかる可能性があります。

参考にした情報源リンク

  • Go言語のソースコード(GitHub): https://github.com/golang/go
  • Go言語のコミット履歴: https://github.com/golang/go/commits/master
  • オペレーティングシステムのシグナルに関する一般的な情報(例: Linux man pages for signal(7), sigaction(2), ucontext(3)など)
  • Machカーネルのセマフォに関する情報(Darwin固有のシステムプログラミングドキュメントなど)
  • futexに関する情報(Linuxカーネルのドキュメントなど)
  • Go言語の初期開発に関するブログ記事やメーリングリストのアーカイブ(Goがオープンソース化される前の情報を見つけるのは難しい場合がありますが、GoのブログやGoogle Groupsのgolang-nutsアーカイブなどが参考になる可能性があります)。

[インデックス 1873] ファイルの概要

このコミットは、Goランタイムの初期段階における重要なリファクタリングを示しています。rt1.cという単一のファイルに集約されていたシグナルハンドリングとスレッド関連のロジックが、signal.cthread.cという2つの独立したファイルに分割されました。さらに、これらのファイルはアーキテクチャ固有のディレクトリ(amd64/)からOS固有のディレクトリ(darwin/linux/)に移動され、より汎用的な配置になりました。また、不要になったsys_types.hファイルが削除されています。

コミット

commit 8ee041dc24f46047f6cff0d61bd634d1cacfc380
Author: Russ Cox <rsc@golang.org>
Date:   Tue Mar 24 13:17:10 2009 -0700

    split rt1.c into signal.c and thread.c.
    move out of arch-specific directory: only os-specific.
    rm sys_types.h (unused).
    
    TBR=r
    OCL=26681
    CL=26681

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/8ee041dc24f46047f6cff0d61bd634d1cacfc380

元コミット内容

split rt1.c into signal.c and thread.c.
move out of arch-specific directory: only os-specific.
rm sys_types.h (unused).

TBR=r
OCL=26681
CL=26681

変更の背景

このコミットが行われた2009年3月は、Go言語がまだ一般に公開される前の、活発な開発初期段階にあたります。Goランタイムは、異なるオペレーティングシステム(OS)やCPUアーキテクチャ上でGoプログラムが効率的に動作するための基盤を提供します。初期のランタイムコードは、機能が単一のファイルに集約されていることがよくありました。

rt1.cというファイルは、Goランタイムの初期実装において、シグナルハンドリング(プログラムが外部イベントやエラーに応答するメカニズム)とスレッド管理(並行処理の基本単位)の両方を担当していました。しかし、これらの機能はそれぞれ独立した複雑なサブシステムであり、単一のファイルにまとまっていると、コードの可読性、保守性、および拡張性が低下します。

この変更の背景には、以下の目的があったと考えられます。

  1. コードのモジュール化と責務の分離: シグナル処理とスレッド処理は異なる関心事であり、それぞれを独立したファイルに分離することで、各ファイルの責務が明確になり、コードの理解が容易になります。
  2. 保守性の向上: 機能ごとにファイルが分かれることで、特定の機能にバグが見つかった場合や、新しい機能を追加する際に、影響範囲を限定しやすくなります。
  3. クロスプラットフォーム対応の改善: シグナルハンドリングやスレッド管理はOSに強く依存する部分です。amd64/rt1.cのようなアーキテクチャ固有のディレクトリから、darwin/linux/といったOS固有のディレクトリに移動することで、OSごとの実装の違いをより明確に管理できるようになります。これにより、新しいOSへの対応や既存OSの特定の挙動への対応が容易になります。
  4. 不要なコードの削除: 開発が進むにつれて、初期に作成されたファイルや定義が不要になることがあります。sys_types.hの削除は、コードベースのクリーンアップと効率化の一環です。

これらの変更は、Goランタイムがより堅牢で、スケーラブルで、将来の機能拡張に対応できるような基盤を築くための、初期の重要なステップでした。

前提知識の解説

このコミットを理解するためには、以下の前提知識が必要です。

  1. Goランタイム (Go Runtime): Goプログラムは、Goランタイムと呼ばれる軽量な実行環境上で動作します。Goランタイムは、ガベージコレクション、スケジューラ(goroutineの管理)、メモリ管理、システムコールインターフェース、シグナルハンドリングなど、Goプログラムの実行に必要な低レベルの機能を提供します。C言語で書かれた部分が多く、OSやアーキテクチャに依存する処理を抽象化しています。

  2. シグナルハンドリング (Signal Handling): シグナルは、オペレーティングシステムがプロセスに送信する非同期通知です。これらは、プログラムの異常終了(例: セグメンテーション違反、ゼロ除算)、外部イベント(例: Ctrl+Cによる割り込み)、タイマーの期限切れなど、様々な状況で発生します。プログラムはシグナルを受信した際に、デフォルトの動作(プロセス終了など)を実行するか、カスタムのシグナルハンドラ関数を登録して特定の処理を行うことができます。Goランタイムは、Goプログラムがシグナルを適切に処理し、クラッシュを回避したり、デバッグ情報(スタックトレースなど)を出力したりするために、独自のシグナルハンドリングメカニズムを持っています。

  3. スレッド (Threads): スレッドは、プロセス内で実行される独立した実行パスです。同じプロセス内のスレッドはメモリ空間を共有するため、効率的なデータ共有が可能です。Go言語のgoroutineは、OSスレッド上で多重化される軽量なスレッドであり、GoランタイムのスケジューラがgoroutineをOSスレッドにマッピングして実行を管理します。このコミットにおける「スレッド」は、Goランタイムが内部的に使用するOSスレッドの管理に関連する部分を指します。

  4. Makefile: Makefileは、ソフトウェアプロジェクトのビルドプロセスを自動化するためのファイルです。makeコマンドによって解釈され、ソースファイルのコンパイル順序、依存関係、リンク方法などを定義します。このコミットでは、新しいファイルが追加されたため、ビルドプロセスにそれらを含めるようにMakefileが更新されています。

  5. amd64darwinlinux: これらはそれぞれ、CPUアーキテクチャとオペレーティングシステムを指します。

    • amd64: x86-64ビットアーキテクチャ。
    • darwin: AppleのmacOS(旧OS X)のカーネル。
    • linux: Linuxカーネル。 Goランタイムは、これらの異なる環境で動作するために、それぞれの環境に特化したコードを持つ必要があります。
  6. rt1.c: Goランタイムの初期段階で存在したC言語のソースファイルで、シグナルハンドリングやスレッド関連の低レベルな処理が含まれていました。このコミットで分割・リネームの対象となっています。

  7. sys_types.h: システムコールやデータ型定義など、システムレベルの型定義を含むヘッダーファイル。このコミットでは不要と判断され削除されました。

技術的詳細

このコミットの技術的な詳細は、主に以下の3つの側面から分析できます。

  1. rt1.cの分割: 元のrt1.cファイルは、シグナル処理とスレッド処理の両方のロジックを含んでいました。このコミットでは、これらの機能が明確に分離され、signal.cthread.cという新しいファイルにそれぞれ移動されました。

    • signal.c: シグナルハンドラの登録、シグナル情報の取得、スタックトレースの出力など、シグナル関連の低レベルな処理が含まれるようになりました。DarwinとLinuxでそれぞれ異なる実装が提供されています。
    • thread.c: スレッドの作成、管理、同期プリミティブ(セマフォなど)の初期化といった、スレッド関連の処理が含まれるようになりました。
  2. ディレクトリ構造の変更: 元のrt1.cは、src/runtime/darwin/amd64/rt1.csrc/runtime/linux/amd64/rt1.cのように、OSとアーキテクチャの両方に特化したディレクトリに配置されていました。この変更により、signal.cthread.csrc/runtime/darwin/src/runtime/linux/といったOS固有のディレクトリに移動されました。 これは、シグナルハンドリングやスレッド管理の多くの側面が、CPUアーキテクチャよりもOSのシステムコールインターフェースに強く依存するという認識に基づいています。例えば、sigactionsigaltstackのようなシステムコールはOSによって提供され、そのAPIはOS間で大きく異なりますが、同じOS内であれば異なるアーキテクチャでも共通のインターフェースを持つことが多いです。この変更により、コードの再利用性が向上し、OSごとの差異をより効率的に管理できるようになります。

  3. sys_types.hの削除: src/runtime/sys_types.hは、条件付きコンパイル(#ifdef amd64_linuxなど)を使用して、特定のOS/アーキテクチャ固有のヘッダーファイル(amd64_linux.hamd64_darwin.h)をインクルードしていました。このコミットでsys_types.hが削除されたのは、おそらく、新しいsignal.cthread.cが直接必要なヘッダーをインクルードするようになり、この抽象化レイヤーが不要になったためと考えられます。これは、依存関係をより明示的にし、不要な間接参照を排除するクリーンアップの一環です。

これらの変更は、Goランタイムの内部構造をより整理し、将来の拡張や異なるプラットフォームへの移植を容易にするための基盤を強化するものです。特に、シグナルとスレッドという並行処理の根幹をなす部分の分離は、Goの並行処理モデル(goroutineとチャネル)を支えるランタイムの安定性と効率性を高める上で不可欠なステップでした。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更は、以下のファイルに集中しています。

  1. src/runtime/Makefile:

    • rt1.$Oのビルド対象からの削除。
    • signal.$Othread.$Oのビルド対象への追加。 これにより、ビルドシステムが新しいファイル構成を認識し、正しくコンパイル・リンクされるようになります。
  2. src/runtime/darwin/signal.c (新規追加):

    • Darwin(macOS)環境におけるシグナルハンドリングのロジックが実装されています。
    • _STRUCT_X86_THREAD_STATE64などのDarwin固有の構造体定義が含まれます。
    • print_thread_state関数(デバッグ目的でスレッドの状態レジスタを出力)が定義されています。
    • sighandler関数(実際のシグナル処理ロジック、スタックトレース出力など)が定義されています。
    • initsig関数(シグナルハンドラの初期設定)が定義されています。
    • signalstack関数(代替シグナルスタックの設定)が定義されています。
  3. src/runtime/darwin/{amd64/rt1.c => thread.c} (リネームと内容変更):

    • 元のrt1.cからシグナル関連のコードが削除され、スレッド関連のコードのみが残されました。
    • ファイル名がthread.cに変更され、OS固有のディレクトリに移動されました。
    • initsema(セマフォの初期化)やxadd(アトミック加算)といった、スレッド同期に関連するヘルパー関数が含まれています。
  4. src/runtime/linux/signal.c (新規追加):

    • Linux環境におけるシグナルハンドリングのロジックが実装されています。
    • _fpstate, sigcontext, ucontextなどのLinux固有の構造体定義が含まれます。
    • print_sigcontext関数(デバッグ目的でシグナルコンテキストを出力)が定義されています。
    • sighandler関数(実際のシグナル処理ロジック、スタックトレース出力など)が定義されています。
    • initsig関数(シグナルハンドラの初期設定)が定義されています。
    • signalstack関数(代替シグナルスタックの設定)が定義されています。
  5. src/runtime/linux/{amd64/rt1.c => thread.c} (リネームと内容変更):

    • 元のrt1.cからシグナル関連のコードが削除され、スレッド関連のコードのみが残されました。
    • ファイル名がthread.cに変更され、OS固有のディレクトリに移動されました。
    • Linuxのfutex(Fast Userspace muTEX)に関するコメントが残っており、スレッド同期の低レベルな実装に関連する部分であることが示唆されます。
  6. src/runtime/sys_types.h (削除):

    • このヘッダーファイルは完全に削除されました。これにより、各OS/アーキテクチャ固有のヘッダーは、それらを必要とするファイルによって直接インクルードされるようになりました。

これらの変更により、Goランタイムのシグナルとスレッドに関するコードが、OSごとに整理され、よりモジュール化された構造になりました。

コアとなるコードの解説

このコミットの核心は、GoランタイムがOSからのシグナルをどのように処理し、また内部的なスレッドをどのように管理するかという、低レベルなメカニズムの再編成にあります。

シグナルハンドリング (signal.c): Goランタイムは、プログラムのクラッシュ(例: セグメンテーション違反)や外部からの割り込み(例: Ctrl+C)といったシグナルを捕捉し、適切に処理する必要があります。signal.cファイルは、このシグナル処理のOS固有の実装を含んでいます。

  • sighandler関数: これは、OSがシグナルをプロセスに送信したときに呼び出されるGoランタイムの主要なシグナルハンドラです。
    • panickingフラグをチェックし、既にパニック状態であれば二重パニックを防ぎます。
    • シグナル番号と、シグナルが発生したアドレス(info->si_addr)やプログラムカウンタ(ss->__ripまたはsc->rip)などの情報を出力します。
    • gotraceback()が真の場合、traceback関数を呼び出して現在のgoroutineのスタックトレースを出力します。これはデバッグ時に非常に役立ちます。
    • 最終的にsys_Exit(2)を呼び出してプロセスを終了させます。これは、Goランタイムが捕捉した致命的なシグナルに対するデフォルトの挙動です。
  • initsig関数: Goプログラムの起動時に、Goランタイムが捕捉すべきシグナルに対してカスタムのシグナルハンドラ(sighandlerまたはsigignore)を登録します。
    • sigactionシステムコール(またはrt_sigaction)を使用して、シグナルハンドラ関数、シグナルマスク、およびフラグ(SA_SIGINFO, SA_ONSTACK, SA_RESTARTなど)を設定します。
    • SA_ONSTACKフラグは、シグナルハンドラが通常のスタックではなく、代替シグナルスタック(signalstackで設定)で実行されることを保証し、スタックオーバーフローによるシグナル処理の失敗を防ぎます。
    • sigtrampはアセンブリルーチンで、シグナルハンドラを呼び出す前にレジスタの状態を保存し、スタックを適切に設定する役割を担います。

スレッド管理 (thread.c): Goランタイムは、goroutineをOSスレッド上で実行するために、OSスレッドの作成、管理、および同期を行う必要があります。thread.cファイルは、これらのスレッド関連の低レベルな処理を含んでいます。

  • initsema関数 (Darwin): Machカーネルのセマフォ(mach_semcreate)を初期化します。これは、Goランタイムが内部的な同期プリミティブとして使用するものです。cas (Compare-And-Swap) 操作を使用して、複数のスレッドが同時にセマフォを初期化しようとした場合の競合状態を防ぎます。
  • xadd関数 (Darwin): アトミックな加算操作を実装しています。これは、複数のスレッドから共有変数に安全にアクセスするために使用されます。
  • Linux版のthread.cには、futex(Fast Userspace muTEX)に関するコメントがあり、Linuxにおける低レベルなスレッド同期メカニズムへの言及が見られます。

Makefileの変更: Makefileの変更は、これらの新しいファイルがGoランタイムのビルドプロセスに正しく組み込まれることを保証します。rt1.$Oが削除され、signal.$Othread.$Oが追加されることで、ビルドシステムは分割された新しいモジュールをコンパイルし、最終的なランタイムバイナリにリンクするようになります。

このコミットは、Goランタイムの初期設計において、シグナルとスレッドというOSに密接に関連する機能を、よりクリーンで保守性の高い方法で分離し、Goの並行処理モデルの基盤を強化した重要な一歩と言えます。

関連リンク

  • Go言語の公式ドキュメント: https://go.dev/doc/
  • Goランタイムのソースコード(現在のバージョン): https://github.com/golang/go/tree/master/src/runtime
  • Goのシグナルハンドリングに関する議論(GoのIssueトラッカーなど): Goの初期のシグナルハンドリングに関する具体的なIssueは特定が難しいですが、go.dev/issuesignalruntimeを検索すると関連する議論が見つかる可能性があります。

参考にした情報源リンク

  • Go言語のソースコード(GitHub): https://github.com/golang/go
  • Go言語のコミット履歴: https://github.com/golang/go/commits/master
  • オペレーティングシステムのシグナルに関する一般的な情報(例: Linux man pages for signal(7), sigaction(2), ucontext(3)など)
  • Machカーネルのセマフォに関する情報(Darwin固有のシステムプログラミングドキュメントなど)
  • futexに関する情報(Linuxカーネルのドキュメントなど)
  • Go言語の初期開発に関するブログ記事やメーリングリストのアーカイブ(Goがオープンソース化される前の情報を見つけるのは難しい場合がありますが、GoのブログやGoogle Groupsのgolang-nutsアーカイブなどが参考になる可能性があります)。
  • Web検索結果: "Go runtime early development signal handling threading rt1.c"