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

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

このコミットは、Go言語のランタイムにおけるCgo関連のシンボル命名規則を統一することを目的としています。特に、runtime/cgo パッケージ内の関数や変数名のプレフィックスを _cgo_ に変更し、一貫性のない命名を修正しています。また、将来的に他のファイルから参照される予定の関数から static キーワードを削除しています。

コミット

commit f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e
Author: Russ Cox <rsc@golang.org>
Date:   Thu Feb 28 16:24:38 2013 -0500

    runtime/cgo: make symbol naming consistent

    The naming in this package is a disaster.
    Make it all consistent.

    Remove some 'static' from functions that will
    be referred to from other files soon.

    This CL is purely renames using global search and replace.

    Submitting separately so that real changes will not
    be drowned out by these renames in future CLs.

    TBR=iant
    CC=golang-dev
    https://golang.org/cl/7416046

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

https://github.com/golang/go/commit/f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e

元コミット内容

runtime/cgo: make symbol naming consistent

The naming in this package is a disaster.
Make it all consistent.

Remove some 'static' from functions that will
be referred to from other files soon.

This CL is purely renames using global search and replace.

Submitting separately so that real changes will not
be drowned out by these renames in future CLs.

TBR=iant
CC=golang-dev
https://golang.org/cl/7416046

変更の背景

このコミットの主な背景は、GoランタイムのCgo関連コードにおけるシンボル命名の一貫性の欠如です。コミットメッセージには「The naming in this package is a disaster. (このパッケージの命名はひどい)」と明記されており、コードの可読性、保守性、そして将来的な拡張性を向上させるために、命名規則を統一する必要がありました。

特に、CgoはGoとC言語の相互運用を可能にする機能であり、GoランタイムとCライブラリの間で多くの関数呼び出しやデータ共有が行われます。このような複雑な相互作用を扱うコードベースでは、シンボル名の一貫性が非常に重要になります。一貫性のない命名は、開発者がコードを理解する際の障壁となり、バグの温床となる可能性もあります。

また、コミットメッセージには「Remove some 'static' from functions that will be referred to from other files soon. (すぐに他のファイルから参照される関数から 'static' を削除する)」とあります。これは、これらの関数が単一のコンパイル単位内でのみ使用されるプライベートな関数ではなく、Goランタイムの他の部分やCgoの異なるモジュールから呼び出されるようになることを示唆しています。static キーワードはC言語において、関数や変数のスコープをそのファイル内に限定する役割があります。この static を削除することで、リンカがこれらのシンボルを他のファイルから参照できるようにし、GoランタイムとCgoの連携をより柔軟にするための準備であると考えられます。

さらに、「This CL is purely renames using global search and replace. Submitting separately so that real changes will not be drowned out by these renames in future CLs. (この変更リストは純粋にグローバルな検索と置換による名前変更です。将来の変更リストでこれらの名前変更によって本当の変更が埋もれてしまわないように、個別に提出します。)」という記述から、このコミットが機能的な変更を含まず、純粋にコードベースのクリーンアップとリファクタリングであることを強調しています。このような大規模な名前変更は、後続の機能追加やバグ修正のコミットと混ざると、変更内容のレビューが非常に困難になるため、独立したコミットとして提出することは、ソフトウェア開発における良いプラクティスです。

前提知識の解説

このコミットを理解するためには、以下のGo言語およびC言語の基本的な概念と、Goランタイムの内部構造に関する知識が必要です。

  1. Go言語のCgo:

    • Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。これにより、既存のCライブラリをGoプロジェクトで再利用したり、パフォーマンスが重要な部分をCで記述したりすることが可能になります。
    • Cgoを使用すると、Goのビルドプロセス中にCコードがコンパイルされ、Goの実行可能ファイルにリンクされます。GoとCの間でデータをやり取りする際には、型変換やメモリ管理の考慮が必要になります。
  2. Goランタイム (Go Runtime):

    • Goランタイムは、Goプログラムの実行を管理するGo言語の重要な部分です。これには、ガベージコレクション、スケジューラ(goroutineの管理)、メモリ割り当て、システムコールインターフェースなどが含まれます。
    • GoプログラムがCgoを介してCコードを呼び出す際、GoランタイムはCの実行環境とGoの実行環境の間でコンテキストスイッチを行います。このプロセスには、GoのgoroutineとCのスレッドのマッピング、スタックの切り替え、レジスタの保存と復元などが伴います。
  3. Goのスケジューラ (Goroutine, G, M, P):

    • Goのスケジューラは、Goの並行処理モデルの中核をなすものです。
      • G (Goroutine): Goにおける軽量なスレッドのようなものです。数千から数百万のgoroutineを同時に実行できます。
      • M (Machine/OS Thread): オペレーティングシステムのスレッドです。Goランタイムは、M上でGを実行します。
      • P (Processor/Logical Processor): MがGを実行するために必要な論理プロセッサです。PはMに割り当てられ、MはPのコンテキストでGを実行します。
    • Cgo呼び出しが行われると、Goランタイムは現在のGをMから切り離し、MをCコードの実行に専念させることがあります。Cコードの実行が完了すると、Mは再びGoのスケジューラに戻り、Gの実行を再開します。このGとMの状態の保存・復元が、Cgoのパフォーマンスと正確性に大きく影響します。
  4. TLS (Thread Local Storage):

    • TLSは、各スレッドが独自のデータコピーを持つことを可能にするメカニズムです。Cgoのコンテキストでは、GoのGとMのポインタをスレッドローカルストレージに保存し、CコードからGoランタイムの状態にアクセスするために使用されることがあります。これにより、CコードがGoのランタイム状態を安全に参照できるようになります。
    • 特にARMアーキテクチャなど、一部のプラットフォームではTLSの扱いが異なるため、プラットフォーム固有の実装が必要になることがあります。
  5. C言語の static キーワード:

    • C言語において、関数やグローバル変数に static キーワードを付けると、そのスコープが宣言されたファイル(翻訳単位)内に限定されます。つまり、他のファイルからはその関数や変数を直接参照することはできません。
    • このコミットでは、static を削除することで、これらの関数が外部から参照可能になり、Goランタイムの異なる部分やCgoの他のモジュールから呼び出せるようになります。
  6. アセンブリ言語 (x86, AMD64, ARM):

    • Goランタイムの低レベルな部分、特にCgoとのインターフェースやスケジューラのコンテキストスイッチ部分は、アセンブリ言語で記述されています。これは、OSのスレッドやレジスタを直接操作する必要があるためです。
    • このコミットで変更されている asm_386.s, asm_amd64.s, asm_arm.s などのファイルは、それぞれ32ビットx86、64ビットx86、ARMアーキテクチャ向けのアセンブリコードです。これらのファイルでは、initcgocgo_load_gm といったシンボルが直接参照されており、それらの名前が変更されています。

