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

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

このコミットは、Go言語のランタイムがOpenBSDオペレーティングシステムと連携するための定義(defs)を更新するものです。特に、OpenBSDの低レベルスレッド作成メカニズムである__tforkシステムコールに関連する構造体__tforkを追加し、既存の型定義を調整しています。これは、今後の変更で__tforkが必要となることを見越した準備作業です。

コミット

  • コミットハッシュ: 99fc28174369621cfe7a445cc4718fba0148745d
  • 作者: Joel Sing jsing@google.com
  • コミット日時: 2012年4月17日 火曜日 02:35:41 +1000

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

https://github.com/golang/go/commit/99fc28174369621cfe7a445cc4718fba0148745d

元コミット内容

runtime: update defs for openbsd

Update runtime defs for openbsd. Add struct __tfork, which will be
needed by an upcoming change.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/6007050

変更の背景

Go言語のランタイムは、各オペレーティングシステム(OS)の特性に合わせて低レベルなシステムコールやデータ構造を扱う必要があります。OpenBSDは、その堅牢性とセキュリティで知られるUNIX系OSであり、独自のシステムコールやカーネルの挙動を持つことがあります。

このコミットの主な背景は、OpenBSDにおける新しいスレッド作成メカニズムである__tforkシステムコールへの対応です。Goランタイムは、ゴルーチン(goroutine)のスケジューリングやシステムスレッドの管理のために、OSが提供するスレッド関連の機能を利用します。OpenBSDでは、従来のrfork()システムコールに代わり、より低レベルで効率的なカーネルスレッド作成のための__tforkが導入されました。

このコミットは、GoランタイムがOpenBSD上で正しく動作し、将来的に__tforkを利用したスレッド管理の改善を可能にするための準備として、必要なデータ構造と定数をGoのランタイム定義に追加しています。特に、__tforkシステムコールは、既存のプロセスのアドレス空間を共有する新しいカーネルスレッドを作成するために使用され、libpthread(POSIXスレッドライブラリ)によって内部的に利用されます。Goランタイムも同様に、この低レベルなインターフェースを直接、または間接的に利用することで、OpenBSD上でのゴルーチンとOSスレッドのマッピングを最適化しようとしていると考えられます。

前提知識の解説

  • Go言語のランタイム (runtime): Go言語のプログラムは、コンパイル時にGoランタイムと呼ばれる部分が組み込まれます。このランタイムは、ガベージコレクション、ゴルーチンのスケジューリング、チャネルの操作、システムコールとの連携など、Goプログラムの実行に必要な低レベルな機能を提供します。OS固有の機能にアクセスするために、各OS向けの定義ファイルやC言語で書かれたコードが含まれています。
  • cgo: Go言語とC言語のコードを相互に呼び出すためのツールです。GoのコードからCのライブラリを呼び出したり、CのコードからGoの関数を呼び出したりできます。このコミットでは、cgo -cdefsというコマンドが使われており、これはGoの構造体定義からC言語のヘッダーファイルを生成するために使用されます。これにより、GoランタイムがC言語で書かれたOS固有のコードと連携する際に、型定義の整合性を保つことができます。
  • OpenBSDの__tforkシステムコール: OpenBSDに特有の低レベルなシステムコールで、既存のプロセスのアドレス空間を共有する新しいカーネルスレッドを作成するために使用されます。これは、libpthreadなどのユーザーレベルスレッドライブラリが内部的に利用する主要なメカニズムです。__tforkは、スレッド制御ブロック(TCB)のアドレスやスタックアドレスなど、新しいスレッドの実行コンテキストを設定するための様々なパラメータを許可します。成功すると、新しく作成されたスレッドでは0を返し、呼び出し元のスレッドには新しいスレッドのIDを返します。OpenBSD 5.1で導入され、以前のrfork()システムコールに代わるものとして位置づけられています。
  • defs_openbsd.go: Goランタイム内でOpenBSD固有の定数や構造体をGoの型として定義しているファイルです。これらのGoの型は、cgo -cdefsによってC言語のヘッダーファイル(defs_openbsd_386.h, defs_openbsd_amd64.hなど)に変換され、C言語で書かれたランタイムコードから利用されます。
  • シグナルハンドリング: オペレーティングシステムは、プログラムの異常終了や外部からのイベント(例: Ctrl+C)をシグナルとしてプログラムに通知します。Goランタイムは、これらのシグナルを適切に処理し、ゴルーチンのパニックや終了、デバッグなどの機能を実現します。シグナルハンドリングには、シグナルスタック(Sigaltstack)やシグナルコンテキスト(Sigcontext)などのOS固有のデータ構造が関わってきます。

