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

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

このコミットは、Go言語のランタイムとビルドシステムにおいて、FreeBSD/ARMアーキテクチャでのCgo(C言語との相互運用機能)を再有効化することを目的としています。具体的には、go/buildパッケージのCgo有効化マップにfreebsd/armを追加し、runtime/cgoパッケージ内のFreeBSD/ARM向けCgoサポートファイル(gcc_freebsd_arm.c)に、スレッドローカルストレージ (TLS) の読み取りに関する修正を加えています。

コミット

commit 092b7cfb08f6bc843050c71f1aae9ffbf4b512a5
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Sat Mar 23 03:21:30 2013 +0800

    runtime/cgo, go/build: re-enable cgo for FreeBSD/ARM.
    
    R=dave, rsc
    CC=golang-dev
    https://golang.org/cl/7970043

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

https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5

元コミット内容

diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index f4a84b8a7f..dc3669c1df 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
 	"darwin/amd64":  true,
 	"freebsd/386":   true,
 	"freebsd/amd64": true,
+	"freebsd/arm":   true,
 	"linux/386":     true,
 	"linux/amd64":   true,
 	"linux/arm":     true,
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 3bcb0b2701..73c990c28f 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
 // 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 <machine/sysarch.h>
 #include <pthread.h>\n #include <string.h>\n #include "libcgo.h"\n@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));\n void\n __aeabi_read_tp(void)\n {\n-\t// read @ 0xffff1000\n \t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS\n+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000\n+\t\t// GCC inline asm doesn\'t provide a way to provide a constant\n+\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value\n+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000\n+#error Wrong ARM_TP_ADDRESS!\n+#endif\n \t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else\n+\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif\n \t\t\"mov pc, lr\\n\\t\"\n \t);\n }\n```

## 変更の背景

Go言語は、様々なプラットフォームやアーキテクチャをサポートすることを目指しています。Cgoは、GoプログラムからC言語のコードを呼び出すための重要な機能であり、システムコールや既存のCライブラリを利用する際に不可欠です。FreeBSD/ARM環境においてCgoが以前は無効化されていたか、あるいは適切に機能していなかった可能性があります。

このコミットの背景には、FreeBSD/ARM環境でのGo言語の利用を促進し、Cgoを必要とするアプリケーションがこのプラットフォームで動作できるようにするという目的があります。特に、スレッドローカルストレージ (TLS) の扱いがFreeBSD/ARMの特定のバージョンや設定で問題となっていた可能性があり、その問題を解決することでCgoの安定動作を保証しようとしています。`__aeabi_read_tp`関数は、ARMアーキテクチャにおけるTLSポインタの読み取りに関連するものであり、その実装がFreeBSD/ARMの特定の環境に適合していなかったことが、Cgo無効化の一因であったと考えられます。

## 前提知識の解説

### Cgo

Cgoは、Go言語のプログラムからC言語の関数を呼び出したり、C言語のデータ型を扱ったりするためのGoの機能です。Goのコード内で`import "C"`と記述することでCgoが有効になり、C言語のコードをGoのソースファイル内に直接記述したり、既存のCライブラリをリンクしたりすることができます。Cgoは、OSのシステムコールを直接叩く必要がある場合や、既存の高性能なCライブラリ(例えばグラフィックライブラリや暗号ライブラリなど)を利用したい場合に非常に有用です。

### FreeBSD/ARM

FreeBSDは、UNIXライクなオペレーティングシステムの一つで、堅牢性と高性能を特徴としています。ARMは、Advanced RISC Machineの略で、低消費電力と高性能を両立するプロセッサアーキテクチャです。スマートフォン、タブレット、組み込みシステム、そして近年ではサーバーなど、幅広いデバイスで利用されています。FreeBSD/ARMは、FreeBSDオペレーティングシステムがARMアーキテクチャ上で動作する環境を指します。

### スレッドローカルストレージ (TLS)

スレッドローカルストレージ (TLS) は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを持つための仕組みです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自の値を保持できます。これは、スレッドセーフなプログラミングや、スレッドごとに異なるコンテキストを管理する際に不可欠です。

ARMアーキテクチャでは、TLSポインタの取得方法が複数存在し、OSやコンパイラのバージョンによって異なる場合があります。`__aeabi_read_tp`は、ARM Embedded Application Binary Interface (EABI) で定義されている、TLSポインタを読み取るための関数です。この関数の正確な実装は、ターゲットとなるシステム(この場合はFreeBSD/ARM)のTLSメカニズムに依存します。