これらの前提知識を理解することで、コミットがGoランタイムのCgo部分の低レベルな動作にどのように影響するかを深く把握できます。

技術的詳細

このコミットは、GoランタイムのCgo関連コードにおけるシンボル名の統一と、一部関数の可視性変更に焦点を当てています。技術的な変更は、主に以下の2点に集約されます。

  1. シンボル名のプレフィックス統一:

    • GoランタイムとCgoの連携において使用される多くのC関数やグローバル変数(関数ポインタ)の命名規則が変更されています。具体的には、initcgolibcgo_sys_thread_startcgo_tls_set_gmcgo_tls_get_gmlibcgo_setenvlibcgo_thread_start といったシンボルが、それぞれ _cgo_init_cgo_sys_thread_startx_cgo_save_gmx_cgo_load_gm_cgo_setenv_cgo_thread_start に変更されています。
    • 特に注目すべきは、initcgo_cgo_init に、libcgo_sys_thread_start_cgo_sys_thread_start に変更されている点です。Goの内部では、Cgo関連のシンボルには慣習的に _cgo_ というプレフィックスが付けられます。この変更は、この慣習に沿って命名を統一し、GoとCの境界を明確にする意図があります。
    • cgo_tls_set_gmcgo_tls_get_gmx_cgo_save_gmx_cgo_load_gm に変更されているのは、これらの関数がGoの g (goroutine) と m (machine/OS thread) のポインタをスレッドローカルストレージに保存・ロードする役割を担っているためです。saveload という動詞を使うことで、関数の目的がより明確になります。また、x_ プレフィックスは、これらの関数がCgoの内部実装の詳細であることを示唆している可能性があります。
  2. static キーワードの削除:

    • Cgo関連のCソースファイル(例: gcc_darwin_386.c, gcc_freebsd_arm.c, gcc_util.c など)において、いくつかの関数から static キーワードが削除されています。
    • 例えば、xinitcgoxlibcgo_setenvxlibcgo_thread_start といった関数は、以前は static で宣言されていましたが、このコミットで static が削除され、グローバルな可視性を持つようになりました。
    • C言語の static キーワードは、関数や変数のスコープをそのファイル(翻訳単位)内に限定します。static を削除することで、これらの関数は他のCソースファイルや、Goランタイムのアセンブリコードから直接呼び出せるようになります。
    • コミットメッセージにある「Remove some 'static' from functions that will be referred to from other files soon.」という記述は、この変更の意図を明確に示しています。これは、GoランタイムとCgoの連携をより密接にし、将来的にこれらの関数がGoの他の部分から直接利用されるようになるための準備であると考えられます。例えば、GoのスケジューラがCgoスレッドの開始や終了をより細かく制御するために、これらの関数を直接呼び出す必要が生じる可能性があります。

これらの変更は、GoランタイムのCgo部分の内部構造を整理し、将来的な機能拡張や最適化のための基盤を強化することを目的としています。純粋な名前変更とスコープ変更であるため、直接的な機能変更やバグ修正ではありませんが、コードベースの健全性を保つ上で非常に重要なリファクタリングです。

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

このコミットは、GoランタイムのCgo関連ファイル全体にわたる広範な名前変更と、一部のC関数からの static キーワードの削除が主な変更点です。以下に、主要な変更箇所をファイルタイプ別に示します。

1. アセンブリファイル (.s 拡張子):

  • src/pkg/runtime/asm_386.s
  • src/pkg/runtime/asm_amd64.s
  • src/pkg/runtime/asm_arm.s
  • src/pkg/runtime/sys_freebsd_arm.s
  • src/pkg/runtime/sys_linux_arm.s
  • src/pkg/runtime/sys_netbsd_arm.s

これらのファイルでは、Goランタイムの初期化ルーチンやCgo呼び出しに関連するアセンブリコード内で、initcgocgo_save_gmcgo_load_gm といったシンボル名が、それぞれ _cgo_init_cgo_save_gm_cgo_load_gm に変更されています。これは、アセンブリコードがCgoのC関数やGoのグローバル変数に直接アクセスしているため、C側での名前変更に合わせてアセンブリ側も更新する必要があるためです。

例 (src/pkg/runtime/asm_386.s から):

--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -14,22 +14,22 @@ TEXT _rt0_386(SB),7,$0
  	MOVL	BX, 124(SP)
 
  	// set default stack bounds.
- 	// initcgo may update stackguard.
+ 	// _cgo_init may update stackguard.
  	MOVL	$runtime·g0(SB), BP
  	LEAL	(-64*1024+104)(SP), BX
  	MOVL	BX, g_stackguard(BP)
  	MOVL	SP, g_stackbase(BP)
  	
- 	// if there is an initcgo, call it to let it
+ 	// if there is an _cgo_init, call it to let it
  	// initialize and to set up GS.  if not,
  	// we set up GS ourselves.
- 	MOVL	initcgo(SB), AX
+ 	MOVL	_cgo_init(SB), AX
  	TESTL	AX, AX
  	JZ	needtls
  	PUSHL	BP
  	CALL	AX
  	POPL	BP
