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

[インデックス 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のランタイムでは、現在のゴルーチンやスケジューラに関する情報(gmポインタ)をスレッドローカルストレージに格納することが一般的です。CgoがGoとCの間でコンテキストを切り替える際、これらのポインタを正しく設定・復元することが重要になります。

技術的詳細

このコミットは、NetBSD上でのCgoの動作を可能にするために、以下の主要な技術的変更を加えています。

  1. Cgo有効化のビルド設定: src/pkg/go/build/build.go内のcgoEnabledマップに、"netbsd/386": true"netbsd/amd64": trueを追加しています。これにより、GoのビルドシステムがNetBSDの386およびamd64アーキテクチャでCgoを有効にするべきだと認識するようになります。

  2. 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スレッド)ポインタをスレッドローカルストレージに設定します。
    • 特に注目すべきは、スレッドローカルストレージへのgmポインタの設定方法です。NetBSD/ELF環境では、%gsレジスタ(386の場合)または%fsレジスタ(amd64の場合)をベースとしたオフセットでTLSにアクセスします。アセンブリ命令(movl %0, %%gs:-8など)を用いて、これらのポインタを特定のメモリ位置に書き込んでいます。これは、GoランタイムがCコードからGoコードにコールバックする際に、正しいGoルーチンコンテキストを復元するために不可欠です。
  3. 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を介して名前解決を行う際に必要となります。
  4. ビルドタグの更新:

    • src/pkg/net/cgo_unix.go および src/pkg/os/user/lookup_unix.go のビルドタグにnetbsdが追加されています。これにより、これらのファイルがNetBSDプラットフォームでもコンパイルされ、Cgoを利用したネットワーク機能やユーザー情報ルックアップ機能がNetBSDで有効になります。
  5. テストスクリプトの調整:

    • doc/progs/runスクリプトが変更され、NetBSD上では特定のCgoテスト(cgo1, cgo2, cgo3, cgo4)が実行されないように設定されています。これは、NetBSD環境におけるsrandom関数のシグネチャの違いや、Cgoが標準出力を正しく扱えないという既知の問題に対応するためです。これは、CgoのNetBSDサポートがまだ初期段階であり、一部の機能に互換性の問題があることを示唆しています。

これらの変更により、GoプログラムはNetBSD上でCgoを介してCライブラリと連携できるようになり、Go言語のNetBSDサポートが大幅に強化されます。

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