### `go/build`パッケージ

`go/build`パッケージは、GoのビルドシステムがGoソースファイルを解析し、ビルドタグ、パッケージパス、Cgoの有効/無効などの情報を取得するために使用されます。このパッケージは、Goのツールチェインがどのようにソースコードを解釈し、コンパイルするかを決定する上で中心的な役割を果たします。`cgoEnabled`マップは、特定のオペレーティングシステムとアーキテクチャの組み合わせ(例: `linux/amd64`、`freebsd/arm`)に対してCgoが有効であるかどうかを定義します。

## 技術的詳細

このコミットの技術的な核心は、FreeBSD/ARM環境におけるTLSポインタの取得方法の調整にあります。

以前の`gcc_freebsd_arm.c`の実装では、`__aeabi_read_tp`関数内でTLSポインタを`0xffff1000`という固定アドレスから読み取ろうとしていました。これは、特定のFreeBSD/ARM環境では有効な方法であったかもしれませんが、より一般的な、あるいは異なるバージョンのFreeBSD/ARMでは問題を引き起こす可能性がありました。

新しい実装では、`ARM_TP_ADDRESS`というプリプロセッサマクロを導入しています。
*   `#ifdef ARM_TP_ADDRESS`ブロック内では、`ARM_TP_ADDRESS`が定義されている場合に、その値が`0xffff1000`であることをコンパイル時にチェックしています。これは、特定の環境でTLSポインタが固定アドレスに配置されていることを前提とした最適化または特定の要件に対応するためのものです。もし`ARM_TP_ADDRESS`が定義されていても、その値が`0xffff1000`でなければコンパイルエラーを発生させることで、誤ったアドレスが使用されることを防いでいます。
*   `#else`ブロックでは、`ARM_TP_ADDRESS`が定義されていない場合(つまり、TLSポインタが固定アドレスにない場合や、より汎用的な方法が必要な場合)に、ARMアーキテクチャのCP15コプロセッサのレジスタからTLSポインタを読み取る命令`mrc p15, 0, r0, c13, c0, 3`を使用しています。この命令は、ARMv6以降のアーキテクチャでTLSレジスタ(TPIDRURWまたはTPIDRURO)からスレッドIDまたはTLSポインタを読み取るための標準的な方法です。

この変更により、FreeBSD/ARM環境におけるTLSポインタの取得がより堅牢になり、異なるFreeBSDのバージョンやARMプロセッサのバリエーションに対応できるようになります。TLSポインタの正確な取得は、CgoがGoとCの間でデータを安全にやり取りし、特にスレッドローカルなコンテキストを正しく管理するために不可欠です。

また、`src/pkg/go/build/build.go`の変更は、Goのビルドシステムに対して、FreeBSD/ARM環境でCgoが利用可能になったことを明示的に通知するものです。これにより、Goのツールチェインは、このプラットフォームでCgoを使用するGoプログラムを正しくビルドできるようになります。

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

1.  **`src/pkg/go/build/build.go`**:
    ```diff
    --- a/src/pkg/go/build/build.go
    +++ b/src/pkg/go/build/build.go
    @@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
     	"darwin/amd64":  true,
     	"freebsd/386":   true,
     	"freebsd/amd64": true,
    +	"freebsd/arm":   true,
     	"linux/386":     true,
     	"linux/amd64":   true,
     	"linux/arm":     true,
    ```
    `cgoEnabled`マップに`"freebsd/arm": true,`が追加されました。

2.  **`src/pkg/runtime/cgo/gcc_freebsd_arm.c`**:
    ```diff
    --- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
    +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
    @@ -2,6 +2,8 @@
     // 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 <machine/sysarch.h>
     #include <pthread.h>
     #include <string.h>
     #include "libcgo.h"
    @@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
     void
     __aeabi_read_tp(void)
     {\n-\t// read @ 0xffff1000
     \t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS
    +\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
    +\t\t// GCC inline asm doesn\'t provide a way to provide a constant
    +\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value
    +\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000
    +#error Wrong ARM_TP_ADDRESS!
    +#endif
     \t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else
    +\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif
     \t\t\"mov pc, lr\\n\\t\"\n     );\n }
    ```
    `__aeabi_read_tp`関数の実装が変更され、`ARM_TP_ADDRESS`マクロを用いた条件付きコンパイルと、CP15コプロセッサからのTLSポインタ読み取りが追加されました。また、必要なヘッダーファイル`<sys/types.h>`と`<machine/sysarch.h>`がインクルードされています。

