[インデックス 17468] ファイルの概要
このコミットでは、Go言語のCgo機能がDragonFly BSDオペレーティングシステム(386およびamd64アーキテクチャ)で利用可能になるように、Goランタイムおよび関連ツールチェーンに多数の変更が加えられています。具体的には、以下のファイルが変更されました。
misc/cgo/test/cthread_unix.c
: CgoテストにおけるUnix系OSのビルドタグにdragonfly
を追加。misc/cgo/testso/cgoso.go
: Cgo共有ライブラリテストのLDFLAGS
にdragonfly
固有の設定を追加。src/cmd/6l/obj.c
: Goリンカ(6l)が認識するヘッダタイプにHdragonfly
を追加。src/cmd/ld/lib.c
: リンカがDragonFly BSD上でerrno
がTLS (Thread Local Storage) を使用していることによる特殊なリンキング要件を処理するためのロジックを追加。src/pkg/go/build/build.go
:go/build
パッケージのcgoEnabled
マップにdragonfly/386
とdragonfly/amd64
を追加し、これらのプラットフォームでCgoが有効であることを宣言。src/pkg/os/user/lookup_unix.go
:os/user
パッケージのUnix系ルックアップ関数のビルドタグにdragonfly
を追加。src/pkg/runtime/cgo/cgo.go
: CgoランタイムのLDFLAGS
にdragonfly
固有の-lpthread
設定を追加。src/pkg/runtime/cgo/dragonfly.c
: DragonFly BSDのCgoランタイムに必要なenviron
と__progname
シンボルを供給するための新しいファイル。src/pkg/runtime/cgo/gcc_dragonfly_386.c
: DragonFly BSD/386アーキテクチャ向けのCgoランタイム初期化およびスレッド開始ロジックを実装する新しいファイル。src/pkg/runtime/cgo/gcc_dragonfly_amd64.c
: DragonFly BSD/amd64アーキテクチャ向けのCgoランタイム初期化およびスレッド開始ロジックを実装する新しいファイル。src/pkg/runtime/cgo/gcc_setenv.c
: Cgoのsetenv
関連ファイルのビルドタグにdragonfly
を追加。src/pkg/runtime/cgo/setenv.c
: Cgoのsetenv
関連ファイルのビルドタグにdragonfly
を追加。src/run.bash
: Goのテストスクリプトにおいて、DragonFly BSDでのリンカの挙動(特にlinkmode=internal
の制限)を考慮した条件分岐を追加。
コミット
commit 2b44b36487a341fc2a8a23f8b35113bd4958af92
Author: Aulus Egnatius Varialus <varialus@gmail.com>
Date: Wed Sep 4 15:19:21 2013 -0700
cgo: enable cgo on dragonfly
Enable cgo for dragonfly/386 and dragonfly/amd64.
R=golang-dev, jsing, iant, bradfitz
CC=golang-dev
https://golang.org/cl/13247046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2b44b36487a341fc2a8a23f8b35113bd4958af92
元コミット内容
cgo: enable cgo on dragonfly
Enable cgo for dragonfly/386 and dragonfly/amd64.
R=golang-dev, jsing, iant, bradfitz
CC=golang-dev
https://golang.org/cl/13247046
変更の背景
このコミットの背景には、Go言語のクロスプラットフォーム対応の拡大という目標があります。Goは設計当初から様々なオペレーティングシステムやアーキテクチャをサポートすることを目指しており、Cgoはその重要な要素の一つです。CgoはGoプログラムからC言語のコードを呼び出すことを可能にし、既存のCライブラリを活用したり、OS固有のシステムコールにアクセスしたりする際に不可欠です。
DragonFly BSDは、FreeBSDからフォークしたオープンソースのUnix系オペレーティングシステムであり、独自のカーネル設計や機能を持っています。Go言語がこのOS上でCgoを完全にサポートするためには、Goのビルドシステム、リンカ、およびCgoランタイムがDragonFly BSDの特定の挙動やABI(Application Binary Interface)に適合するように調整される必要がありました。
特に、DragonFly BSDにおけるerrno
(エラー番号を保持するグローバル変数)の実装が、Goのリンカが直接扱えないTLS (Thread Local Storage) を利用している点が大きな課題でした。このため、GoプログラムがCgoを通じてerrno
を使用するCライブラリ(例えばnet
やos/user
パッケージが依存するlibcなど)とリンクする際に、特別なリンキング戦略が必要となりました。
このコミットは、Go言語がDragonFly BSD環境でより堅牢に動作し、Cgoを介してシステムレベルの機能や既存のCライブラリをシームレスに利用できるようにするための基盤を構築することを目的としています。
前提知識の解説
Cgo (GoとCの相互運用)
Cgoは、GoプログラムからC言語の関数を呼び出したり、C言語のコード内でGoの関数を呼び出したりするためのGo言語の機能です。Goのソースファイル内にCコードを直接記述し、import "C"
という特別なインポート宣言を使用することで有効になります。Cgoは、GoとCの異なる型システム、メモリ管理、呼び出し規約などを橋渡しする役割を担います。
Cgoが有効な場合、GoコンパイラはCコードをコンパイルし、GoコードとリンクするためにGCC(またはClang)などのCコンパイラ/リンカを内部的に利用します。これにより、Goプログラムは既存のCライブラリ(例: libc
、pthread
など)を利用できるようになります。
DragonFly BSD
DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUnix系オペレーティングシステムです。FreeBSDとは異なるカーネル設計(特にメッセージパッシングベースのカーネルや、HAMMERファイルシステムなど)を採用しており、独自の進化を遂げています。Go言語のようなクロスプラットフォーム言語がDragonFly BSDをサポートするには、そのOS固有のシステムコール、ライブラリ、リンキングの挙動などを考慮する必要があります。
リンカ (ld)
リンカは、コンパイラによって生成されたオブジェクトファイル(機械語コードとデータを含む)と、必要なライブラリを結合して、実行可能なプログラムを生成するツールです。Go言語のビルドプロセスでは、Go独自のリンカ(cmd/6l
など)と、Cgoを使用する場合にはGCCなどの外部リンカが連携して動作します。
リンカの主な役割は以下の通りです。
- シンボル解決: 異なるオブジェクトファイルやライブラリ間で参照される関数や変数のアドレスを解決します。
- 再配置: コード内のアドレス参照を、最終的なメモリレイアウトに合わせて調整します。
- ライブラリの結合: 静的ライブラリ(プログラムに直接組み込まれる)や動的ライブラリ(実行時にロードされる)をプログラムにリンクします。
TLS (Thread Local Storage)
TLS (Thread Local Storage) は、マルチスレッド環境において、各スレッドがそれぞれ独立した変数インスタンスを持つことを可能にするメカニズムです。通常、グローバル変数はすべてのスレッドで共有されますが、TLS変数はスレッドごとに異なる値を保持できます。
errno
は、多くのUnix系システムでシステムコールがエラーを返した場合にそのエラーコードを格納するために使用されるグローバル変数です。しかし、マルチスレッド環境では、複数のスレッドが同時にシステムコールを実行し、それぞれ異なるエラーを返す可能性があるため、errno
は通常TLSとして実装されます。これにより、各スレッドは自身のエラーコードを独立して取得できます。
TLS変数は、リンカにとって特別な種類の再配置(TLSリロケーション)を必要とします。Goのリンカが特定のTLSリロケーションタイプを直接サポートしていない場合、Cgoを介してCライブラリとリンクする際に問題が発生する可能性があります。
_cgo_export.h
Cgoを使用すると、Goの関数をCから呼び出すためのCヘッダファイルが自動的に生成されます。このヘッダファイルは通常_cgo_export.h
という名前で、Go関数に対応するCのプロトタイプ宣言を含んでいます。Cgoのテストや内部実装で、GoとCの間のインターフェースを定義するために利用されます。
+build
タグ
Go言語のソースファイルでは、ファイルの先頭に// +build tag
のようなコメント行を記述することで、条件付きコンパイルを行うことができます。これは、特定のOS、アーキテクチャ、またはビルドタグが指定された場合にのみ、そのファイルをコンパイル対象に含めるために使用されます。例えば、// +build darwin freebsd linux
は、macOS、FreeBSD、Linuxのいずれかでビルドされる場合にこのファイルがコンパイルされることを意味します。
LDFLAGS
LDFLAGS
は、リンカに渡されるオプションを指定するための環境変数またはビルド設定です。Cgoでは、Cコンパイラ/リンカに特定のライブラリをリンクさせたり、ライブラリの検索パスを指定したりするために#cgo LDFLAGS: ...
というディレクティブを使用します。
linkmode=internal
vs linkmode=external
Goのビルドシステムには、Cgoを使用する際のリンキングモードがいくつかあります。
linkmode=internal
: GoのリンカがCgoによって生成されたオブジェクトファイルとGoのオブジェクトファイルを直接リンクしようとします。これは通常、GoのリンカがCのオブジェクトファイルを理解できる場合に効率的です。linkmode=external
: Goのリンカは、Cgoによって生成されたオブジェクトファイルとGoのオブジェクトファイルを結合する際に、外部のCリンカ(通常はGCC)を呼び出します。これは、Goのリンカが直接扱えない複雑なリンキング要件(例: 特定のTLSリロケーション)がある場合や、CライブラリがGoのリンカでは解決できないシンボルに依存している場合に必要となります。
このコミットでは、DragonFly BSDのerrno
がTLSを使用しているため、linkmode=internal
では問題が発生し、linkmode=external
を強制する必要があることが示されています。
技術的詳細
このコミットの主要な技術的課題は、DragonFly BSDにおけるCgoのサポートを確立すること、特にerrno
のTLS実装に起因するリンキングの問題を解決することでした。
-
errno
のTLSリロケーション問題: DragonFly BSDでは、errno
が__thread
キーワードを使用してTLSとして宣言されています。これにより、errno
への参照はR_386_TLS_GD
またはR_X86_64_TLSGD
といったTLSグローバルダイナミックリロケーションタイプを生成します。当時のGoリンカはこれらのTLSリロケーションタイプを直接処理する能力がありませんでした。 この問題を回避するため、src/cmd/ld/lib.c
において、DragonFly BSD向けにnet
およびos/user
パッケージ(これらはerrno
を使用するlibc関数に依存する可能性が高い)がリンクされる際に、強制的にlinkmode=external
が使用されるように変更が加えられました。これにより、Goのリンカではなく、TLSリロケーションを適切に処理できる外部のGCCリンカが使用されることになります。 -
environ
と__progname
の供給: DragonFly BSDのC標準ライブラリ(libc)は、プログラムの起動時にenviron
(環境変数へのポインタの配列)と__progname
(プログラム名)というグローバルシンボルが存在することを期待します。しかし、Goのランタイムは標準のCランタイム起動ルーチン(crt0.o
など)をリンクしないため、これらのシンボルがデフォルトでは提供されません。 この問題を解決するため、src/pkg/runtime/cgo/dragonfly.c
という新しいファイルが追加されました。このファイルは、ダミーのenviron
配列と__progname
ポインタを宣言し、#pragma dynexport
ディレクティブを使用して、これらのシンボルが動的リンカによってエクスポートされるようにします。これにより、libcがこれらのシンボルを正しく参照できるようになります。 -
Cgoランタイムのプラットフォーム固有の実装: Cgoは、GoとCの間でスレッドの切り替えやスタックの管理を行うために、OSおよびアーキテクチャ固有のランタイムコードを必要とします。このコミットでは、DragonFly BSDの386およびamd64アーキテクチャ向けに、
src/pkg/runtime/cgo/gcc_dragonfly_386.c
とsrc/pkg/runtime/cgo/gcc_dragonfly_amd64.c
という2つの新しいファイルが追加されました。 これらのファイルには、x_cgo_init
(Cgoランタイムの初期化)と_cgo_sys_thread_start
(Cgoスレッドの開始)関数が含まれています。これらはpthread
ライブラリを使用してスレッドを作成し、Goのランタイムが期待するスタックガードやM/G(Machine/Goroutine)ポインタの設定を行います。特に、スタックガードの計算はOSのpthread_attr_getstacksize
の結果に基づいて行われます。 -
ビルドタグとリンカフラグの更新: GoのビルドシステムがDragonFly BSDを認識し、Cgoを有効にするために、
src/pkg/go/build/build.go
のcgoEnabled
マップにdragonfly/386
とdragonfly/amd64
が追加されました。 また、Cgoテストファイルやos/user
パッケージなど、Cgoを使用する可能性のあるGoソースファイルには、+build dragonfly
タグが追加され、DragonFly BSDでのコンパイル対象となるように設定されました。 さらに、src/pkg/runtime/cgo/cgo.go
では、DragonFly BSD向けに-lpthread
リンカフラグが追加され、スレッド関連のC関数が正しくリンクされるようにしました。 -
テストスクリプトの調整:
src/run.bash
テストスクリプトは、DragonFly BSDにおけるlinkmode=internal
の制限を考慮して修正されました。具体的には、GOHOSTOS
がdragonfly
の場合、go test -ldflags '-linkmode=internal'
のテストがスキップされるようになりました。これは、前述のerrno
のTLSリロケーション問題により、linkmode=internal
がDragonFly BSDで機能しないためです。
これらの変更により、Go言語はDragonFly BSD上でCgoを介してCコードと相互運用できるようになり、より広範なシステム機能へのアクセスと既存のCライブラリの利用が可能になりました。
コアとなるコードの変更箇所
src/pkg/go/build/build.go
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -258,21 +258,23 @@ func (ctxt *Context) SrcDirs() []string {
var Default Context = defaultContext()
var cgoEnabled = map[string]bool{
-"darwin/386": true,
-"darwin/amd64": true,
-"freebsd/386": true,
-"freebsd/amd64": true,
-"freebsd/arm": true,
-"linux/386": true,
-"linux/amd64": true,
-"linux/arm": true,
-"netbsd/386": true,
-"netbsd/amd64": true,
-"netbsd/arm": true,
-"openbsd/386": true,
-"openbsd/amd64": true,
-"windows/386": true,
-"windows/amd64": true,
+"darwin/386": true,
+"darwin/amd64": true,
+"dragonfly/386": true,
+"dragonfly/amd64": true,
+"freebsd/386": true,
+"freebsd/amd64": true,
+"freebsd/arm": true,
+"linux/386": true,
+"linux/amd64": true,
+"linux/arm": true,
+"netbsd/386": true,
+"netbsd/amd64": true,
+"netbsd/arm": true,
+"openbsd/386": true,
+"openbsd/amd64": true,
+"windows/386": true,
+"windows/amd64": true,
}
func defaultContext() Context {
src/cmd/ld/lib.c
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -582,6 +582,16 @@ ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64
}
}
+ // DragonFly declares errno with __thread, which results in a symbol
+ // type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
+ // currently know how to handle TLS relocations, hence we have to
+ // force external linking for any libraries that link in code that
+ // uses errno. This can be removed if the Go linker ever supports
+ // these relocation types.
+ if(HEADTYPE == Hdragonfly)
+ if(strcmp(pkg, "net") == 0 || strcmp(pkg, "os/user") == 0)
+ isinternal = 0;
+
if(!isinternal)
externalobj = 1;
src/pkg/runtime/cgo/dragonfly.c
(新規ファイル)
// Copyright 2010 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.
// Supply environ and __progname, because we don't
// link against the standard DragonFly crt0.o and the
// libc dynamic library needs them.
char *environ[1];
char *__progname;
#pragma dynexport environ environ
#pragma dynexport __progname __progname
src/pkg/runtime/cgo/gcc_dragonfly_386.c
(新規ファイル)
// 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.
#include <sys/types.h>
#include <sys/signalvar.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include "libcgo.h"
static void* threadentry(void*);
static void (*setmg_gcc)(void*, void*);
void
x_cgo_init(G *g, void (*setmg)(void*, void*))
{
pthread_attr_t attr;
size_t size;
setmg_gcc = setmg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stackguard = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
void
_cgo_sys_thread_start(ThreadStart *ts)
{
pthread_attr_t attr;
sigset_t ign, oset;
pthread_t p;
size_t size;
int err;
SIGFILLSET(ign);
sigprocmask(SIG_SETMASK, &ign, &oset);
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
ts->g->stackguard = size;
err = pthread_create(&p, &attr, threadentry, ts);
sigprocmask(SIG_SETMASK, &oset, nil);
if (err != 0) {
fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
abort();
}
}
static void*
threadentry(void *v)
{
ThreadStart ts;
ts = *(ThreadStart*)v;
free(v);
ts.g->stackbase = (uintptr)&ts;
/*
* _cgo_sys_thread_start set stackguard to stack size;
* change to actual guard pointer.
*/
ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
/*
* Set specific keys.
*/
setmg_gcc((void*)ts.m, (void*)ts.g);
crosscall_386(ts.fn);
return nil;
}
src/pkg/runtime/cgo/gcc_dragonfly_amd64.c
(新規ファイル)
// 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.
#include <sys/types.h>
#include <sys/signalvar.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include "libcgo.h"
static void* threadentry(void*);
static void (*setmg_gcc)(void*, void*);
void
x_cgo_init(G *g, void (*setmg)(void*, void*))
{
pthread_attr_t attr;
size_t size;
setmg_gcc = setmg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stackguard = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}
void
_cgo_sys_thread_start(ThreadStart *ts)
{
pthread_attr_t attr;
sigset_t ign, oset;
pthread_t p;
size_t size;
int err;
SIGFILLSET(ign);
sigprocmask(SIG_SETMASK, &ign, &oset);
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
ts->g->stackguard = size;
err = pthread_create(&p, &attr, threadentry, ts);
sigprocmask(SIG_SETMASK, &oset, nil);
if (err != 0) {
fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
abort();
}
}
static void*
threadentry(void *v)
{
ThreadStart ts;
ts = *(ThreadStart*)v;
free(v);
ts.g->stackbase = (uintptr)&ts;
/*
* _cgo_sys_thread_start set stackguard to stack size;
* change to actual guard pointer.
*/
ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
/*
* Set specific keys.
*/
setmg_gcc((void*)ts.m, (void*)ts.g);
crosscall_amd64(ts.fn);
return nil;
}
src/run.bash
--- a/src/run.bash
+++ b/src/run.bash
@@ -104,7 +104,8 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test
go test -ldflags '-linkmode=auto' || exit 1
-go test -ldflags '-linkmode=internal' || exit 1
+# linkmode=internal fails on dragonfly since errno is a TLS relocation.
+[ "$GOHOSTOS" == dragonfly ] || go test -ldflags '-linkmode=internal' || exit 1
case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls.
@@ -118,7 +119,7 @@ darwin-386 | darwin-amd64)
*) go test -ldflags '-linkmode=external' || exit 1;;\
esac
;;\
-freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
+dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1
コアとなるコードの解説
src/pkg/go/build/build.go
の変更
この変更は、GoのビルドシステムがCgoを有効にするプラットフォームのリストにdragonfly/386
とdragonfly/amd64
を追加するものです。go/build
パッケージは、Goのソースファイルをビルドする際に、どのOSとアーキテクチャの組み合わせでCgoがサポートされているかを判断するためにこのマップを参照します。この追加により、GoツールチェーンはDragonFly BSD上でCgoを有効にしてGoプログラムをコンパイルできるようになります。
src/cmd/ld/lib.c
の変更
この変更は、Goリンカの挙動をDragonFly BSDに特化して調整するものです。
HEADTYPE == Hdragonfly
という条件で、現在のターゲットOSがDragonFly BSDであるかをチェックします。- もしターゲットがDragonFly BSDであり、かつリンク対象のパッケージが
net
またはos/user
である場合、isinternal
フラグを0
に設定します。 isinternal
が0
に設定されると、Goリンカは内部リンキング(linkmode=internal
)ではなく、外部リンキング(linkmode=external
)を強制します。
この変更の理由は、DragonFly BSDのerrno
変数がTLS (Thread Local Storage) を使用して宣言されており、その結果生成されるTLSリロケーション(R_386_TLS_GD
やR_X86_64_TLSGD
)を当時のGoリンカが直接処理できなかったためです。net
やos/user
パッケージは、Cgoを介してC標準ライブラリの関数(errno
を使用するもの)に依存する可能性が高いため、これらのパッケージがリンクされる際には、TLSリロケーションを適切に処理できる外部のGCCリンカを使用するように強制することで、リンクエラーを防ぎます。
src/pkg/runtime/cgo/dragonfly.c
(新規ファイル) の解説
この新しいファイルは、DragonFly BSDのCgoランタイムが正しく動作するために必要な、特定のグローバルシンボルを提供します。
char *environ[1];
: 環境変数へのポインタの配列であるenviron
を宣言します。これは、C標準ライブラリがプログラムの環境変数にアクセスするために使用するグローバル変数です。Goのランタイムは標準のCcrt0.o
をリンクしないため、このシンボルを明示的に提供する必要があります。char *__progname;
: プログラム名へのポインタである__progname
を宣言します。これもまた、C標準ライブラリがプログラム名を取得するために使用するグローバル変数です。#pragma dynexport environ environ
と#pragma dynexport __progname __progname
: これらのpragma
ディレクティブは、GCCの拡張機能であり、指定されたシンボル(environ
と__progname
)が動的リンカによってエクスポートされるべきであることを示します。これにより、GoプログラムがCgoを介してリンクされる際に、C標準ライブラリがこれらのシンボルを正しく解決できるようになります。
src/pkg/runtime/cgo/gcc_dragonfly_386.c
および src/pkg/runtime/cgo/gcc_dragonfly_amd64.c
(新規ファイル) の解説
これらのファイルは、DragonFly BSDの386およびamd64アーキテクチャ向けのCgoランタイムのコア部分を実装しています。
x_cgo_init(G *g, void (*setmg)(void*, void*))
: Cgoランタイムの初期化関数です。GoのランタイムがCgoスレッドのスタックガードを設定するために必要な情報を初期化します。pthread_attr_getstacksize
を使用してスレッドのスタックサイズを取得し、それに基づいてGoのg->stackguard
(ゴルーチンのスタック境界)を設定します。_cgo_sys_thread_start(ThreadStart *ts)
: CgoによってGoランタイムスレッドが開始される際に呼び出される関数です。pthread_create
を使用して新しいネイティブスレッドを作成し、そのスレッドでthreadentry
関数を実行します。この関数は、シグナルマスクの設定、スレッド属性の初期化、スタックサイズの取得、そしてスレッドの作成を行います。static void* threadentry(void *v)
: 新しく作成されたネイティブスレッドのエントリポイントとなる関数です。この関数は、Goのゴルーチン(G
)とマシン(M
)のポインタをスレッドローカルストレージに設定し、GoのCgoコールバック関数(ts.fn
)を呼び出します。これにより、Cgoを介してGoコードがネイティブスレッド上で実行される準備が整います。スタックガードの再計算もここで行われます。
これらのファイルは、GoのランタイムとDragonFly BSDのネイティブスレッドモデルとの間の橋渡しを行い、CgoがGoとCのコード間で安全にスレッドを切り替え、スタックを管理できるようにするために不可欠です。
src/run.bash
の変更
この変更は、Goのテストスクリプトにおいて、DragonFly BSDでのCgoテストの挙動を調整するものです。
[ "$GOHOSTOS" == dragonfly ] || go test -ldflags '-linkmode=internal' || exit 1
: この行は、もし現在のホストOSがDragonFly BSDである場合、go test -ldflags '-linkmode=internal'
コマンドの実行をスキップするようにします。- コメント
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
が追加されており、DragonFly BSDではerrno
がTLSリロケーションを使用しているため、linkmode=internal
が失敗することを示しています。
この変更は、前述のsrc/cmd/ld/lib.c
での変更と連携しており、DragonFly BSDにおけるリンカの特殊な要件に対応するために、テスト環境でも同様の考慮が必要であることを示しています。これにより、テストスイートがDragonFly BSD上で正しく実行され、誤った失敗を避けることができます。
関連リンク
- https://github.com/golang/go/commit/2b44b36487a341fc2a8a23f8b35113bd4958af92
- Go CL 13247046: https://golang.org/cl/13247046
参考にした情報源リンク
- Go言語公式ドキュメント (Cgo): https://go.dev/blog/cgo
- DragonFly BSD 公式サイト: https://www.dragonflybsd.org/
- Thread-Local Storage (TLS) の概念に関する一般的な情報源 (例: Wikipedia, OS開発者向けドキュメントなど)
- リンカの動作に関する一般的な情報源 (例: リンカとローダ, ELFフォーマットの仕様など)
pthread
ライブラリのドキュメント (例: POSIX標準)- GCCの
#pragma dynexport
に関するドキュメント (GCCの拡張機能) - Goのビルドタグに関するドキュメント: https://go.dev/cmd/go/#hdr-Build_constraints
- Goのリンキングモードに関する情報 (Goのリンカの内部動作に関する記事やドキュメント)