技術的詳細

このコミットは、主に以下のファイルに影響を与えています。

  1. src/pkg/runtime/defs_openbsd.go:

    • cgoコマンドの呼び出し方法が変更されました。以前はgodefsツールを使用していたようですが、go tool cgo -cdefsを使用するように更新されています。これは、Goのビルドシステムとcgoの統合が進んだことを示唆しています。
    • type Tfork C.struct___tforkという行が追加され、OpenBSDのstruct __tforkに対応するGoの型Tforkが定義されました。これは、Goランタイムが__tforkシステムコールを呼び出す際に、その引数として渡すデータ構造をGo側で表現するために必要です。
    • 既存の型定義の順序が変更され、Sigaltstack, Sigset, Sigcontext, Siginfo, Sigvalなどのシグナル関連の型が再配置されました。
    • sfxsave64usavefpuという型定義が削除されました。これらは以前、machine/fpu.hのインクルードを避けるためのハックとしてコメントされていましたが、今回の変更で不要になったか、より適切な方法で扱われるようになったと考えられます。
  2. src/pkg/runtime/defs_openbsd_386.h および src/pkg/runtime/defs_openbsd_amd64.h:

    • これらのファイルはdefs_openbsd.goからcgo -cdefsによって自動生成されるヘッダーファイルです。
    • ファイルの冒頭のコメントが// godefs -f -m32 defs.cから// Created by cgo -cdefs - DO NOT EDITに変更され、生成元が明確化されました。
    • struct Tforkの定義が追加されました。これは__tforkシステムコールが期待する構造体であり、tf_tcb(スレッド制御ブロック)、tf_tid(スレッドID)、tf_flags(フラグ)などのフィールドを持ちます。
    • 既存の定数(PROT_NONE, MAP_ANON, SA_SIGINFO, EINTR, 各種シグナル番号など)の定義が、より整形された形式(タブ区切り)に変更されました。これは、cgo -cdefsの出力フォーマットの変更によるものと考えられます。
    • Sigaltstack, Sigcontext, Siginfo, StackT, Timespec, Timeval, Itimervalなどの構造体定義が、フィールド名の前にbyteint32などの型が明示的に記述される形式に更新されました。また、パディングバイト(Pad_cgo_0)が追加されるなど、cgoによるアラインメントの調整が反映されています。
    • Sigvalの定義がunion Sigvalからtypedef byte Sigval[4];またはtypedef byte Sigval[8];(アーキテクチャによる)に変更されました。これは、Goのunionの扱いがCのunionと異なるため、cgoがより単純なバイト配列として扱うように変換した結果と考えられます。
    • sfxsave64usavefpuに関連する定義がこれらのヘッダーファイルからも削除されました。
  3. src/pkg/runtime/signal_openbsd_386.c および src/pkg/runtime/signal_openbsd_amd64.c:

    • runtime·signalstack関数内で、Sigaltstack構造体のss_spフィールドに値を代入する際に、st.ss_sp = (int8*)p;からst.ss_sp = p;へとキャストが削除されました。これは、defs_openbsd.goおよび生成されるヘッダーファイルでss_spの型がvoid *またはbyte *として適切に定義されたため、明示的なキャストが不要になったことを示しています。これにより、コードの可読性と型安全性が向上します。

これらの変更は、GoランタイムがOpenBSDの新しいスレッドモデルとより密接に連携し、将来的な機能拡張やパフォーマンス最適化の基盤を築くための重要なステップです。

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

src/pkg/runtime/defs_openbsd.go

--- a/src/pkg/runtime/defs_openbsd.go
+++ b/src/pkg/runtime/defs_openbsd.go
@@ -7,8 +7,8 @@
 /*
 Input to cgo.
 
-GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
-GOARCH=386 cgo -cdefs defs.go >386/defs.h
+GOARCH=amd64 go tool cgo -cdefs defs_openbsd.go >defs_openbsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_openbsd.go >defs_openbsd_386.h
 */
 
 package runtime