## コアとなるコードの解説

### `src/pkg/go/build/build.go`の変更

`cgoEnabled`マップは、Goのビルドプロセスにおいて、どのOS/アーキテクチャの組み合わせでCgoがサポートされているかを定義します。このマップに`"freebsd/arm": true`を追加することで、GoのツールチェインはFreeBSD/ARM環境でCgoを有効にしてビルドを行うことを許可するようになります。これは、Cgoを利用するGoプログラムがFreeBSD/ARM上でコンパイルされるための前提条件となります。

### `src/pkg/runtime/cgo/gcc_freebsd_arm.c`の変更

このファイルは、FreeBSD/ARM環境におけるCgoランタイムの低レベルな部分、特にCgoがGoランタイムとCコードの間でどのように連携するかを扱います。

`__aeabi_read_tp`関数は、ARMアーキテクチャにおいてスレッドローカルストレージ (TLS) のポインタを読み取るためのABI (Application Binary Interface) 規定の関数です。TLSは、各スレッドが独自のデータを持つことを可能にする重要なメカニズムであり、CgoがCライブラリと連携する際に、スレッド固有のコンテキストを正しく管理するために不可欠です。

変更前は、TLSポインタを`0xffff1000`という固定アドレスから読み取るアセンブリ命令がハードコードされていました。これは、特定のFreeBSD/ARMのセットアップでは機能するかもしれませんが、TLSの配置が異なるシステムでは問題を引き起こす可能性があります。

変更後は、より柔軟で堅牢な方法が導入されました。
*   **`#ifdef ARM_TP_ADDRESS`**: このプリプロセッサディレクティブは、`ARM_TP_ADDRESS`というマクロが定義されているかどうかをチェックします。このマクロは、コンパイル時にTLSポインタの固定アドレスが定義されている場合に利用されます。
    *   **`#if ARM_TP_ADDRESS != 0xffff1000`**: もし`ARM_TP_ADDRESS`が定義されていても、その値が期待される`0xffff1000`と異なる場合、コンパイルエラーを発生させます。これは、ハードコードされたアドレスが誤っている場合に早期に問題を検出するための安全策です。
    *   **`"ldr r0, =0xffff1000\\n\\t" "ldr r0, [r0]\\n\\t"`**: `ARM_TP_ADDRESS`が`0xffff1000`であると確認された場合、引き続きこの固定アドレスからTLSポインタを読み取ります。これは、特定の環境でのパフォーマンス最適化や、特定のTLS実装への対応のために残されている可能性があります。
*   **`#else`**: `ARM_TP_ADDRESS`が定義されていない場合、より汎用的な方法が使用されます。
    *   **`"mrc p15, 0, r0, c13, c0, 3\\n\\t"`**: このアセンブリ命令は、ARMアーキテクチャのCP15コプロセッサからレジスタを読み取るためのものです。具体的には、`c13, c0, 3`はTLSポインタを保持するシステムレジスタ(通常はTPIDRURWまたはTPIDRURO)を指します。この命令を使用することで、OSやコンパイラのバージョンに依存しない、より標準的な方法でTLSポインタを取得できます。

この修正により、FreeBSD/ARM環境におけるCgoのTLS処理が改善され、GoプログラムがC言語のコードとより安定して連携できるようになります。

## 関連リンク

*   **Gerrit Change-ID**: `https://golang.org/cl/7970043` (GoプロジェクトのコードレビューシステムであるGerritへのリンク。このコミットのレビュープロセスや関連する議論の詳細が確認できます。)

## 参考にした情報源リンク

*   **ARM Architecture Reference Manual**: ARMプロセッサのCP15コプロセッサとTLSレジスタに関する詳細な情報。
*   **FreeBSD Documentation**: FreeBSDにおけるTLSの実装に関する情報。
*   **Go Language Documentation (Cgo)**: Go言語のCgo機能に関する公式ドキュメント。
*   **ARM EABI (Embedded Application Binary Interface) Specification**: `__aeabi_read_tp`のようなABI規定関数の詳細。
# [インデックス 15901] ファイルの概要

