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

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

このコミットでは、Go言語のCgo機能がDragonFly BSDオペレーティングシステム(386およびamd64アーキテクチャ)で利用可能になるように、Goランタイムおよび関連ツールチェーンに多数の変更が加えられています。具体的には、以下のファイルが変更されました。

  • misc/cgo/test/cthread_unix.c: CgoテストにおけるUnix系OSのビルドタグにdragonflyを追加。
  • misc/cgo/testso/cgoso.go: Cgo共有ライブラリテストのLDFLAGSdragonfly固有の設定を追加。
  • 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/386dragonfly/amd64を追加し、これらのプラットフォームでCgoが有効であることを宣言。
  • src/pkg/os/user/lookup_unix.go: os/userパッケージのUnix系ルックアップ関数のビルドタグにdragonflyを追加。
  • src/pkg/runtime/cgo/cgo.go: CgoランタイムのLDFLAGSdragonfly固有の-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ライブラリ(例えばnetos/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ライブラリ(例: libcpthreadなど)を利用できるようになります。

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実装に起因するリンキングの問題を解決することでした。

  1. 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リンカが使用されることになります。

  2. environ__prognameの供給: DragonFly BSDのC標準ライブラリ(libc)は、プログラムの起動時にenviron(環境変数へのポインタの配列)と__progname(プログラム名)というグローバルシンボルが存在することを期待します。しかし、Goのランタイムは標準のCランタイム起動ルーチン(crt0.oなど)をリンクしないため、これらのシンボルがデフォルトでは提供されません。 この問題を解決するため、src/pkg/runtime/cgo/dragonfly.cという新しいファイルが追加されました。このファイルは、ダミーのenviron配列と__prognameポインタを宣言し、#pragma dynexportディレクティブを使用して、これらのシンボルが動的リンカによってエクスポートされるようにします。これにより、libcがこれらのシンボルを正しく参照できるようになります。

  3. Cgoランタイムのプラットフォーム固有の実装: Cgoは、GoとCの間でスレッドの切り替えやスタックの管理を行うために、OSおよびアーキテクチャ固有のランタイムコードを必要とします。このコミットでは、DragonFly BSDの386およびamd64アーキテクチャ向けに、src/pkg/runtime/cgo/gcc_dragonfly_386.csrc/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の結果に基づいて行われます。

  4. ビルドタグとリンカフラグの更新: GoのビルドシステムがDragonFly BSDを認識し、Cgoを有効にするために、src/pkg/go/build/build.gocgoEnabledマップにdragonfly/386dragonfly/amd64が追加されました。 また、Cgoテストファイルやos/userパッケージなど、Cgoを使用する可能性のあるGoソースファイルには、+build dragonflyタグが追加され、DragonFly BSDでのコンパイル対象となるように設定されました。 さらに、src/pkg/runtime/cgo/cgo.goでは、DragonFly BSD向けに-lpthreadリンカフラグが追加され、スレッド関連のC関数が正しくリンクされるようにしました。

  5. テストスクリプトの調整: src/run.bashテストスクリプトは、DragonFly BSDにおけるlinkmode=internalの制限を考慮して修正されました。具体的には、GOHOSTOSdragonflyの場合、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/386dragonfly/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に設定します。
  • isinternal0に設定されると、Goリンカは内部リンキング(linkmode=internal)ではなく、外部リンキング(linkmode=external)を強制します。

この変更の理由は、DragonFly BSDのerrno変数がTLS (Thread Local Storage) を使用して宣言されており、その結果生成されるTLSリロケーション(R_386_TLS_GDR_X86_64_TLSGD)を当時のGoリンカが直接処理できなかったためです。netos/userパッケージは、Cgoを介してC標準ライブラリの関数(errnoを使用するもの)に依存する可能性が高いため、これらのパッケージがリンクされる際には、TLSリロケーションを適切に処理できる外部のGCCリンカを使用するように強制することで、リンクエラーを防ぎます。

src/pkg/runtime/cgo/dragonfly.c (新規ファイル) の解説

この新しいファイルは、DragonFly BSDのCgoランタイムが正しく動作するために必要な、特定のグローバルシンボルを提供します。

  • char *environ[1];: 環境変数へのポインタの配列であるenvironを宣言します。これは、C標準ライブラリがプログラムの環境変数にアクセスするために使用するグローバル変数です。Goのランタイムは標準のC crt0.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上で正しく実行され、誤った失敗を避けることができます。

関連リンク

参考にした情報源リンク

  • 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のリンカの内部動作に関する記事やドキュメント)