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

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

このコミットは、Go言語のランタイムにおけるFreeBSDおよびNetBSD向けのビルド修正に関するものです。具体的には、ランタイムの内部構造変更("reorg")後に発生したコンパイルエラーやリンクエラーを解消するための調整が含まれています。

コミット

commit 45ebc064849296cdf51f8e245db30051aaefc744
Author: Russ Cox <rsc@golang.org>
Date:   Thu Mar 14 17:39:39 2013 -0400

    runtime: freebsd, netbsd build fixes after reorg
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/7826044

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

https://github.com/golang/go/commit/45ebc064849296cdf51f8e245db30051aaefc744

元コミット内容

このコミットの元の内容は以下の通りです。

runtime: freebsd, netbsd build fixes after reorg

R=golang-dev
CC=golang-dev
https://golang.org/cl/7826044

これは、Goランタイムの内部再編成("reorg")後に、FreeBSDおよびNetBSD環境でのビルドが失敗する問題を修正するためのコミットであることを示しています。

変更の背景

このコミットの背景には、Goランタイムの内部構造が大きく変更された「reorg」(再編成)があります。Goのランタイムは、ガベージコレクション、スケジューリング、システムコールインターフェースなど、Goプログラムの実行を支える低レベルな機能を提供します。これらの機能はOSに依存する部分が多く、特にシグナルハンドリングやスレッド(LWP: Lightweight Process)の管理はOS固有のAPIを使用します。

「reorg」によって、ランタイムのコードベースが整理され、一部のデータ構造や関数の定義が変更されたと考えられます。この変更により、FreeBSDおよびNetBSDといった特定のOS環境で、以前のコードが新しい構造と整合しなくなり、コンパイルエラーやリンクエラーが発生するようになりました。

具体的には、以下の問題が発生したと推測されます。

  1. Ucontext構造体へのアクセス方法の変更: シグナルハンドリングにおいて、シグナル発生時のCPUレジスタの状態を保持するUcontext構造体へのアクセス方法が変更された可能性があります。以前はポインタのデリファレンスが必要だった箇所が、新しい構造では不要になった、あるいはその逆の変更があったと考えられます。
  2. lwp_tramp関数の宣言不足: NetBSDのLWP(軽量プロセス)関連のコードで、runtime·lwp_trampという関数が使用されているにもかかわらず、その宣言が不足していた可能性があります。ランタイムの再編成により、この関数の宣言が別のファイルに移動したり、新しい場所で明示的に宣言する必要が生じたと考えられます。

このコミットは、これらのビルド問題を解決し、FreeBSDおよびNetBSD上でのGoプログラムの安定した動作を保証するために行われました。

前提知識の解説

このコミットを理解するためには、以下の技術的な概念について理解しておく必要があります。

  • Goランタイム (Go Runtime): Go言語のプログラムは、コンパイル時にGoランタイムとリンクされます。Goランタイムは、ガベージコレクション、ゴルーチンのスケジューリング、チャネル操作、システムコールインターフェースなど、Goプログラムの実行に必要な低レベルな機能を提供します。OSに依存する部分が多く、OSごとに異なる実装が存在します。

  • Ucontext構造体: Unix系OS(FreeBSD, NetBSDなど)におけるシグナルハンドリングで使用されるデータ構造です。シグナルが発生した際に、その時点のCPUレジスタの状態(プログラムカウンタ、スタックポインタなど)やシグナルマスクなどのコンテキスト情報を保存するために使用されます。これにより、シグナルハンドラが実行された後、元の実行コンテキストに正確に戻ることができます。uc_mcontextはその中に含まれるメンバーで、CPU固有のレジスタ情報(マシンコンテキスト)を保持します。

  • mcontext (Machine Context): Ucontext構造体の一部であり、CPUのレジスタの状態を保持する部分です。CPUアーキテクチャ(例: x86, AMD64, ARM)によってその内容は異なります。シグナルハンドラがレジスタの値を読み書きする際に利用されます。

  • SIG_REGSマクロ: Goランタイムのシグナルハンドリングコードで使用されるマクロで、Ucontextポインタからmcontextへのアクセスを抽象化しています。このマクロは、シグナルハンドラ内でCPUレジスタにアクセスするための共通インターフェースを提供します。

  • LWP (Lightweight Process): NetBSDなどの一部のUnix系OSで採用されている、カーネルが管理する軽量な実行単位です。スレッドと似ていますが、より低レベルな概念です。Goランタイムは、ゴルーチンをOSのスレッド(LWP)にマッピングして実行します。

  • lwp_tramp関数: NetBSDのLWP関連のコードで使われる可能性のある関数名です。通常、「tramp」(トランポリン)という用語は、ある関数から別の関数へジャンプするための中間コードや、コンテキストスイッチの際に使用される小さなコード片を指します。lwp_trampは、新しいLWPの開始点や、LWP間のコンテキストスイッチに関連する処理を行う関数であると推測されます。

  • ポインタのデリファレンス (*): C言語において、ポインタが指すメモリ位置にある値にアクセスするための演算子です。例えば、*ptrptrが指すアドレスにある値を取得します。