このコミットは、Go言語のランタイムとビルドシステムにおいて、FreeBSD/ARMアーキテクチャでのCgo(C言語との相互運用機能)を再有効化することを目的としています。具体的には、`go/build`パッケージのCgo有効化マップに`freebsd/arm`を追加し、`runtime/cgo`パッケージ内のFreeBSD/ARM向けCgoサポートファイル(`gcc_freebsd_arm.c`)に、スレッドローカルストレージ (TLS) の読み取りに関する修正を加えています。

## コミット

commit 092b7cfb08f6bc843050c71f1aae9ffbf4b512a5 Author: Shenghou Ma minux.ma@gmail.com Date: Sat Mar 23 03:21:30 2013 +0800

runtime/cgo, go/build: re-enable cgo for FreeBSD/ARM.

R=dave, rsc
CC=golang-dev
https://golang.org/cl/7970043

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

[https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5](https://github.com/golang/go/commit/092b7cfb08f6bc843050c71f1aae9ffbf4b512a5)

## 元コミット内容

```diff
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index f4a84b8a7f..dc3669c1df 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
 	"darwin/amd64":  true,
 	"freebsd/386":   true,
 	"freebsd/amd64": true,
+	"freebsd/arm":   true,
 	"linux/386":     true,
 	"linux/amd64":   true,
 	"linux/arm":     true,
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 3bcb0b2701..73c990c28f 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
 // 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 <machine/sysarch.h>
 #include <pthread.h>
 #include <string.h>
 #include "libcgo.h"
@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
 void
 __aeabi_read_tp(void)
 {\n-\t// read @ 0xffff1000
 \t__asm__ __volatile__ (\n+#ifdef ARM_TP_ADDRESS
+\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+\t\t// GCC inline asm doesn\'t provide a way to provide a constant
+\t\t// to "ldr r0, =??\" pseudo instruction, so we hardcode the value
+\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000
+#error Wrong ARM_TP_ADDRESS!
+#endif
 \t\t\"ldr r0, =0xffff1000\\n\\t\"\n \t\t\"ldr r0, [r0]\\n\\t\"\n+#else
+\t\t\"mrc p15, 0, r0, c13, c0, 3\\n\\t\"\n+#endif
 \t\t\"mov pc, lr\\n\\t\"\n     );\n }

変更の背景

Go言語は、様々なプラットフォームやアーキテクチャをサポートすることを目指しています。Cgoは、GoプログラムからC言語のコードを呼び出したり、既存のCライブラリを利用する際に不可欠な機能です。FreeBSD/ARM環境においてCgoが以前は無効化されていたか、あるいは適切に機能していなかった可能性があります。

このコミットの背景には、FreeBSD/ARM環境でのGo言語の利用を促進し、Cgoを必要とするアプリケーションがこのプラットフォームで動作できるようにするという目的があります。特に、スレッドローカルストレージ (TLS) の扱いがFreeBSD/ARMの特定のバージョンや設定で問題となっていた可能性があり、その問題を解決することでCgoの安定動作を保証しようとしています。__aeabi_read_tp関数は、ARMアーキテクチャにおけるTLSポインタの読み取りに関連するものであり、その実装がFreeBSD/ARMの特定の環境に適合していなかったことが、Cgo無効化の一因であったと考えられます。

前提知識の解説

Cgo

Cgoは、Go言語のプログラムからC言語の関数を呼び出したり、C言語のデータ型を扱ったりするためのGoの機能です。Goのコード内でimport "C"と記述することでCgoが有効になり、C言語のコードをGoのソースファイル内に直接記述したり、既存のCライブラリをリンクしたりすることができます。Cgoは、OSのシステムコールを直接叩く必要がある場合や、既存の高性能なCライブラリ(例えばグラフィックライブラリや暗号ライブラリなど)を利用したい場合に非常に有用です。

FreeBSD/ARM

FreeBSDは、UNIXライクなオペレーティングシステムの一つで、堅牢性と高性能を特徴としています。ARMは、Advanced RISC Machineの略で、低消費電力と高性能を両立するプロセッサアーキテクチャです。スマートフォン、タブレット、組み込みシステム、そして近年ではサーバーなど、幅広いデバイスで利用されています。FreeBSD/ARMは、FreeBSDオペレーティングシステムがARMアーキテクチャ上で動作する環境を指します。

スレッドローカルストレージ (TLS)

スレッドローカルストレージ (TLS) は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを持つための仕組みです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自の値を保持できます。これは、スレッドセーフなプログラミングや、スレッドごとに異なるコンテキストを管理する際に不可欠です。

ARMアーキテクチャでは、TLSポインタの取得方法が複数存在し、OSやコンパイラのバージョンによって異なる場合があります。__aeabi_read_tpは、ARM Embedded Application Binary Interface (EABI) で定義されている、TLSポインタを読み取るための関数です。この関数の正確な実装は、ターゲットとなるシステム(この場合はFreeBSD/ARM)のTLSメカニズムに依存します。

go/buildパッケージ

go/buildパッケージは、GoのビルドシステムがGoソースファイルを解析し、ビルドタグ、パッケージパス、Cgoの有効/無効などの情報を取得するために使用されます。このパッケージは、Goのツールチェインがどのようにソースコードを解釈し、コンパイルするかを決定する上で中心的な役割を果たします。cgoEnabledマップは、特定のオペレーティングシステムとアーキテクチャの組み合わせ(例: linux/amd64freebsd/arm)に対してCgoが有効であるかどうかを定義します。

技術的詳細

このコミットの技術的な核心は、FreeBSD/ARM環境におけるTLSポインタの取得方法の調整にあります。

以前のgcc_freebsd_arm.cの実装では、__aeabi_read_tp関数内でTLSポインタを0xffff1000という固定アドレスから読み取ろうとしていました。これは、特定のFreeBSD/ARM環境では有効な方法であったかもしれませんが、より一般的な、あるいは異なるバージョンのFreeBSD/ARMでは問題を引き起こす可能性がありました。

新しい実装では、ARM_TP_ADDRESSというプリプロセッサマクロを導入しています。

  • #ifdef ARM_TP_ADDRESSブロック内では、ARM_TP_ADDRESSが定義されている場合に、その値が0xffff1000であることをコンパイル時にチェックしています。これは、特定の環境でTLSポインタが固定アドレスに配置されていることを前提とした最適化または特定の要件に対応するためのものです。もしARM_TP_ADDRESSが定義されていても、その値が0xffff1000でなければコンパイルエラーを発生させることで、誤ったアドレスが使用されることを防いでいます。
  • #elseブロックでは、ARM_TP_ADDRESSが定義されていない場合(つまり、TLSポインタが固定アドレスにない場合や、より汎用的な方法が必要な場合)に、ARMアーキテクチャのCP15コプロセッサのレジスタからTLSポインタを読み取る命令mrc p15, 0, r0, c13, c0, 3を使用しています。この命令は、ARMv6以降のアーキテクチャでTLSレジスタ(TPIDRURWまたはTPIDRURO)からスレッドIDまたはTLSポインタを読み取るための標準的な方法です。

この変更により、FreeBSD/ARM環境におけるTLSポインタの取得がより堅牢になり、異なるFreeBSDのバージョンやARMプロセッサのバリエーションに対応できるようになります。TLSポインタの正確な取得は、CgoがGoとCの間でデータを安全にやり取りし、特にスレッドローカルなコンテキストを正しく管理するために不可欠です。

また、src/pkg/go/build/build.goの変更は、Goのビルドシステムに対して、FreeBSD/ARM環境でCgoが利用可能になったことを明示的に通知するものです。これにより、Goのツールチェインは、このプラットフォームでCgoを使用するGoプログラムを正しくビルドできるようになります。

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

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

    --- a/src/pkg/go/build/build.go
    +++ b/src/pkg/go/build/build.go
    @@ -262,6 +262,7 @@ var cgoEnabled = map[string]bool{
     	"darwin/amd64":  true,
     	"freebsd/386":   true,
     	"freebsd/amd64": true,
    +	"freebsd/arm":   true,
     	"linux/386":     true,
     	"linux/amd64":   true,
     	"linux/arm":     true,
    

    cgoEnabledマップに"freebsd/arm": true,が追加されました。

  2. src/pkg/runtime/cgo/gcc_freebsd_arm.c:

    --- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
    +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
    @@ -2,6 +2,8 @@
     // 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 <machine/sysarch.h>
     #include <pthread.h>
     #include <string.h>
     #include "libcgo.h"
    @@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
     void
     __aeabi_read_tp(void)
     {\n-\t// read @ 0xffff1000
    

\t__asm__ volatile (\n+#ifdef ARM_TP_ADDRESS +\t\t// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000 +\t\t// GCC inline asm doesn't provide a way to provide a constant +\t\t// to "ldr r0, =??" pseudo instruction, so we hardcode the value +\t\t// and check it with cpp.\n+#if ARM_TP_ADDRESS != 0xffff1000 +#error Wrong ARM_TP_ADDRESS! +#endif \t\t"ldr r0, =0xffff1000\n\t"\n \t\t"ldr r0, [r0]\n\t"\n+#else +\t\t"mrc p15, 0, r0, c13, c0, 3\n\t"\n+#endif \t\t"mov pc, lr\n\t"\n );\n } ``` __aeabi_read_tp関数の実装が変更され、ARM_TP_ADDRESSマクロを用いた条件付きコンパイルと、CP15コプロセッサからのTLSポインタ読み取りが追加されました。また、必要なヘッダーファイル<sys/types.h><machine/sysarch.h>がインクルードされています。

コアとなるコードの解説

src/pkg/go/build/build.goの変更

cgoEnabledマップは、Goのビルドプロセスにおいて、どのOS/アーキテクチャの組み合わせでCgoがサポートされているかを定義します。このマップに"freebsd/arm": trueを追加することで、GoのツールチェインはFreeBSD/ARM環境でCgoを有効にしてビルドを行うことを許可するようになります。これは、Cgoを利用するGoプログラムがFreeBSD/ARM上でコンパイルされるための前提条件となります。

src/pkg/runtime/cgo/gcc_freebsd_arm.cの変更

このファイルは、FreeBSD/ARM環境におけるCgoランタイムの低レベルな部分、特にCgoがGoランタイムとCコードの間でどのように連携するかを扱います。

__aeabi_read_tp関数は、ARMアーキテクチャにおいてスレッドローカルストレージ (TLS) のポインタを読み取るためのABI (Application Binary Interface) 規定の関数です。TLSは、各スレッドが独自のデータを持つことを可能にする重要なメカニズムであり、CgoがCライブラリと連携する際に、スレッド固有のコンテキストを正しく管理するために不可欠です。

変更前は、TLSポインタを0xffff1000という固定アドレスから読み取るアセンブリ命令がハードコードされていました。これは、特定のFreeBSD/ARMのセットアップでは機能するかもしれませんが、TLSの配置が異なるシステムでは問題を引き起こす可能性があります。

変更後は、より柔軟で堅牢な方法が導入されました。

  • #ifdef ARM_TP_ADDRESS: このプリプロセッサディレクティブは、ARM_TP_ADDRESSというマクロが定義されているかどうかをチェックします。このマクロは、コンパイル時にTLSポインタの固定アドレスが定義されている場合に利用されます。
    • #if ARM_TP_ADDRESS != 0xffff1000: もしARM_TP_ADDRESSが定義されていても、その値が期待される0xffff1000と異なる場合、コンパイルエラーを発生させます。これは、ハードコードされたアドレスが誤っている場合に早期に問題を検出するための安全策です。
    • "ldr r0, =0xffff1000\\n\\t" "ldr r0, [r0]\\n\\t": ARM_TP_ADDRESS0xffff1000であると確認された場合、引き続きこの固定アドレスからTLSポインタを読み取ります。これは、特定の環境でのパフォーマンス最適化や、特定のTLS実装への対応のために残されている可能性があります。
  • #else: ARM_TP_ADDRESSが定義されていない場合、より汎用的な方法が使用されます。
    • "mrc p15, 0, r0, c13, c0, 3\\n\\t": このアセンブリ命令は、ARMアーキテクチャのCP15コプロセッサからレジスタを読み取るためのものです。具体的には、c13, c0, 3はTLSポインタを保持するシステムレジスタ(通常はTPIDRURWまたはTPIDRURO)を指します。この命令を使用することで、OSやコンパイラのバージョンに依存しない、より標準的な方法でTLSポインタを取得できます。

この修正により、FreeBSD/ARM環境におけるCgoのTLS処理が改善され、GoプログラムがC言語のコードとより安定して連携できるようになります。

関連リンク

  • Gerrit Change-ID: https://golang.org/cl/7970043 (GoプロジェクトのコードレビューシステムであるGerritへのリンク。このコミットのレビュープロセスや関連する議論の詳細が確認できます。)

参考にした情報源リンク