@@ -93,9 +93,12 @@ const (
 	ITIMER_PROF    = C.ITIMER_PROF
 )
 
+type Tfork C.struct___tfork
+
 type Sigaltstack C.struct_sigaltstack
-type Sigset C.sigset_t
+type Sigcontext C.struct_sigcontext
 type Siginfo C.siginfo_t
+type Sigset C.sigset_t
 type Sigval C.union_sigval
 
 type StackT C.stack_t
@@ -103,9 +106,3 @@ type StackT C.stack_t
 type Timespec C.struct_timespec
 type Timeval C.struct_timeval
 type Itimerval C.struct_itimerval
-\n-// This is a hack to avoid pulling in machine/fpu.h.\n-type sfxsave64 struct{}\n-type usavefpu struct{}\n-\n-type Sigcontext C.struct_sigcontext

src/pkg/runtime/defs_openbsd_386.h (一部抜粋、amd64も同様の変更)

--- a/src/pkg/runtime/defs_openbsd_386.h
+++ b/src/pkg/runtime/defs_openbsd_386.h
@@ -1,146 +1,148 @@
-// godefs -f -m32 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_openbsd.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
+\tPROT_NONE\t= 0x0,
+\tPROT_READ\t= 0x1,
+\tPROT_WRITE\t= 0x2,
+\tPROT_EXEC\t= 0x4,
 
-// Types
-#pragma pack on
+\tMAP_ANON\t= 0x1000,
+\tMAP_PRIVATE\t= 0x2,
+\tMAP_FIXED\t= 0x10,
 
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {\n-\tvoid *ss_sp;\n-\tuint32 ss_size;\n-\tint32 ss_flags;\n-};\n+\tSA_SIGINFO\t= 0x40,
+\tSA_RESTART\t= 0x2,
+\tSA_ONSTACK\t= 0x1,
+\n+\tEINTR\t= 0x4,
+\n+\tSIGHUP\t\t= 0x1,
...
+\tITIMER_PROF\t= 0x2,
+};
+\n+typedef struct Tfork Tfork;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigcontext Sigcontext;
 typedef struct Siginfo Siginfo;