- 	// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
+ 	// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
  	CMPL runtime·iswindows(SB), $0
  	JEQ ok
  needtls:

2. Cgo関連のCソースファイル (.c 拡張子):

  • src/pkg/runtime/cgo/gcc_darwin_386.c
  • src/pkg/runtime/cgo/gcc_darwin_amd64.c
  • src/pkg/runtime/cgo/gcc_freebsd_386.c
  • src/pkg/runtime/cgo/gcc_freebsd_amd64.c
  • src/pkg/runtime/cgo/gcc_freebsd_arm.c
  • src/pkg/runtime/cgo/gcc_linux_386.c
  • src/pkg/runtime/cgo/gcc_linux_amd64.c
  • src/pkg/runtime/cgo/gcc_linux_arm.c
  • src/pkg/runtime/cgo/gcc_netbsd_386.c
  • src/pkg/runtime/cgo/gcc_netbsd_amd64.c
  • src/pkg/runtime/cgo/gcc_netbsd_arm.c
  • src/pkg/runtime/cgo/gcc_openbsd_386.c
  • src/pkg/runtime/cgo/gcc_openbsd_amd64.c
  • src/pkg/runtime/cgo/gcc_setenv.c
  • src/pkg/runtime/cgo/gcc_util.c
  • src/pkg/runtime/cgo/gcc_windows_386.c
  • src/pkg/runtime/cgo/gcc_windows_amd64.c

これらのファイルは、各OS/アーキテクチャ固有のCgo実装を含んでいます。ここでは、主に以下の変更が行われています。

  • static キーワードの削除: xinitcgoxlibcgo_setenvxlibcgo_thread_start など、Goランタイムから呼び出されるC関数から static が削除され、グローバルな可視性を持つようになりました。
  • 関数ポインタの命名変更: initcgolibcgo_sys_thread_startcgo_load_gmcgo_save_gmlibcgo_setenvlibcgo_thread_start といった関数ポインタの宣言と初期化が、新しい命名規則 (_cgo_init など) に合わせて変更されています。

例 (src/pkg/runtime/cgo/gcc_darwin_386.c から):

--- a/src/pkg/runtime/cgo/gcc_darwin_386.c
+++ b/src/pkg/runtime/cgo/gcc_darwin_386.c
@@ -101,8 +101,8 @@ inittls(void)\n \t\tpthread_key_delete(tofree[i]);\n }\n \n-static void\n-xinitcgo(G *g)\n+void\n+x_cgo_init(G *g)\n {\n  \tpthread_attr_t attr;\n  \tsize_t size;\
@@ -115,10 +115,10 @@ xinitcgo(G *g)\n  \tinittls();\n }\n \n-void (*initcgo)(G*) = xinitcgo;\n+void (*_cgo_init)(G*) = x_cgo_init;\n \n void\n-libcgo_sys_thread_start(ThreadStart *ts)\n+_cgo_sys_thread_start(ThreadStart *ts)\n {\n  \tpthread_attr_t attr;\n  \tsigset_t ign, oset;\
@@ -153,7 +153,7 @@ threadentry(void *v)\n  \tts.g->stackbase = (uintptr)&ts;\n \n  \t/*\n-\t * libcgo_sys_thread_start set stackguard to stack size;\n+\t * _cgo_sys_thread_start set stackguard to stack size;\n  \t * change to actual guard pointer.\n  \t */\n  \tts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;\

3. ヘッダーファイル (.h 拡張子):

  • src/pkg/runtime/cgo/libcgo.h

このヘッダーファイルでは、Cgo関連の外部関数ポインタの宣言が新しい命名規則に合わせて更新されています。

例 (src/pkg/runtime/cgo/libcgo.h から):

--- a/src/pkg/runtime/cgo/libcgo.h
+++ b/src/pkg/runtime/cgo/libcgo.h
@@ -26,14 +26,14 @@ struct G
 };
 
 /*
- * Arguments to the libcgo_thread_start call.
+ * Arguments to the _cgo_thread_start call.
  * Also known to ../pkg/runtime/runtime.h.
  */
 typedef struct ThreadStart ThreadStart;\
@@ -40,10 +40,10 @@ struct ThreadStart
 /*
  * Called by 5c/6c/8c world.\
  * Makes a local copy of the ThreadStart and\
- * calls libcgo_sys_thread_start(ts).\
+ * calls _cgo_sys_thread_start(ts).\
  */\
-extern void (*libcgo_thread_start)(ThreadStart *ts);\
+extern void (*_cgo_thread_start)(ThreadStart *ts);\
 \
 /*\
  * Creates the new operating system thread (OS, arch dependent).\
  */\
-void libcgo_sys_thread_start(ThreadStart *ts);\
+void _cgo_sys_thread_start(ThreadStart *ts);\

4. GoランタイムのCソースファイル (.c 拡張子):

  • src/pkg/runtime/cgocall.c
  • src/pkg/runtime/env_posix.c
  • src/pkg/runtime/proc.c

これらのファイルでは、Cgo関連のグローバル変数や関数ポインタの宣言、およびそれらの使用箇所が新しい命名規則に合わせて更新されています。

例 (src/pkg/runtime/cgocall.c から):

--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -83,10 +83,10 @@
 // _cgoexp_GoF immediately returns to crosscall2, which restores the
 // callee-save registers for gcc and returns to GoF, which returns to f.
 
-void *initcgo;	/* filled in by dynamic linker when Cgo is available */
+void *_cgo_init;	/* filled in by dynamic linker when Cgo is available */
 static int64 cgosync;  /* represents possible synchronization in C code */
 
 // These two are only used by the architecture where TLS based storage isn't
 // the default for g and m (e.g., ARM)
-void *cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
-void *cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
+void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
+void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */

これらの変更は、GoランタイムのCgoインターフェース全体にわたるものであり、GoとCの間の相互作用を管理する低レベルな部分に影響を与えています。

コアとなるコードの解説