技術的詳細

このコミットは、主に以下の2つの技術的な問題に対処しています。

  1. SIG_REGSマクロの修正: src/pkg/runtime/signal_freebsd_386.hsrc/pkg/runtime/signal_freebsd_amd64.hsrc/pkg/runtime/signal_freebsd_arm.hの各ファイルで定義されているSIG_REGSマクロが修正されています。 変更前: #define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext) 変更後: #define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)

    この変更は、uc_mcontextが既にポインタ型であるか、あるいは新しいランタイムの構造ではUcontextuc_mcontextメンバーが直接mcontext構造体へのポインタを返すようになったことを示唆しています。以前はuc_mcontextmcontext構造体そのものであり、そのアドレスを取得するために*(デリファレンス)が必要だったか、あるいはuc_mcontextmcontextへのポインタのポインタであった可能性があります。新しい構造では、uc_mcontextが直接mcontextへのポインタを返すため、余分なデリファレンスが不要になった、または誤ったデリファレンスがコンパイルエラーを引き起こすようになったと考えられます。これにより、SIG_REGSマクロはUcontextポインタから直接mcontextポインタを取得するようになります。

  2. runtime·lwp_tramp関数の宣言追加: src/pkg/runtime/os_netbsd.cファイルに、extern void runtime·lwp_tramp(void);という行が追加されています。 これは、NetBSD環境でLWP(軽量プロセス)を扱う際に使用されるruntime·lwp_trampという関数が、このファイル内で使用されているにもかかわらず、その宣言が不足していたために発生したリンクエラーを解消するためのものです。Goランタイムの再編成により、この関数の定義が移動したり、以前は暗黙的に解決されていたものが明示的な宣言を必要とするようになったと考えられます。externキーワードは、この関数が別のコンパイル単位で定義されていることをコンパイラに伝えます。

これらの変更は、Goランタイムの内部的な再編成("reorg")が、OS固有のコードに影響を与え、特にポインタの扱いや関数の可視性に関する調整が必要になったことを明確に示しています。

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