-struct Siginfo {\n-\tint32 si_signo;\n-\tint32 si_code;\n-\tint32 si_errno;\n-\tbyte _data[116];\n+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+\n+#pragma pack on
+\n+struct Tfork {\n+\tbyte\t*tf_tcb;\n+\tint32\t*tf_tid;\n+\tint32\ttf_flags;\n };
 \n-typedef union Sigval Sigval;\n-union Sigval {\n-\tint32 sival_int;\n-\tvoid *sival_ptr;\n+struct Sigaltstack {\n+\tbyte\t*ss_sp;\n+\tuint32\tss_size;\n+\tint32\tss_flags;\n };
+struct Sigcontext {\n+\tint32\tsc_gs;\n+\tint32\tsc_fs;\n+\tint32\tsc_es;\n+\tint32\tsc_ds;\n+\tint32\tsc_edi;\n+\tint32\tsc_esi;\n+\tint32\tsc_ebp;\n+\tint32\tsc_ebx;\n+\tint32\tsc_edx;\n+\tint32\tsc_ecx;\n+\tint32\tsc_eax;\n+\tint32\tsc_eip;\n+\tint32\tsc_cs;\n+\tint32\tsc_eflags;\n+\tint32\tsc_esp;\n+\tint32\tsc_ss;\n+\tint32\tsc_onstack;\n+\tint32\tsc_mask;\n+\tint32\tsc_trapno;\n+\tint32\tsc_err;\n+\tvoid\t*sc_fpstate;\n+};
+struct Siginfo {\n+\tint32\tsi_signo;\n+\tint32\tsi_code;\n+\tint32\tsi_errno;\n+\tbyte\t_data[116];
+};
+typedef\tuint32\tSigset;
+typedef\tbyte\tSigval[4];
 \n-typedef struct StackT StackT;\n struct StackT {\n-\tvoid *ss_sp;\n-\tuint32 ss_size;\n-\tint32 ss_flags;\n+\tbyte\t*ss_sp;\n+\tuint32\tss_size;\n+\tint32\tss_flags;\n };
 \n-typedef struct Timespec Timespec;\n struct Timespec {\n-\tint32 tv_sec;\n-\tint32 tv_nsec;\n+\tint32\ttv_sec;\n+\tint32\ttv_nsec;\n };
-\n-typedef struct Timeval Timeval;\n struct Timeval {\n-\tint32 tv_sec;\n-\tint32 tv_usec;\n+\tint32\ttv_sec;\n+\tint32\ttv_usec;\n };
-\n-typedef struct Itimerval Itimerval;\n struct Itimerval {\n-\tTimeval it_interval;\n-\tTimeval it_value;\n+\tTimeval\tit_interval;\n+\tTimeval\tit_value;\n };
 \n-typedef void sfxsave64;\n \n-typedef void usavefpu;\n-\n-typedef struct Sigcontext Sigcontext;\
-struct Sigcontext {\n-\tint32 sc_gs;\n-\tint32 sc_fs;\n-\tint32 sc_es;\n-\tint32 sc_ds;\n-\tint32 sc_edi;\n-\tint32 sc_esi;\n-\tint32 sc_ebp;\n-\tint32 sc_ebx;\n-\tint32 sc_edx;\n-\tint32 sc_ecx;\n-\tint32 sc_eax;\n-\tint32 sc_eip;\n-\tint32 sc_cs;\n-\tint32 sc_eflags;\n-\tint32 sc_esp;\n-\tint32 sc_ss;\n-\tint32 sc_onstack;\n-\tint32 sc_mask;\n-\tint32 sc_trapno;\n-\tint32 sc_err;\n-\tusavefpu *sc_fpstate;\n-};\
 #pragma pack off

src/pkg/runtime/signal_openbsd_386.c (amd64も同様の変更)

--- a/src/pkg/runtime/signal_openbsd_386.c
+++ b/src/pkg/runtime/signal_openbsd_386.c
@@ -109,7 +109,7 @@ runtime·signalstack(byte *p, int32 n)
 {
 	Sigaltstack st;
 
-	st.ss_sp = (int8*)p;
+	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
 	runtime·sigaltstack(&st, nil);

コアとなるコードの解説

このコミットの核心は、GoランタイムがOpenBSDの低レベルなスレッド作成メカニズムである__tforkシステムコールと連携できるようにするための基盤を構築することにあります。

  1. Tfork構造体の追加: src/pkg/runtime/defs_openbsd.gotype Tfork C.struct___tforkが追加されたことで、GoのコードからC言語のstruct __tforkを型安全に参照できるようになりました。これにより、Goランタイムは__tforkシステムコールを呼び出す際に、その引数として必要な情報をGoの型として扱うことが可能になります。__tforkシステムコールは、新しいカーネルスレッドを作成する際に、スレッド制御ブロック(TCB)やスレッドID、各種フラグなどの情報を受け取ります。このTfork型は、これらの情報をGo側で表現するためのものです。

  2. cgo -cdefsへの移行とヘッダーファイルの更新: defs_openbsd.goのコメントが示すように、godefsツールからgo tool cgo -cdefsへの移行が行われました。これにより、Goの型定義からC言語のヘッダーファイルがより標準的な方法で生成されるようになりました。生成されたdefs_openbsd_386.hおよびdefs_openbsd_amd64.hには、struct Tforkの定義が追加され、GoランタイムのC言語部分が__tforkシステムコールと直接やり取りできるようになります。また、既存のシグナル関連の構造体(Sigaltstack, Sigcontext, Siginfoなど)の定義も、cgoの新しい生成ロジックに合わせて調整され、パディングバイトの追加や型名の明示などが行われています。これは、GoとCの間のメモリレイアウトの整合性を保つ上で重要です。

  3. シグナルハンドリングコードの簡素化: src/pkg/runtime/signal_openbsd_386.cおよびsrc/pkg/runtime/signal_openbsd_amd64.cにおけるst.ss_sp = (int8*)p;からst.ss_sp = p;への変更は、Sigaltstack構造体のss_spフィールドの型がGoの定義とCの定義でより一致するようになったことを示しています。これにより、不要なキャストが削除され、コードのクリーンアップと型安全性の向上が図られています。

これらの変更は、GoランタイムがOpenBSDの特定のシステムコールやデータ構造をより正確かつ効率的に利用するための基盤を強化し、将来的にOpenBSD上でのGoプログラムのパフォーマンスや安定性を向上させるための準備となります。

関連リンク

参考にした情報源リンク