このコミットにおけるコアとなるコードの変更は、機能的な変更ではなく、主にシンボル名の統一関数の可視性(static キーワードの削除)の変更です。これらの変更は、GoランタイムのCgo部分のコードベースの健全性と保守性を向上させることを目的としています。

1. シンボル名の統一 (initcgo -> _cgo_init など)

GoランタイムとCgoの連携では、GoコードとCコードの間で多くの関数や変数が共有されます。これらのシンボルには、Goの内部的な慣習として _cgo_ というプレフィックスを付けることが一般的です。このコミットでは、この慣習に沿って、一貫性のない命名がされていたシンボル名を変更しています。

  • initcgo から _cgo_init への変更:

    • initcgo は、Cgoが利用可能な場合に動的リンカによって埋め込まれる関数ポインタです。Goランタイムの初期化時にCgo固有の初期化処理(例: スレッドローカルストレージの設定、スタックガードの調整など)を行うために呼び出されます。
    • _cgo_init という名前に変更することで、この関数がCgoの初期化に関連するGoの内部シンボルであることがより明確になります。アセンブリコード (asm_386.s, asm_amd64.s, asm_arm.s) では、この関数ポインタを直接参照して呼び出しているため、名前の変更に合わせてアセンブリコードも更新されています。
  • libcgo_sys_thread_start から _cgo_sys_thread_start への変更:

    • libcgo_sys_thread_start は、新しいOSスレッドを作成するCgoの内部関数です。Goランタイムが新しいM(OSスレッド)を起動する際に、Cgoが有効な場合はこの関数を呼び出して、Cgoの環境下でスレッドが適切に初期化されるようにします。
    • _cgo_sys_thread_start への変更も、Cgo関連のシステムコールインターフェースであることを明確にするためのものです。
  • cgo_tls_get_gm / cgo_tls_set_gm から x_cgo_load_gm / x_cgo_save_gm への変更:

    • これらの関数は、Goの g (goroutine) と m (machine/OS thread) のポインタをスレッドローカルストレージ (TLS) に保存 (set) およびロード (get) する役割を担っています。特にARMアーキテクチャなど、TLSベースのストレージがデフォルトではない環境で重要になります。
    • loadsave という動詞を使用することで、関数の操作がより直感的に理解できるようになります。また、x_ プレフィックスは、これらの関数がCgoの内部実装の詳細であり、直接外部から呼び出されることを意図していないことを示唆している可能性があります。アセンブリコード (asm_arm.s, sys_freebsd_arm.s, sys_linux_arm.s, sys_netbsd_arm.s) では、これらの関数を直接呼び出して gm の状態を管理しています。
  • libcgo_setenv から _cgo_setenv への変更:

    • libcgo_setenv は、Goの syscall.Setenv がCgo経由でCの setenv 関数を呼び出すためのラッパーです。
    • _cgo_setenv への変更は、Cgoを介した環境変数の設定に関連するGoの内部シンボルであることを明確にします。
  • libcgo_thread_start から _cgo_thread_start への変更:

    • libcgo_thread_start は、Goランタイムが新しいスレッドを起動する際に、Cgoが有効な場合に呼び出される関数ポインタです。この関数は、ThreadStart 構造体(新しいスレッドの mg、および開始関数を含む)を受け取り、OS固有の _cgo_sys_thread_start を呼び出して実際のスレッドを起動します。
    • _cgo_thread_start への変更も、Cgoを介したスレッド起動に関連するGoの内部シンボルであることを明確にします。

これらの名前変更は、コードベース全体にわたるグローバルな検索と置換によって行われており、GoとCの境界をまたぐシンボルの命名規則を統一し、将来的な開発における混乱を避けるための重要なステップです。

2. static キーワードの削除

C言語において、static キーワードは関数や変数のスコープをそのファイル(翻訳単位)内に限定します。このコミットでは、Cgo関連のCソースファイル内のいくつかの関数からこの static キーワードが削除されています。

  • 影響を受ける関数: x_cgo_init (旧 xinitcgo)、x_cgo_setenv (旧 xlibcgo_setenv)、x_cgo_thread_start (旧 xlibcgo_thread_start) など。
  • 目的: コミットメッセージにあるように、「将来的に他のファイルから参照される関数から static を削除する」ことが目的です。static を削除することで、これらの関数はグローバルなリンケージを持つようになり、他のCソースファイルやGoランタイムのアセンブリコードから直接呼び出すことが可能になります。
  • 意義: これは、GoランタイムとCgoの連携をより柔軟にし、将来的な機能拡張や最適化のための準備であると考えられます。例えば、GoのスケジューラやガベージコレクタがCgoスレッドの状態をより細かく制御するために、これらの関数を直接呼び出す必要が生じる可能性があります。static の削除は、これらの関数が単なる内部ヘルパー関数ではなく、Goランタイムの重要なインターフェースの一部であることを示唆しています。

これらの変更は、GoランタイムのCgo部分の内部構造を整理し、コードの可読性、保守性、そして将来的な拡張性を向上させるための基盤を強化するものです。機能的な変更は伴いませんが、大規模なコードベースの長期的な健全性を維持する上で不可欠なリファクタリングと言えます。

関連リンク

  • Go言語のCgoドキュメント: https://pkg.go.dev/cmd/cgo
  • Goランタイムの内部構造に関する記事 (GoのGPMモデルなど): 多数のブログ記事やGoの公式ドキュメント、ソースコード解説が存在します。例えば、"Go scheduler GPM model" などで検索すると良いでしょう。
  • Goのソースコードリポジトリ: https://github.com/golang/go