このコミットにおけるコアとなるコードの変更箇所は、主に以下のファイルに集中しています。

  1. src/pkg/go/build/build.go:

    • cgoEnabledマップに"netbsd/386": true"netbsd/amd64": trueが追加され、NetBSDの386およびamd64アーキテクチャでCgoが有効化されるようにビルド設定が更新されました。
  2. 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関数: 新しいスレッドのエントリポイント。
  3. 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関数: 新しいスレッドのエントリポイント。
  4. misc/cgo/stdio/stdio_netbsd.go (新規追加):

    • NetBSD向けのCgoによる標準入出力(Stdout, Stderr)へのアクセスを提供するGoファイル。
    • C.__sF[1]C.__sF[2]unsafe.PointerでGoのFile型にキャストして公開。
  5. src/pkg/net/cgo_netbsd.go (新規追加):

    • NetBSD向けのCgoによるネットワーク関連機能を提供するGoファイル。
    • cgoAddrInfoFlags()関数: getaddrinfoで使用するAI_CANONNAME, AI_V4MAPPED, AI_ALLフラグを返す。
  6. 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):
        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)
        );
        
        NetBSD/ELFの386環境では、%gsセグメントレジスタをベースとして、オフセット-8-4にそれぞれGoのg(現在のゴルーチン)とm(現在のOSスレッド)ポインタを格納します。これは、GoランタイムがCgoコールバックなどでGoコードに切り替える際に、正しいゴルーチンコンテキストを復元するために必要です。
      • amd64版 (gcc_netbsd_amd64.c):
        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)
        );
        
        NetBSD/ELFのamd64環境では、%fsセグメントレジスタをベースとして、オフセット-16-8にそれぞれgmポインタを格納します。64ビットアーキテクチャなので、movq(move quadword)命令を使用し、オフセットも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言語のソースコード (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のランタイムでは、現在のゴルーチンやスケジューラに関する情報(gmポインタ)をスレッドローカルストレージに格納することが一般的です。CgoがGoとCの間でコンテキストを切り替える際、これらのポインタを正しく設定・復元することが重要になります。

技術的詳細

このコミットは、NetBSD上でのCgoの動作を可能にするために、以下の主要な技術的変更を加えています。

  1. Cgo有効化のビルド設定: src/pkg/go/build/build.go内のcgoEnabledマップに、"netbsd/386": true"netbsd/amd64": trueを追加しています。これにより、GoのビルドシステムがNetBSDの386およびamd64アーキテクチャでCgoを有効にするべきだと認識するようになります。

  2. 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スレッド)ポインタをスレッドローカルストレージに設定します。
    • 特に注目すべきは、スレッドローカルストレージへのgmポインタの設定方法です。NetBSD/ELF環境では、%gsレジスタ(386の場合)または%fsレジスタ(amd64の場合)をベースとしたオフセットでTLSにアクセスします。アセンブリ命令(movl %0, %%gs:-8など)を用いて、これらのポインタを特定のメモリ位置に書き込んでいます。これは、GoランタイムがCコードからGoコードにコールバックする際に、正しいGoルーチンコンテキストを復元するために不可欠です。
  3. 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を介して名前解決を行う際に必要となります。
  4. ビルドタグの更新:

    • src/pkg/net/cgo_unix.go および src/pkg/os/user/lookup_unix.go のビルドタグにnetbsdが追加されています。これにより、これらのファイルがNetBSDプラットフォームでもコンパイルされ、Cgoを利用したネットワーク機能やユーザー情報ルックアップ機能がNetBSDで有効になります。
  5. テストスクリプトの調整:

    • doc/progs/runスクリプトが変更され、NetBSD上では特定のCgoテスト(cgo1, cgo2, cgo3, cgo4)が実行されないように設定されています。これは、NetBSD環境におけるsrandom関数のシグネチャの違いや、Cgoが標準出力を正しく扱えないという既知の問題に対応するためです。これは、CgoのNetBSDサポートがまだ初期段階であり、一部の機能に互換性の問題があることを示唆しています。

これらの変更により、GoプログラムはNetBSD上でCgoを介してCライブラリと連携できるようになり、Go言語のNetBSDサポートが大幅に強化されます。

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

このコミットにおけるコアとなるコードの変更箇所は、主に以下のファイルに集中しています。

  1. src/pkg/go/build/build.go:

    • cgoEnabledマップに"netbsd/386": true"netbsd/amd64": trueが追加され、NetBSDの386およびamd64アーキテクチャでCgoが有効化されるようにビルド設定が更新されました。
  2. 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関数: 新しいスレッドのエントリポイント。
  3. 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関数: 新しいスレッドのエントリポイント。
  4. misc/cgo/stdio/stdio_netbsd.go (新規追加):

    • NetBSD向けのCgoによる標準入出力(Stdout, Stderr)へのアクセスを提供するGoファイル。
    • C.__sF[1]C.__sF[2]unsafe.PointerでGoのFile型にキャストして公開。
  5. src/pkg/net/cgo_netbsd.go (新規追加):

    • NetBSD向けのCgoによるネットワーク関連機能を提供するGoファイル。
    • cgoAddrInfoFlags()関数: getaddrinfoで使用するAI_CANONNAME, AI_V4MAPPED, AI_ALLフラグを返す。
  6. 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):
        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)
        );
        
        NetBSD/ELFの386環境では、%gsセグメントレジスタをベースとして、オフセット-8-4にそれぞれGoのg(現在のゴルーチン)とm(現在のOSスレッド)ポインタを格納します。これは、GoランタイムがCgoコールバックなどでGoコードに切り替える際に、正しいゴルーチンコンテキストを復元するために必要です。
      • amd64版 (gcc_netbsd_amd64.c):
        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)
        );
        
        NetBSD/ELFのamd64環境では、%fsセグメントレジスタをベースとして、オフセット-16-8にそれぞれgmポインタを格納します。64ビットアーキテクチャなので、movq(move quadword)命令を使用し、オフセットも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言語のソースコード (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のシステムプログラミングに関するドキュメント