このコミットで変更されたコアとなるコードは以下の4つのファイルです。

  1. src/pkg/runtime/os_netbsd.c

    --- a/src/pkg/runtime/os_netbsd.c
    +++ b/src/pkg/runtime/os_netbsd.c
    @@ -30,6 +30,7 @@ extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void
     extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint);
     extern int32 runtime·lwp_unpark(int32 lwp, void *hint);
     extern int32 runtime·lwp_self(void);
    +extern void runtime·lwp_tramp(void);
     
     // From NetBSD\'s <sys/sysctl.h>\
     #define\tCTL_HW\t6
    
  2. src/pkg/runtime/signal_freebsd_386.h

    --- a/src/pkg/runtime/signal_freebsd_386.h
    +++ b/src/pkg/runtime/signal_freebsd_386.h
    @@ -2,7 +2,7 @@
     // Use of this source code is governed by a BSD-style
     // license that can be found in the LICENSE file.
     
    -#define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext)
    +#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
     
     #define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).mc_eax)
     #define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).mc_ebx)
    
  3. src/pkg/runtime/signal_freebsd_amd64.h

    --- a/src/pkg/runtime/signal_freebsd_amd64.h
    +++ b/src/pkg/runtime/signal_freebsd_amd64.h
    @@ -2,7 +2,7 @@
     // Use of this source code is governed by a BSD-style
     // license that can be found in the LICENSE file.\n
     
    -#define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext)
    +#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
     
     #define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).mc_rax)
     #define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).mc_rbx)
    
  4. src/pkg/runtime/signal_freebsd_arm.h

    --- a/src/pkg/runtime/signal_freebsd_arm.h
    +++ b/src/pkg/runtime/signal_freebsd_arm.h
    @@ -2,7 +2,7 @@
     // Use of this source code is governed by a BSD-style
     // license that can be found in the LICENSE file.
     
    -#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
    +#define SIG_REGS(ctxt) (((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
     
     #define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[0])
     #define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[1])
    

コアとなるコードの解説

src/pkg/runtime/os_netbsd.c の変更

このファイルはNetBSD固有のランタイムコードを含んでいます。追加された行 extern void runtime·lwp_tramp(void); は、runtime·lwp_trampという名前の関数が外部で定義されていることをコンパイラに伝えます。Goランタイムの再編成により、この関数が使用される場所と定義される場所の間に依存関係の不整合が生じたため、明示的な宣言が必要になったと考えられます。これにより、リンカがこの関数を正しく解決できるようになり、NetBSD上でのビルドエラーが解消されます。

src/pkg/runtime/signal_freebsd_*.h ファイル群の変更

これらのファイルは、FreeBSDにおける異なるCPUアーキテクチャ(386, AMD64, ARM)向けのシグナルハンドリング関連の定義を含んでいます。共通して変更されているのはSIG_REGSマクロの定義です。

変更前: #define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext) 変更後: #define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)

この変更は、Ucontext構造体内のuc_mcontextメンバーの型またはそのアクセス方法が変更されたことを示しています。

  • 変更前: uc_mcontextmcontext構造体そのものであったか、あるいはmcontextへのポインタのポインタであったため、*演算子によるデリファレンスが必要でした。
  • 変更後: uc_mcontextが直接mcontext構造体へのポインタを返すようになったため、*演算子によるデリファレンスが不要になりました。もし変更後も*が残っていた場合、mcontextポインタをさらにデリファレンスしようとして、不正なメモリアクセスやコンパイルエラーを引き起こす可能性があります。

この修正により、シグナルハンドラがUcontextからCPUレジスタ情報(mcontext)を正しく取得できるようになり、FreeBSD上でのシグナルハンドリングが正常に機能するようになります。これは、ランタイムの内部的なデータ構造の変更に、OS固有のヘッダーファイルが追従した典型的な例と言えます。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特に src/pkg/runtime ディレクトリ)
  • Unix系OSにおける ucontext.h およびシグナルハンドリングに関するドキュメント
  • NetBSDのLWPに関するドキュメント
  • Go言語のコミット履歴と関連する議論 (Gerrit)
  • Go言語のメーリングリスト (golang-dev) のアーカイブ
  • Ucontextに関する一般的な情報: https://man7.org/linux/man-pages/man3/getcontext.3.html (Linuxのmanページですが、概念は共通しています)
  • FreeBSDのシグナルハンドリングに関する情報: https://www.freebsd.org/cgi/man.cgi?query=sigaction&sektion=2
  • NetBSDのLWPに関する情報: https://www.netbsd.org/docs/guide/en/chap-lwp.html
  • Goのランタイム再編成に関する情報 (当時のメーリングリストや設計ドキュメント): 2013年3月頃のGoランタイムの大きな変更に関する情報は、当時のGo開発者メーリングリスト(golang-dev)のアーカイブや、Goの設計ドキュメント(もし公開されていれば)に詳細が記載されている可能性があります。具体的な「reorg」の内容については、当時のGoのリリースノートや開発ブログなども参考になります。