参考にした情報源リンク

  • コミット情報: /home/orange/Project/comemo/commit_data/15504.txt
  • GitHubコミットページ: https://github.com/golang/go/commit/f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e
  • Go言語のCgoに関する一般的な知識 (Web検索)
  • GoランタイムのGPMモデル、TLSに関する一般的な知識 (Web検索)
  • C言語の static キーワードに関する一般的な知識 (Web検索)```markdown

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

このコミットは、Go言語のランタイムにおけるCgo関連のシンボル命名規則を統一することを目的としています。特に、runtime/cgo パッケージ内の関数や変数名のプレフィックスを _cgo_ に変更し、一貫性のない命名を修正しています。また、将来的に他のファイルから参照される予定の関数から static キーワードを削除しています。

コミット

commit f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e
Author: Russ Cox <rsc@golang.org>
Date:   Thu Feb 28 16:24:38 2013 -0500

    runtime/cgo: make symbol naming consistent

    The naming in this package is a disaster.
    Make it all consistent.

    Remove some 'static' from functions that will
    be referred to from other files soon.

    This CL is purely renames using global search and replace.

    Submitting separately so that real changes will not
    be drowned out by these renames in future CLs.

    TBR=iant
    CC=golang-dev
    https://golang.org/cl/7416046

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

https://github.com/golang/go/commit/f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e

元コミット内容

runtime/cgo: make symbol naming consistent

The naming in this package is a disaster.
Make it all consistent.

Remove some 'static' from functions that will
be referred to from other files soon.

This CL is purely renames using global search and replace.

Submitting separately so that real changes will not
be drowned out by these renames in future CLs.

TBR=iant
CC=golang-dev
https://golang.org/cl/7416046

変更の背景

このコミットの主な背景は、GoランタイムのCgo関連コードにおけるシンボル命名の一貫性の欠如です。コミットメッセージには「The naming in this package is a disaster. (このパッケージの命名はひどい)」と明記されており、コードの可読性、保守性、そして将来的な拡張性を向上させるために、命名規則を統一する必要がありました。

特に、CgoはGoとC言語の相互運用を可能にする機能であり、GoランタイムとCライブラリの間で多くの関数呼び出しやデータ共有が行われます。このような複雑な相互作用を扱うコードベースでは、シンボル名の一貫性が非常に重要になります。一貫性のない命名は、開発者がコードを理解する際の障壁となり、バグの温床となる可能性もあります。

また、コミットメッセージには「Remove some 'static' from functions that will be referred to from other files soon. (すぐに他のファイルから参照される関数から 'static' を削除する)」とあります。これは、これらの関数が単一のコンパイル単位内でのみ使用されるプライベートな関数ではなく、Goランタイムの他の部分やCgoの異なるモジュールから呼び出されるようになることを示唆しています。static キーワードはC言語において、関数や変数のスコープをそのファイル内に限定する役割があります。この static を削除することで、リンカがこれらのシンボルを他のファイルから参照できるようにし、GoランタイムとCgoの連携をより柔軟にするための準備であると考えられます。

さらに、「This CL is purely renames using global search and replace. Submitting separately so that real changes will not be drowned out by these renames in future CLs. (この変更リストは純粋にグローバルな検索と置換による名前変更です。将来の変更リストでこれらの名前変更によって本当の変更が埋もれてしまわないように、個別に提出します。)」という記述から、このコミットが機能的な変更を含まず、純粋にコードベースのクリーンアップとリファクタリングであることを強調しています。このような大規模な名前変更は、後続の機能追加やバグ修正のコミットと混ざると、変更内容のレビューが非常に困難になるため、独立したコミットとして提出することは、ソフトウェア開発における良いプラクティスです。

前提知識の解説

このコミットを理解するためには、以下のGo言語およびC言語の基本的な概念と、Goランタイムの内部構造に関する知識が必要です。

  1. Go言語のCgo:

    • Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。これにより、既存のCライブラリをGoプロジェクトで再利用したり、パフォーマンスが重要な部分をCで記述したりすることが可能になります。
    • Cgoを使用すると、Goのビルドプロセス中にCコードがコンパイルされ、Goの実行可能ファイルにリンクされます。GoとCの間でデータをやり取りする際には、型変換やメモリ管理の考慮が必要になります。
  2. Goランタイム (Go Runtime):

    • Goランタイムは、Goプログラムの実行を管理するGo言語の重要な部分です。これには、ガベージコレクション、スケジューラ(goroutineの管理)、メモリ割り当て、システムコールインターフェースなどが含まれます。
    • GoプログラムがCgoを介してCコードを呼び出す際、GoランタイムはCの実行環境とGoの実行環境の間でコンテキストスイッチを行います。このプロセスには、GoのgoroutineとCのスレッドのマッピング、スタックの切り替え、レジスタの保存と復元などが伴います。
  3. Goのスケジューラ (Goroutine, G, M, P):

    • Goのスケジューラは、Goの並行処理モデルの中核をなすものです。
      • G (Goroutine): Goにおける軽量なスレッドのようなものです。数千から数百万のgoroutineを同時に実行できます。
      • M (Machine/OS Thread): オペレーティングシステムのスレッドです。Goランタイムは、M上でGを実行します。
      • P (Processor/Logical Processor): MがGを実行するために必要な論理プロセッサです。PはMに割り当てられ、MはPのコンテキストでGを実行します。
    • Cgo呼び出しが行われると、Goランタイムは現在のGをMから切り離し、MをCコードの実行に専念させることがあります。Cコードの実行が完了すると、Mは再びGoのスケジューラに戻り、Gの実行を再開します。このGとMの状態の保存・復元が、Cgoのパフォーマンスと正確性に大きく影響します。
  4. TLS (Thread Local Storage):

    • TLSは、各スレッドが独自のデータコピーを持つことを可能にするメカニズムです。Cgoのコンテキストでは、GoのGとMのポインタをスレッドローカルストレージに保存し、CコードからGoランタイムの状態にアクセスするために使用されることがあります。これにより、CコードがGoのランタイム状態を安全に参照できるようになります。
    • 特にARMアーキテクチャなど、一部のプラットフォームではTLSの扱いが異なるため、プラットフォーム固有の実装が必要になることがあります。
  5. C言語の static キーワード:

    • C言語において、関数やグローバル変数に static キーワードを付けると、そのスコープが宣言されたファイル(翻訳単位)内に限定されます。つまり、他のファイルからはその関数や変数を直接参照することはできません。
    • このコミットでは、static を削除することで、これらの関数が外部から参照可能になり、Goランタイムの異なる部分やCgoの他のモジュールから呼び出せるようになります。
  6. アセンブリ言語 (x86, AMD64, ARM):

    • Goランタイムの低レベルな部分、特にCgoとのインターフェースやスケジューラのコンテキストスイッチ部分は、アセンブリ言語で記述されています。これは、OSのスレッドやレジスタを直接操作する必要があるためです。
    • このコミットで変更されている asm_386.s, asm_amd64.s, asm_arm.s などのファイルは、それぞれ32ビットx86、64ビットx86、ARMアーキテクチャ向けのアセンブリコードです。これらのファイルでは、initcgocgo_load_gm といったシンボルが直接参照されており、それらの名前が変更されています。

これらの前提知識を理解することで、コミットがGoランタイムのCgo部分の低レベルな動作にどのように影響するかを深く把握できます。

技術的詳細

このコミットは、GoランタイムのCgo関連コードにおけるシンボル名の統一と、一部関数の可視性変更に焦点を当てています。技術的な変更は、主に以下の2点に集約されます。

  1. シンボル名のプレフィックス統一:

    • GoランタイムとCgoの連携において使用される多くのC関数やグローバル変数(関数ポインタ)の命名規則が変更されています。具体的には、initcgolibcgo_sys_thread_startcgo_tls_set_gmcgo_tls_get_gmlibcgo_setenvlibcgo_thread_start といったシンボルが、それぞれ _cgo_init_cgo_sys_thread_startx_cgo_save_gmx_cgo_load_gm_cgo_setenv_cgo_thread_start に変更されています。
    • 特に注目すべきは、initcgo_cgo_init に、libcgo_sys_thread_start_cgo_sys_thread_start に変更されている点です。Goの内部では、Cgo関連のシンボルには慣習的に _cgo_ というプレフィックスが付けられます。この変更は、この慣習に沿って命名を統一し、GoとCの境界を明確にする意図があります。
    • cgo_tls_set_gmcgo_tls_get_gmx_cgo_save_gmx_cgo_load_gm に変更されているのは、これらの関数がGoの g (goroutine) と m (machine/OS thread) のポインタをスレッドローカルストレージに保存・ロードする役割を担っているためです。saveload という動詞を使うことで、関数の目的がより明確になります。また、x_ プレフィックスは、これらの関数がCgoの内部実装の詳細であることを示唆している可能性があります。
  2. static キーワードの削除:

    • Cgo関連のCソースファイル(例: gcc_darwin_386.c, gcc_freebsd_arm.c, gcc_util.c など)において、いくつかの関数から static キーワードが削除されています。
    • 例えば、xinitcgoxlibcgo_setenvxlibcgo_thread_start といった関数は、以前は static で宣言されていましたが、このコミットで static が削除され、グローバルな可視性を持つようになりました。
    • C言語の static キーワードは、関数や変数のスコープをそのファイル(翻訳単位)内に限定します。static を削除することで、これらの関数は他のCソースファイルや、Goランタイムのアセンブリコードから直接呼び出せるようになります。
    • コミットメッセージにある「Remove some 'static' from functions that will be referred to from other files soon.」という記述は、この変更の意図を明確に示しています。これは、GoランタイムとCgoの連携をより密接にし、将来的にこれらの関数がGoの他の部分から直接利用されるようになるための準備であると考えられます。例えば、GoのスケジューラがCgoスレッドの開始や終了をより細かく制御するために、これらの関数を直接呼び出す必要が生じる可能性があります。

これらの変更は、GoランタイムのCgo部分の内部構造を整理し、将来的な機能拡張や最適化のための基盤を強化することを目的としています。純粋な名前変更とスコープ変更であるため、直接的な機能変更やバグ修正ではありませんが、コードベースの健全性を保つ上で非常に重要なリファクタリングです。

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

このコミットは、GoランタイムのCgo関連ファイル全体にわたる広範な名前変更と、一部のC関数からの static キーワードの削除が主な変更点です。以下に、主要な変更箇所をファイルタイプ別に示します。

1. アセンブリファイル (.s 拡張子):

  • src/pkg/runtime/asm_386.s
  • src/pkg/runtime/asm_amd64.s
  • src/pkg/runtime/asm_arm.s
  • src/pkg/runtime/sys_freebsd_arm.s
  • src/pkg/runtime/sys_linux_arm.s
  • src/pkg/runtime/sys_netbsd_arm.s

これらのファイルでは、Goランタイムの初期化ルーチンやCgo呼び出しに関連するアセンブリコード内で、initcgocgo_save_gmcgo_load_gm といったシンボル名が、それぞれ _cgo_init_cgo_save_gm_cgo_load_gm に変更されています。これは、アセンブリコードがCgoのC関数やGoのグローバル変数に直接アクセスしているため、C側での名前変更に合わせてアセンブリ側も更新する必要があるためです。

例 (src/pkg/runtime/asm_386.s から):

--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -14,22 +14,22 @@ TEXT _rt0_386(SB),7,$0
  	MOVL	BX, 124(SP)
 
  	// set default stack bounds.
- 	// initcgo may update stackguard.
+ 	// _cgo_init may update stackguard.
  	MOVL	$runtime·g0(SB), BP
  	LEAL	(-64*1024+104)(SP), BX
  	MOVL	BX, g_stackguard(BP)
  	MOVL	SP, g_stackbase(BP)
  	
- 	// if there is an initcgo, call it to let it
+ 	// if there is an _cgo_init, call it to let it
  	// initialize and to set up GS.  if not,
  	// we set up GS ourselves.
- 	MOVL	initcgo(SB), AX
+ 	MOVL	_cgo_init(SB), AX
  	TESTL	AX, AX
  	JZ	needtls
  	PUSHL	BP
  	CALL	AX
  	POPL	BP
- 	// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
+ 	// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
  	CMPL runtime·iswindows(SB), $0
  	JEQ ok
  needtls:

2. Cgo関連のCソースファイル (.c 拡張子):

  • src/pkg/runtime/cgo/gcc_darwin_386.c
  • src/pkg/runtime/cgo/gcc_darwin_amd64.c
  • src/pkg/runtime/cgo/gcc_freebsd_386.c
  • src/pkg/runtime/cgo/gcc_freebsd_amd64.c
  • src/pkg/runtime/cgo/gcc_freebsd_arm.c
  • src/pkg/runtime/cgo/gcc_linux_386.c
  • src/pkg/runtime/cgo/gcc_linux_amd64.c
  • src/pkg/runtime/cgo/gcc_linux_arm.c
  • src/pkg/runtime/cgo/gcc_netbsd_386.c
  • src/pkg/runtime/cgo/gcc_netbsd_amd64.c
  • src/pkg/runtime/cgo/gcc_netbsd_arm.c
  • src/pkg/runtime/cgo/gcc_openbsd_386.c
  • src/pkg/runtime/cgo/gcc_openbsd_amd64.c
  • src/pkg/runtime/cgo/gcc_setenv.c
  • src/pkg/runtime/cgo/gcc_util.c
  • src/pkg/runtime/cgo/gcc_windows_386.c
  • src/pkg/runtime/cgo/gcc_windows_amd64.c

これらのファイルは、各OS/アーキテクチャ固有のCgo実装を含んでいます。ここでは、主に以下の変更が行われています。

  • static キーワードの削除: xinitcgoxlibcgo_setenvxlibcgo_thread_start など、Goランタイムから呼び出されるC関数から static が削除され、グローバルな可視性を持つようになりました。
  • 関数ポインタの命名変更: initcgolibcgo_sys_thread_startcgo_load_gmcgo_save_gmlibcgo_setenvlibcgo_thread_start といった関数ポインタの宣言と初期化が、新しい命名規則 (_cgo_init など) に合わせて変更されています。

例 (src/pkg/runtime/cgo/gcc_darwin_386.c から):

--- a/src/pkg/runtime/cgo/gcc_darwin_386.c
+++ b/src/pkg/runtime/cgo/gcc_darwin_386.c
@@ -101,8 +101,8 @@ inittls(void)\n \t\tpthread_key_delete(tofree[i]);\n }\n \n-static void\n-xinitcgo(G *g)\n+void\n+x_cgo_init(G *g)\n {\n  \tpthread_attr_t attr;\n  \tsize_t size;\
@@ -115,10 +115,10 @@ xinitcgo(G *g)\n  \tinittls();\n }\n \n-void (*initcgo)(G*) = xinitcgo;\n+void (*_cgo_init)(G*) = x_cgo_init;\n \n void\n-libcgo_sys_thread_start(ThreadStart *ts)\n+_cgo_sys_thread_start(ThreadStart *ts)\n {\n  \tpthread_attr_t attr;\n  \tsigset_t ign, oset;\
@@ -153,7 +153,7 @@ threadentry(void *v)\n  \tts.g->stackbase = (uintptr)&ts;\n \n  \t/*\n-\t * libcgo_sys_thread_start set stackguard to stack size;\n+\t * _cgo_sys_thread_start set stackguard to stack size;\n  \t * change to actual guard pointer.\n  \t */\n  \tts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;\

3. ヘッダーファイル (.h 拡張子):

  • src/pkg/runtime/cgo/libcgo.h

このヘッダーファイルでは、Cgo関連の外部関数ポインタの宣言が新しい命名規則に合わせて更新されています。

例 (src/pkg/runtime/cgo/libcgo.h から):

--- a/src/pkg/runtime/cgo/libcgo.h
+++ b/src/pkg/runtime/cgo/libcgo.h
@@ -26,14 +26,14 @@ struct G
 };
 
 /*
- * Arguments to the libcgo_thread_start call.
+ * Arguments to the _cgo_thread_start call.
  * Also known to ../pkg/runtime/runtime.h.
  */
 typedef struct ThreadStart ThreadStart;\
@@ -40,10 +40,10 @@ struct ThreadStart
 /*
  * Called by 5c/6c/8c world.\
  * Makes a local copy of the ThreadStart and\
- * calls libcgo_sys_thread_start(ts).\
+ * calls _cgo_sys_thread_start(ts).\
  */\
-extern void (*libcgo_thread_start)(ThreadStart *ts);\
+extern void (*_cgo_thread_start)(ThreadStart *ts);\
 \
 /*\
  * Creates the new operating system thread (OS, arch dependent).\
  */\
-void libcgo_sys_thread_start(ThreadStart *ts);\
+void _cgo_sys_thread_start(ThreadStart *ts);\

4. GoランタイムのCソースファイル (.c 拡張子):

  • src/pkg/runtime/cgocall.c
  • src/pkg/runtime/env_posix.c
  • src/pkg/runtime/proc.c

これらのファイルでは、Cgo関連のグローバル変数や関数ポインタの宣言、およびそれらの使用箇所が新しい命名規則に合わせて更新されています。

例 (src/pkg/runtime/cgocall.c から):

--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -83,10 +83,10 @@
 // _cgoexp_GoF immediately returns to crosscall2, which restores the
 // callee-save registers for gcc and returns to GoF, which returns to f.
 
-void *initcgo;	/* filled in by dynamic linker when Cgo is available */
+void *_cgo_init;	/* filled in by dynamic linker when Cgo is available */
 static int64 cgosync;  /* represents possible synchronization in C code */
 
 // These two are only used by the architecture where TLS based storage isn't
 // the default for g and m (e.g., ARM)
-void *cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
-void *cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
+void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
+void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */

これらの変更は、GoランタイムのCgoインターフェース全体にわたるものであり、GoとCの間の相互作用を管理する低レベルな部分に影響を与えています。

コアとなるコードの解説

このコミットにおけるコアとなるコードの変更は、機能的な変更ではなく、主にシンボル名の統一関数の可視性(static キーワードの削除)の変更です。これらの変更は、GoランタイムのCgo部分のコードベースの健全性と保守性を向上させることを目的としています。

1. シンボル名の統一 (initcgo -> _cgo_init など)

GoランタイムとCgoの連携では、GoコードとCコードの間で多くの関数や変数が共有されます。これらのシンボルには、Goの内部的な慣習として _cgo_ というプレフィックスを付けることが一般的です。このコミットでは、この慣習に沿って、一貫性のない命名がされていたシンボル名を変更しています。

  • initcgo から _cgo_init への変更:

    • initcgo は、Cgoが利用可能な場合に動的リンカによって埋め込まれる関数ポインタです。Goランタイムの初期化時にCgo固有の初期化処理(例: スレッドローカルストレージの設定、スタックガードの調整など)を行うために呼び出されます。
    • _cgo_init という名前に変更することで、この関数がCgoの初期化に関連するGoの内部シンボルであることがより明確になります。アセンブリコード (asm_386.s, asm_amd64.s, asm_arm.s) では、この関数ポインタを直接参照して呼び出しているため、名前の変更に合わせてアセンブリコードも更新されています。
  • libcgo_sys_thread_start から _cgo_sys_thread_start への変更:

    • libcgo_sys_thread_start は、新しいOSスレッドを作成するCgoの内部関数です。Goランタイムが新しいM(OSスレッド)を起動する際に、Cgoが有効な場合はこの関数を呼び出して、Cgoの環境下でスレッドが適切に初期化されるようにします。
    • _cgo_sys_thread_start への変更も、Cgo関連のシステムコールインターフェースであることを明確にするためのものです。
  • cgo_tls_get_gm / cgo_tls_set_gm から x_cgo_load_gm / x_cgo_save_gm への変更:

    • これらの関数は、Goの g (goroutine) と m (machine/OS thread) のポインタをスレッドローカルストレージ (TLS) に保存 (set) およびロード (get) する役割を担っています。特にARMアーキテクチャなど、TLSベースのストレージがデフォルトではない環境で重要になります。
    • loadsave という動詞を使用することで、関数の操作がより直感的に理解できるようになります。また、x_ プレフィックスは、これらの関数がCgoの内部実装の詳細であり、直接外部から呼び出されることを意図していないことを示唆している可能性があります。アセンブリコード (asm_arm.s, sys_freebsd_arm.s, sys_linux_arm.s, sys_netbsd_arm.s) では、これらの関数を直接呼び出して gm の状態を管理しています。
  • libcgo_setenv から _cgo_setenv への変更:

    • libcgo_setenv は、Goの syscall.Setenv がCgo経由でCの setenv 関数を呼び出すためのラッパーです。
    • _cgo_setenv への変更は、Cgoを介した環境変数の設定に関連するGoの内部シンボルであることを明確にします。
  • libcgo_thread_start から _cgo_thread_start への変更:

    • libcgo_thread_start は、Goランタイムが新しいスレッドを起動する際に、Cgoが有効な場合に呼び出される関数ポインタです。この関数は、ThreadStart 構造体(新しいスレッドの mg、および開始関数を含む)を受け取り、OS固有の _cgo_sys_thread_start を呼び出して実際のスレッドを起動します。
    • _cgo_thread_start への変更も、Cgoを介したスレッド起動に関連するGoの内部シンボルであることを明確にします。

これらの名前変更は、コードベース全体にわたるグローバルな検索と置換によって行われており、GoとCの境界をまたぐシンボルの命名規則を統一し、将来的な開発における混乱を避けるための重要なステップです。

2. static キーワードの削除

C言語において、static キーワードは関数や変数のスコープをそのファイル(翻訳単位)内に限定します。このコミットでは、Cgo関連のCソースファイル内のいくつかの関数からこの static キーワードが削除されています。

  • 影響を受ける関数: x_cgo_init (旧 xinitcgo)、x_cgo_setenv (旧 xlibcgo_setenv)、x_cgo_thread_start (旧 xlibcgo_thread_start) など。
  • 目的: コミットメッセージにあるように、「将来的に他のファイルから参照される関数から static を削除する」ことが目的です。static を削除することで、これらの関数はグローバルなリンケージを持つようになり、他のCソースファイルやGoランタイムのアセンブリコードから直接呼び出すことが可能になります。
  • 意義: これは、GoランタイムとCgoの連携をより柔軟にし、将来的な機能拡張や最適化のための準備であると考えられます。例えば、GoのスケジューラやガベージコレクタがCgoスレッドの状態をより細かく制御するために、これらの関数を直接呼び出す必要が生じる可能性があります。static の削除は、これらの関数が単なる内部ヘルパー関数ではなく、Goランタイムの重要なインターフェースの一部であることを示唆しています。

これらの変更は、GoランタイムのCgo部分の内部構造を整理し、コードの可読性、保守性、そして将来的な拡張性を向上させるための基盤を強化するものです。機能的な変更は伴いませんが、大規模なコードベースの長期的な健全性を維持する上で不可欠なリファクタリングと言えます。

関連リンク

  • Go言語のCgoドキュメント: https://pkg.go.dev/cmd/cgo
  • Goランタイムの内部構造に関する記事 (GoのGPMモデルなど): 多数のブログ記事やGoの公式ドキュメント、ソースコード解説が存在します。例えば、"Go scheduler GPM model" などで検索すると良いでしょう。
  • Goのソースコードリポジトリ: https://github.com/golang/go

参考にした情報源リンク

  • コミット情報: /home/orange/Project/comemo/commit_data/15504.txt
  • GitHubコミットページ: https://github.com/golang/go/commit/f8d49b509bb081dbf7fc1e1f4a1403e3ab8ce56e
  • Go言語のCgoに関する一般的な知識 (Web検索)
  • GoランタイムのGPMモデル、TLSに関する一般的な知識 (Web検索)
  • C言語の static キーワードに関する一般的な知識 (Web検索)