[インデックス 13274] ファイルの概要
このコミットは、Go言語のCgo機能がNetBSDオペレーティングシステム上の386およびamd64アーキテクチャで利用可能になるようにするための変更を導入しています。具体的には、Goのビルドシステム、Cgoランタイム、および標準ライブラリの一部にNetBSD固有のサポートを追加し、CgoがGoプログラムからCコードを呼び出すことを可能にします。
コミット
commit 5131deeeb2da14668a318c1b40e5d6842af06ab1
Author: Joel Sing <jsing@google.com>
Date: Tue Jun 5 01:43:04 2012 +1000
cgo: enable cgo on netbsd/386 and netbsd/amd64
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6261056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5131deeeb2da14668a318c1b40e5d6842af06ab1
元コミット内容
このコミットの目的は、「cgo: enable cgo on netbsd/386 and netbsd/amd64」(cgo: netbsd/386 および netbsd/amd64 で cgo を有効化)です。これは、Go言語のCgoツールがNetBSDオペレーティングシステムの32ビット (386) および64ビット (amd64) アーキテクチャで動作するようにするための変更を意味します。
変更の背景
Go言語は、その設計思想として、可能な限り純粋なGoコードで記述されることを目指していますが、既存のCライブラリとの連携や、特定のシステムコールへのアクセスが必要な場合もあります。Cgoは、GoプログラムからCコードを呼び出し、またCコードからGoコードを呼び出すためのメカニズムを提供します。
NetBSDは、UNIX系のオープンソースオペレーティングシステムであり、その移植性の高さで知られています。Go言語がより多くのプラットフォームで利用されるためには、各プラットフォーム固有のCgoサポートを実装する必要があります。このコミット以前は、NetBSD上でのCgoのサポートが不完全であったか、あるいは全く存在しなかったと考えられます。
この変更の背景には、Go言語のクロスプラットフォーム対応を強化し、NetBSDユーザーがCgoを利用してGoプログラムを開発できるようにするという目的があります。特に、ネットワーク関連の機能やユーザー情報取得など、OS固有のCライブラリに依存するGoの標準パッケージが、Cgoを介してNetBSD上で正しく機能するために、このような低レベルのサポートが必要とされます。
前提知識の解説
Cgo
Cgoは、Go言語のツールであり、GoプログラムがC言語のコードを呼び出したり、C言語のコードからGo言語の関数を呼び出したりすることを可能にします。これは、既存のCライブラリをGoプロジェクトで再利用したり、Go言語では直接アクセスできないOS固有の機能(システムコールなど)を利用したりする際に不可欠です。
Cgoを使用するには、Goソースファイル内に特別なimport "C"
ステートメントを記述し、その直前のコメントブロックにC言語のコードを記述します。Cgoツールは、GoとCの間のブリッジコードを生成し、Goの型とCの型の間でデータを変換する役割を担います。
NetBSD
NetBSDは、BSD系UNIXオペレーティングシステムの一つで、非常に高い移植性を持つことで知られています。多様なハードウェアアーキテクチャに対応しており、組み込みシステムからサーバーまで幅広い用途で利用されています。Go言語のようなクロスプラットフォーム言語にとって、NetBSDのような多様な環境をサポートすることは、その普及において重要です。
386 (i386) および AMD64 (x86-64)
これらはCPUのアーキテクチャを指します。
- 386 (i386): Intel 80386プロセッサに由来する32ビットのx86アーキテクチャです。古いシステムや一部の組み込みシステムでまだ使用されています。
- AMD64 (x86-64): AMDが開発し、Intelも採用している64ビットのx86アーキテクチャです。現代のほとんどのデスクトップPCやサーバーで使用されています。
Go言語のランタイムやCgoの低レベルな実装は、これらのアーキテクチャ固有の特性(レジスタの使用方法、スタックフレームのレイアウト、スレッドローカルストレージのアクセス方法など)に依存するため、各アーキテクチャごとに異なるコードが必要となる場合があります。
pthread
(POSIX Threads)
pthread
は、POSIX標準で定義されたスレッドAPIです。UNIX系オペレーティングシステムでマルチスレッドプログラミングを行う際の標準的なインターフェースとして広く利用されています。Goのランタイムは、OSのスレッド機能を利用してゴルーチンをスケジューリングするため、CgoがCコードからGoコードを呼び出す際や、GoランタイムがCライブラリと連携する際には、pthread
のようなOSのスレッド管理機能との連携が不可欠です。
スレッドローカルストレージ (TLS)
スレッドローカルストレージは、各スレッドがそれぞれ独立したデータを保持できるメモリ領域です。マルチスレッド環境において、グローバル変数や静的変数をスレッド間で共有するのではなく、スレッドごとに独立したコピーを持たせたい場合に利用されます。Goのランタイムでは、現在のゴルーチンやスケジューラに関する情報(g
とm
ポインタ)をスレッドローカルストレージに格納することが一般的です。CgoがGoとCの間でコンテキストを切り替える際、これらのポインタを正しく設定・復元することが重要になります。
技術的詳細
このコミットは、NetBSD上でのCgoの動作を可能にするために、以下の主要な技術的変更を加えています。
-
Cgo有効化のビルド設定:
src/pkg/go/build/build.go
内のcgoEnabled
マップに、"netbsd/386": true
と"netbsd/amd64": true
を追加しています。これにより、GoのビルドシステムがNetBSDの386およびamd64アーキテクチャでCgoを有効にするべきだと認識するようになります。 -
NetBSD固有のCgoランタイムサポート:
src/pkg/runtime/cgo/gcc_netbsd_386.c
およびsrc/pkg/runtime/cgo/gcc_netbsd_amd64.c
という新しいファイルが追加されています。これらは、NetBSD上でのCgoの低レベルなランタイムサポートを提供します。- これらのファイルには、
xinitcgo
関数とlibcgo_sys_thread_start
関数が含まれています。xinitcgo
: Goランタイムの初期化時に呼び出され、現在のGoルーチンのスタックガードを設定します。これは、スタックオーバーフロー検出のための重要なメカニズムです。libcgo_sys_thread_start
: Cgoが新しいOSスレッドを起動する際に呼び出されます。pthread_create
を使用して新しいスレッドを作成し、そのスレッドのスタックガードを設定し、Goのg
(ゴルーチン)とm
(マシン/OSスレッド)ポインタをスレッドローカルストレージに設定します。
- 特に注目すべきは、スレッドローカルストレージへの
g
とm
ポインタの設定方法です。NetBSD/ELF環境では、%gs
レジスタ(386の場合)または%fs
レジスタ(amd64の場合)をベースとしたオフセットでTLSにアクセスします。アセンブリ命令(movl %0, %%gs:-8
など)を用いて、これらのポインタを特定のメモリ位置に書き込んでいます。これは、GoランタイムがCコードからGoコードにコールバックする際に、正しいGoルーチンコンテキストを復元するために不可欠です。
-
NetBSD固有の標準ライブラリCgoバインディング:
misc/cgo/stdio/stdio_netbsd.go
が追加され、NetBSD上での標準入出力(Stdout
,Stderr
)へのCgoアクセスを提供します。これは、C言語のFILE
構造体へのポインタをGoのunsafe.Pointer
を介してラップすることで実現されています。src/pkg/net/cgo_netbsd.go
が追加され、NetBSD上でのネットワーク関連のCgoバインディングを提供します。特に、cgoAddrInfoFlags()
関数は、getaddrinfo
システムコールで使用されるフラグ(AI_CANONNAME
,AI_V4MAPPED
,AI_ALL
)を定義しています。これは、Goのnet
パッケージがCgoを介して名前解決を行う際に必要となります。
-
ビルドタグの更新:
src/pkg/net/cgo_unix.go
およびsrc/pkg/os/user/lookup_unix.go
のビルドタグにnetbsd
が追加されています。これにより、これらのファイルがNetBSDプラットフォームでもコンパイルされ、Cgoを利用したネットワーク機能やユーザー情報ルックアップ機能がNetBSDで有効になります。
-
テストスクリプトの調整:
doc/progs/run
スクリプトが変更され、NetBSD上では特定のCgoテスト(cgo1
,cgo2
,cgo3
,cgo4
)が実行されないように設定されています。これは、NetBSD環境におけるsrandom
関数のシグネチャの違いや、Cgoが標準出力を正しく扱えないという既知の問題に対応するためです。これは、CgoのNetBSDサポートがまだ初期段階であり、一部の機能に互換性の問題があることを示唆しています。
これらの変更により、GoプログラムはNetBSD上でCgoを介してCライブラリと連携できるようになり、Go言語のNetBSDサポートが大幅に強化されます。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主に以下のファイルに集中しています。
-
src/pkg/go/build/build.go
:cgoEnabled
マップに"netbsd/386": true
と"netbsd/amd64": true
が追加され、NetBSDの386およびamd64アーキテクチャでCgoが有効化されるようにビルド設定が更新されました。
-
src/pkg/runtime/cgo/gcc_netbsd_386.c
(新規追加):- NetBSD/386アーキテクチャ向けのCgoランタイムサポートファイル。
xinitcgo
関数: Goランタイム初期化時のスタックガード設定。libcgo_sys_thread_start
関数: 新しいOSスレッド作成と、g
およびm
ポインタのスレッドローカルストレージ(%gs:-8
,%gs:-4
)への設定。threadentry
関数: 新しいスレッドのエントリポイント。
-
src/pkg/runtime/cgo/gcc_netbsd_amd64.c
(新規追加):- NetBSD/amd64アーキテクチャ向けのCgoランタイムサポートファイル。
xinitcgo
関数: Goランタイム初期化時のスタックガード設定。libcgo_sys_thread_start
関数: 新しいOSスレッド作成と、g
およびm
ポインタのスレッドローカルストレージ(%fs:-16
,%fs:-8
)への設定。threadentry
関数: 新しいスレッドのエントリポイント。
-
misc/cgo/stdio/stdio_netbsd.go
(新規追加):- NetBSD向けのCgoによる標準入出力(
Stdout
,Stderr
)へのアクセスを提供するGoファイル。 C.__sF[1]
とC.__sF[2]
をunsafe.Pointer
でGoのFile
型にキャストして公開。
- NetBSD向けのCgoによる標準入出力(
-
src/pkg/net/cgo_netbsd.go
(新規追加):- NetBSD向けのCgoによるネットワーク関連機能を提供するGoファイル。
cgoAddrInfoFlags()
関数:getaddrinfo
で使用するAI_CANONNAME
,AI_V4MAPPED
,AI_ALL
フラグを返す。
-
src/pkg/net/cgo_unix.go
およびsrc/pkg/os/user/lookup_unix.go
:- これらのファイルのビルドタグ(
// +build darwin freebsd linux
)にnetbsd
が追加され、NetBSDでもこれらのCgo関連ファイルがコンパイルされるようになりました。
- これらのファイルのビルドタグ(
コアとなるコードの解説
src/pkg/go/build/build.go
の変更
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -213,11 +213,13 @@ var Default Context = defaultContext()
var cgoEnabled = map[string]bool{
"darwin/386": true,
"darwin/amd64": true,
+ "freebsd/386": true,
+ "freebsd/amd64": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
- "freebsd/386": true,
- "freebsd/amd64": true,
+ "netbsd/386": true,
+ "netbsd/amd64": true,
"windows/386": true,
"windows/amd64": true,
}
この変更は、Goのビルドシステムに対して、NetBSDの386およびamd64アーキテクチャでCgoを有効にするように指示します。cgoEnabled
マップは、特定のOS/アーキテクチャの組み合わせでCgoがサポートされているかどうかをGoツールチェーンが判断するために使用されます。
src/pkg/runtime/cgo/gcc_netbsd_386.c
および gcc_netbsd_amd64.c
の新規追加
これらのファイルは、NetBSD上でのGoランタイムとCgoの連携の核心をなします。
共通の構造:
xinitcgo(G *g)
: Goランタイムの初期化時に呼び出され、現在のゴルーチンg
のスタックガードを設定します。スタックガードは、スタックオーバーフローを検出するためのポインタです。libcgo_sys_thread_start(ThreadStart *ts)
: Cgoが新しいOSスレッドを起動する際に呼び出されます。pthread_attr_t attr;
: スレッド属性を定義するための構造体。sigset_t ign, oset;
: シグナルマスクを一時的に変更するための変数。sigfillset(&ign)
で全てのシグナルをブロックし、sigprocmask
で適用することで、スレッド作成中のシグナルハンドリングの問題を回避します。pthread_create(&p, &attr, threadentry, ts);
: 新しいPOSIXスレッドを作成します。threadentry
が新しいスレッドのエントリポイントとなります。ts->g->stackguard = size;
: 新しいスレッドのスタックガードを初期スタックサイズに設定します。
threadentry(void *v)
: 新しく作成されたOSスレッドが最初に実行する関数です。ts = *(ThreadStart*)v; free(v);
:ThreadStart
構造体(Goから渡された情報を含む)を取得し、動的に割り当てられたメモリを解放します。ts.g->stackbase = (uintptr)&ts;
: 現在のスタックポインタをゴルーチンのスタックベースとして設定します。ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
: スタックガードを実際のガードポインタに調整します。- スレッドローカルストレージ (TLS) の設定: ここが最もアーキテクチャ依存性の高い部分です。
- 386版 (
gcc_netbsd_386.c
):
NetBSD/ELFの386環境では、asm volatile ( "movl %0, %%gs:-8\\n" // MOVL g, -8(GS) "movl %1, %%gs:-4\\n" // MOVL m, -4(GS) :: "r"(ts.g), "r"(ts.m) );
%gs
セグメントレジスタをベースとして、オフセット-8
と-4
にそれぞれGoのg
(現在のゴルーチン)とm
(現在のOSスレッド)ポインタを格納します。これは、GoランタイムがCgoコールバックなどでGoコードに切り替える際に、正しいゴルーチンコンテキストを復元するために必要です。 - amd64版 (
gcc_netbsd_amd64.c
):
NetBSD/ELFのamd64環境では、asm volatile ( "movq %0, %%fs:-16\\n" // MOVL g, -16(FS) "movq %1, %%fs:-8\\n" // MOVL m, -8(FS) :: "r"(ts.g), "r"(ts.m) );
%fs
セグメントレジスタをベースとして、オフセット-16
と-8
にそれぞれg
とm
ポインタを格納します。64ビットアーキテクチャなので、movq
(move quadword)命令を使用し、オフセットも386版とは異なります。
- 386版 (
crosscall_386(ts.fn)
/crosscall_amd64(ts.fn)
: GoからCgoを介して呼び出されたGo関数(ts.fn
)を実行します。
misc/cgo/stdio/stdio_netbsd.go
の新規追加
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package stdio
/*
#include <stdio.h>
extern FILE __sF[3];
*/
import "C"
import "unsafe"
var Stdout = (*File)(unsafe.Pointer(&C.__sF[1]))
var Stderr = (*File)(unsafe.Pointer(&C.__sF[2]))
このファイルは、Cgoを介してNetBSDの標準Cライブラリのstdio
機能にアクセスするためのGoバインディングを提供します。C.__sF[3]
は、C言語の標準入出力ストリーム(stdin
, stdout
, stderr
)を指すFILE
ポインタの配列です。__sF[1]
がstdout
、__sF[2]
がstderr
に対応します。unsafe.Pointer
を使用して、CのFILE*
をGoの*File
型に変換し、Goプログラムからこれらの標準ストリームにアクセスできるようにしています。
src/pkg/net/cgo_netbsd.go
の新規追加
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build netbsd
package net
/*
#include <netdb.h>
*/
import "C"
func cgoAddrInfoFlags() C.int {
<<<<<<< local
return C.AI_CANONNAME
=======
return C.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
>>>>>>> other
}
このファイルは、NetBSD上でのネットワーク関連のCgoバインディングを提供します。+build netbsd
というビルドタグにより、このファイルはNetBSD環境でのみコンパイルされます。cgoAddrInfoFlags()
関数は、C言語のgetaddrinfo
関数で使用されるフラグを返します。元のコミットメッセージにはマージコンフリクトの痕跡(<<<<<<< local
など)がありますが、最終的にはC.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
が返されるようになります。これらのフラグは、名前解決の際に正規名、IPv4マップされたIPv6アドレス、および全てのアドレスファミリーを要求することを示します。
関連リンク
- Go言語公式ウェブサイト: https://golang.org/
- NetBSD公式ウェブサイト: https://www.netbsd.org/
- Go言語のCgoに関するドキュメント: https://go.dev/blog/cgo (GoブログのCgoに関する記事)
- POSIX Threads (pthread) の概要: https://ja.wikipedia.org/wiki/POSIX_Threads
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている
https://golang.org/cl/6261056
は、Gerritの変更リストへのリンクです) - x86アーキテクチャにおけるセグメントレジスタ(GS/FS)とTLS: 一般的なOS開発やシステムプログラミングの資料
- NetBSDのシステムプログラミングに関するドキュメント```markdown
[インデックス 13274] ファイルの概要
このコミットは、Go言語のCgo機能がNetBSDオペレーティングシステム上の386およびamd64アーキテクチャで利用可能になるようにするための変更を導入しています。具体的には、Goのビルドシステム、Cgoランタイム、および標準ライブラリの一部にNetBSD固有のサポートを追加し、CgoがGoプログラムからCコードを呼び出すことを可能にします。
コミット
commit 5131deeeb2da14668a318c1b40e5d6842af06ab1
Author: Joel Sing <jsing@google.com>
Date: Tue Jun 5 01:43:04 2012 +1000
cgo: enable cgo on netbsd/386 and netbsd/amd64
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6261056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5131deeeb2da14668a318c1b40e5d6842af06ab1
元コミット内容
このコミットの目的は、「cgo: enable cgo on netbsd/386 and netbsd/amd64」(cgo: netbsd/386 および netbsd/amd64 で cgo を有効化)です。これは、Go言語のCgoツールがNetBSDオペレーティングシステムの32ビット (386) および64ビット (amd64) アーキテクチャで動作するようにするための変更を意味します。
変更の背景
Go言語は、その設計思想として、可能な限り純粋なGoコードで記述されることを目指していますが、既存のCライブラリとの連携や、特定のシステムコールへのアクセスが必要な場合もあります。Cgoは、GoプログラムからCコードを呼び出し、またCコードからGoコードを呼び出すためのメカニズムを提供します。
NetBSDは、UNIX系のオープンソースオペレーティングシステムであり、その移植性の高さで知られています。Go言語がより多くのプラットフォームで利用されるためには、各プラットフォーム固有のCgoサポートを実装する必要があります。このコミット以前は、NetBSD上でのCgoのサポートが不完全であったか、あるいは全く存在しなかったと考えられます。
この変更の背景には、Go言語のクロスプラットフォーム対応を強化し、NetBSDユーザーがCgoを利用してGoプログラムを開発できるようにするという目的があります。特に、ネットワーク関連の機能やユーザー情報取得など、OS固有のCライブラリに依存するGoの標準パッケージが、Cgoを介してNetBSD上で正しく機能するために、このような低レベルのサポートが必要とされます。
前提知識の解説
Cgo
Cgoは、Go言語のツールであり、GoプログラムがC言語のコードを呼び出したり、C言語のコードからGo言語の関数を呼び出したりすることを可能にします。これは、既存のCライブラリをGoプロジェクトで再利用したり、Go言語では直接アクセスできないOS固有の機能(システムコールなど)を利用したりする際に不可欠です。
Cgoを使用するには、Goソースファイル内に特別なimport "C"
ステートメントを記述し、その直前のコメントブロックにC言語のコードを記述します。Cgoツールは、GoとCの間のブリッジコードを生成し、Goの型とCの型の間でデータを変換する役割を担います。
NetBSD
NetBSDは、BSD系UNIXオペレーティングシステムの一つで、非常に高い移植性を持つことで知られています。多様なハードウェアアーキテクチャに対応しており、組み込みシステムからサーバーまで幅広い用途で利用されています。Go言語のようなクロスプラットフォーム言語にとって、NetBSDのような多様な環境をサポートすることは、その普及において重要です。
386 (i386) および AMD64 (x86-64)
これらはCPUのアーキテクチャを指します。
- 386 (i386): Intel 80386プロセッサに由来する32ビットのx86アーキテクチャです。古いシステムや一部の組み込みシステムでまだ使用されています。
- AMD64 (x86-64): AMDが開発し、Intelも採用している64ビットのx86アーキテクチャです。現代のほとんどのデスクトップPCやサーバーで使用されています。
Go言語のランタイムやCgoの低レベルな実装は、これらのアーキテクチャ固有の特性(レジスタの使用方法、スタックフレームのレイアウト、スレッドローカルストレージのアクセス方法など)に依存するため、各アーキテクチャごとに異なるコードが必要となる場合があります。
pthread
(POSIX Threads)
pthread
は、POSIX標準で定義されたスレッドAPIです。UNIX系オペレーティングシステムでマルチスレッドプログラミングを行う際の標準的なインターフェースとして広く利用されています。Goのランタイムは、OSのスレッド機能を利用してゴルーチンをスケジューリングするため、CgoがCコードからGoコードを呼び出す際や、GoランタイムがCライブラリと連携する際には、pthread
のようなOSのスレッド管理機能との連携が不可欠です。
スレッドローカルストレージ (TLS)
スレッドローカルストレージは、各スレッドがそれぞれ独立したデータを保持できるメモリ領域です。マルチスレッド環境において、グローバル変数や静的変数をスレッド間で共有するのではなく、スレッドごとに独立したコピーを持たせたい場合に利用されます。Goのランタイムでは、現在のゴルーチンやスケジューラに関する情報(g
とm
ポインタ)をスレッドローカルストレージに格納することが一般的です。CgoがGoとCの間でコンテキストを切り替える際、これらのポインタを正しく設定・復元することが重要になります。
技術的詳細
このコミットは、NetBSD上でのCgoの動作を可能にするために、以下の主要な技術的変更を加えています。
-
Cgo有効化のビルド設定:
src/pkg/go/build/build.go
内のcgoEnabled
マップに、"netbsd/386": true
と"netbsd/amd64": true
を追加しています。これにより、GoのビルドシステムがNetBSDの386およびamd64アーキテクチャでCgoを有効にするべきだと認識するようになります。 -
NetBSD固有のCgoランタイムサポート:
src/pkg/runtime/cgo/gcc_netbsd_386.c
およびsrc/pkg/runtime/cgo/gcc_netbsd_amd64.c
という新しいファイルが追加されています。これらは、NetBSD上でのCgoの低レベルなランタイムサポートを提供します。- これらのファイルには、
xinitcgo
関数とlibcgo_sys_thread_start
関数が含まれています。xinitcgo
: Goランタイムの初期化時に呼び出され、現在のGoルーチンのスタックガードを設定します。これは、スタックオーバーフロー検出のための重要なメカニズムです。libcgo_sys_thread_start
: Cgoが新しいOSスレッドを起動する際に呼び出されます。pthread_create
を使用して新しいスレッドを作成し、そのスレッドのスタックガードを設定し、Goのg
(ゴルーチン)とm
(マシン/OSスレッド)ポインタをスレッドローカルストレージに設定します。
- 特に注目すべきは、スレッドローカルストレージへの
g
とm
ポインタの設定方法です。NetBSD/ELF環境では、%gs
レジスタ(386の場合)または%fs
レジスタ(amd64の場合)をベースとしたオフセットでTLSにアクセスします。アセンブリ命令(movl %0, %%gs:-8
など)を用いて、これらのポインタを特定のメモリ位置に書き込んでいます。これは、GoランタイムがCコードからGoコードにコールバックする際に、正しいGoルーチンコンテキストを復元するために不可欠です。
-
NetBSD固有の標準ライブラリCgoバインディング:
misc/cgo/stdio/stdio_netbsd.go
が追加され、NetBSD上での標準入出力(Stdout
,Stderr
)へのCgoアクセスを提供します。これは、C言語のFILE
構造体へのポインタをGoのunsafe.Pointer
を介してラップすることで実現されています。src/pkg/net/cgo_netbsd.go
が追加され、NetBSD上でのネットワーク関連のCgoバインディングを提供します。特に、cgoAddrInfoFlags()
関数は、getaddrinfo
システムコールで使用されるフラグ(AI_CANONNAME
,AI_V4MAPPED
,AI_ALL
)を定義しています。これは、Goのnet
パッケージがCgoを介して名前解決を行う際に必要となります。
-
ビルドタグの更新:
src/pkg/net/cgo_unix.go
およびsrc/pkg/os/user/lookup_unix.go
のビルドタグにnetbsd
が追加されています。これにより、これらのファイルがNetBSDプラットフォームでもコンパイルされ、Cgoを利用したネットワーク機能やユーザー情報ルックアップ機能がNetBSDで有効になります。
-
テストスクリプトの調整:
doc/progs/run
スクリプトが変更され、NetBSD上では特定のCgoテスト(cgo1
,cgo2
,cgo3
,cgo4
)が実行されないように設定されています。これは、NetBSD環境におけるsrandom
関数のシグネチャの違いや、Cgoが標準出力を正しく扱えないという既知の問題に対応するためです。これは、CgoのNetBSDサポートがまだ初期段階であり、一部の機能に互換性の問題があることを示唆しています。
これらの変更により、GoプログラムはNetBSD上でCgoを介してCライブラリと連携できるようになり、Go言語のNetBSDサポートが大幅に強化されます。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主に以下のファイルに集中しています。
-
src/pkg/go/build/build.go
:cgoEnabled
マップに"netbsd/386": true
と"netbsd/amd64": true
が追加され、NetBSDの386およびamd64アーキテクチャでCgoが有効化されるようにビルド設定が更新されました。
-
src/pkg/runtime/cgo/gcc_netbsd_386.c
(新規追加):- NetBSD/386アーキテクチャ向けのCgoランタイムサポートファイル。
xinitcgo
関数: Goランタイム初期化時のスタックガード設定。libcgo_sys_thread_start
関数: 新しいOSスレッド作成と、g
およびm
ポインタのスレッドローカルストレージ(%gs:-8
,%gs:-4
)への設定。threadentry
関数: 新しいスレッドのエントリポイント。
-
src/pkg/runtime/cgo/gcc_netbsd_amd64.c
(新規追加):- NetBSD/amd64アーキテクチャ向けのCgoランタイムサポートファイル。
xinitcgo
関数: Goランタイム初期化時のスタックガード設定。libcgo_sys_thread_start
関数: 新しいOSスレッド作成と、g
およびm
ポインタのスレッドローカルストレージ(%fs:-16
,%fs:-8
)への設定。threadentry
関数: 新しいスレッドのエントリポイント。
-
misc/cgo/stdio/stdio_netbsd.go
(新規追加):- NetBSD向けのCgoによる標準入出力(
Stdout
,Stderr
)へのアクセスを提供するGoファイル。 C.__sF[1]
とC.__sF[2]
をunsafe.Pointer
でGoのFile
型にキャストして公開。
- NetBSD向けのCgoによる標準入出力(
-
src/pkg/net/cgo_netbsd.go
(新規追加):- NetBSD向けのCgoによるネットワーク関連機能を提供するGoファイル。
cgoAddrInfoFlags()
関数:getaddrinfo
で使用するAI_CANONNAME
,AI_V4MAPPED
,AI_ALL
フラグを返す。
-
src/pkg/net/cgo_unix.go
およびsrc/pkg/os/user/lookup_unix.go
:- これらのファイルのビルドタグ(
// +build darwin freebsd linux
)にnetbsd
が追加され、NetBSDでもこれらのCgo関連ファイルがコンパイルされるようになりました。
- これらのファイルのビルドタグ(
コアとなるコードの解説
src/pkg/go/build/build.go
の変更
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -213,11 +213,13 @@ var Default Context = defaultContext()
var cgoEnabled = map[string]bool{
"darwin/386": true,
"darwin/amd64": true,
+ "freebsd/386": true,
+ "freebsd/amd64": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
- "freebsd/386": true,
- "freebsd/amd64": true,
+ "netbsd/386": true,
+ "netbsd/amd64": true,
"windows/386": true,
"windows/amd64": true,
}
この変更は、Goのビルドシステムに対して、NetBSDの386およびamd64アーキテクチャでCgoを有効にするように指示します。cgoEnabled
マップは、特定のOS/アーキテクチャの組み合わせでCgoがサポートされているかどうかをGoツールチェーンが判断するために使用されます。
src/pkg/runtime/cgo/gcc_netbsd_386.c
および gcc_netbsd_amd64.c
の新規追加
これらのファイルは、NetBSD上でのGoランタイムとCgoの連携の核心をなします。
共通の構造:
xinitcgo(G *g)
: Goランタイムの初期化時に呼び出され、現在のゴルーチンg
のスタックガードを設定します。スタックガードは、スタックオーバーフローを検出するためのポインタです。libcgo_sys_thread_start(ThreadStart *ts)
: Cgoが新しいOSスレッドを起動する際に呼び出されます。pthread_attr_t attr;
: スレッド属性を定義するための構造体。sigset_t ign, oset;
: シグナルマスクを一時的に変更するための変数。sigfillset(&ign)
で全てのシグナルをブロックし、sigprocmask
で適用することで、スレッド作成中のシグナルハンドリングの問題を回避します。pthread_create(&p, &attr, threadentry, ts);
: 新しいPOSIXスレッドを作成します。threadentry
が新しいスレッドのエントリポイントとなります。ts->g->stackguard = size;
: 新しいスレッドのスタックガードを初期スタックサイズに設定します。
threadentry(void *v)
: 新しく作成されたOSスレッドが最初に実行する関数です。ts = *(ThreadStart*)v; free(v);
:ThreadStart
構造体(Goから渡された情報を含む)を取得し、動的に割り当てられたメモリを解放します。ts.g->stackbase = (uintptr)&ts;
: 現在のスタックポインタをゴルーチンのスタックベースとして設定します。ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
: スタックガードを実際のガードポインタに調整します。- スレッドローカルストレージ (TLS) の設定: ここが最もアーキテクチャ依存性の高い部分です。
- 386版 (
gcc_netbsd_386.c
):
NetBSD/ELFの386環境では、asm volatile ( "movl %0, %%gs:-8\\n" // MOVL g, -8(GS) "movl %1, %%gs:-4\\n" // MOVL m, -4(GS) :: "r"(ts.g), "r"(ts.m) );
%gs
セグメントレジスタをベースとして、オフセット-8
と-4
にそれぞれGoのg
(現在のゴルーチン)とm
(現在のOSスレッド)ポインタを格納します。これは、GoランタイムがCgoコールバックなどでGoコードに切り替える際に、正しいゴルーチンコンテキストを復元するために必要です。 - amd64版 (
gcc_netbsd_amd64.c
):
NetBSD/ELFのamd64環境では、asm volatile ( "movq %0, %%fs:-16\\n" // MOVL g, -16(FS) "movq %1, %%fs:-8\\n" // MOVL m, -8(FS) :: "r"(ts.g), "r"(ts.m) );
%fs
セグメントレジスタをベースとして、オフセット-16
と-8
にそれぞれg
とm
ポインタを格納します。64ビットアーキテクチャなので、movq
(move quadword)命令を使用し、オフセットも386版とは異なります。
- 386版 (
crosscall_386(ts.fn)
/crosscall_amd64(ts.fn)
: GoからCgoを介して呼び出されたGo関数(ts.fn
)を実行します。
misc/cgo/stdio/stdio_netbsd.go
の新規追加
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package stdio
/*
#include <stdio.h>
extern FILE __sF[3];
*/
import "C"
import "unsafe"
var Stdout = (*File)(unsafe.Pointer(&C.__sF[1]))
var Stderr = (*File)(unsafe.Pointer(&C.__sF[2]))
このファイルは、Cgoを介してNetBSDの標準Cライブラリのstdio
機能にアクセスするためのGoバインディングを提供します。C.__sF[3]
は、C言語の標準入出力ストリーム(stdin
, stdout
, stderr
)を指すFILE
ポインタの配列です。__sF[1]
がstdout
、__sF[2]
がstderr
に対応します。unsafe.Pointer
を使用して、CのFILE*
をGoの*File
型に変換し、Goプログラムからこれらの標準ストリームにアクセスできるようにしています。
src/pkg/net/cgo_netbsd.go
の新規追加
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build netbsd
package net
/*
#include <netdb.h>
*/
import "C"
func cgoAddrInfoFlags() C.int {
<<<<<<< local
return C.AI_CANONNAME
=======
return C.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
>>>>>>> other
}
このファイルは、NetBSD上でのネットワーク関連のCgoバインディングを提供します。+build netbsd
というビルドタグにより、このファイルはNetBSD環境でのみコンパイルされます。cgoAddrInfoFlags()
関数は、C言語のgetaddrinfo
関数で使用されるフラグを返します。元のコミットメッセージにはマージコンフリクトの痕跡(<<<<<<< local
など)がありますが、最終的にはC.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
が返されるようになります。これらのフラグは、名前解決の際に正規名、IPv4マップされたIPv6アドレス、および全てのアドレスファミリーを要求することを示します。
関連リンク
- Go言語公式ウェブサイト: https://golang.org/
- NetBSD公式ウェブサイト: https://www.netbsd.org/
- Go言語のCgoに関するドキュメント: https://go.dev/blog/cgo (GoブログのCgoに関する記事)
- POSIX Threads (pthread) の概要: https://ja.wikipedia.org/wiki/POSIX_Threads
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている
https://golang.org/cl/6261056
は、Gerritの変更リストへのリンクです) - x86アーキテクチャにおけるセグメントレジスタ(GS/FS)とTLS: 一般的なOS開発やシステムプログラミングの資料
- NetBSDのシステムプログラミングに関するドキュメント