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

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

コミット

commit 0e5cd9d3f6ee8e0828cf29152d7180f70a00d6c7
Author: Joel Sing <jsing@google.com>
Date:   Tue Nov 8 11:43:58 2011 -0500

    runtime: add timespec definition for freebsd
    
    R=golang-dev, devon.odell
    CC=golang-dev
    https://golang.org/cl/5340058

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

https://github.com/golang/go/commit/0e5cd9d3f6ee8e0828cf29152d7180f70a00d6c7

元コミット内容

このコミットは、Go言語のランタイムにおいて、FreeBSDオペレーティングシステム向けにtimespec構造体の定義を追加するものです。具体的には、386アーキテクチャとamd64アーキテクチャの両方に対応するdefs.hファイルにTimespec構造体を追加し、defs.cファイルで$Timespecとして型定義を行っています。

変更の背景

Go言語のランタイムは、様々なオペレーティングシステムやアーキテクチャに対応するために、それぞれの環境固有のシステムコールやデータ構造を適切に扱う必要があります。timespec構造体は、UNIX系システムにおいて時間(秒とナノ秒)を表現するための標準的なデータ構造であり、nanosleepclock_gettimeなどの時間関連のシステムコールで使用されます。

このコミットが行われた2011年11月時点では、Go言語のFreeBSDサポートが成熟していく過程にあり、FreeBSD固有のシステムコールをGoランタイムから適切に呼び出すために、必要なデータ構造の定義が追加されていました。timespecの定義が不足していたため、FreeBSD上で時間関連のシステムコールを正確に利用することができなかったと考えられます。この変更は、GoランタイムがFreeBSDのシステムとより深く連携し、時間に関する操作を正確に行えるようにするための基盤を整備するものです。

前提知識の解説

1. Go言語のランタイム (Runtime)

Go言語のランタイムは、Goプログラムの実行を管理する低レベルのコンポーネントです。これには、ガベージコレクション、スケジューラ(ゴルーチンの管理)、メモリ割り当て、システムコールインターフェースなどが含まれます。ランタイムは、Goプログラムがオペレーティングシステムとどのように対話するかを定義し、異なるOSやアーキテクチャ間でGoプログラムの移植性を確保する上で重要な役割を果たします。

2. timespec構造体

timespecは、POSIX標準で定義されている時間値を表現するための構造体です。通常、以下のような形式で定義されます。

struct timespec {
    time_t tv_sec;  // 秒
    long   tv_nsec; // ナノ秒 (0から999,999,999まで)
};

この構造体は、高精度な時間測定や、特定の時間だけスリープするnanosleepなどのシステムコールで利用されます。tv_secはエポックからの秒数を、tv_nsecは秒未満のナノ秒を表します。

3. FreeBSD

FreeBSDは、UNIX系のオープンソースオペレーティングシステムです。高性能で安定しており、サーバーや組み込みシステムで広く利用されています。Go言語は、Linux、macOS、Windowsなどと同様に、FreeBSDも公式にサポートしています。

4. defs.hdefs.c

Go言語のランタイムソースコードにおいて、src/pkg/runtime/<os>/<arch>/defs.hのようなファイルは、特定のOSとアーキテクチャに特化した低レベルの定義(構造体、定数、マクロなど)を含んでいます。これらは、GoランタイムがC言語で書かれた部分や、システムコールを呼び出す際に必要となるC言語互換のデータ構造を定義するために使用されます。 defs.cファイルは、これらの定義に関連するC言語のコードや、Go言語からC言語の構造体を参照するための型エイリアスなどを提供することがあります。

5. 386とamd64アーキテクチャ

  • 386: Intel 80386プロセッサに由来する32ビットアーキテクチャを指します。現代では主にレガシーシステムや特定の組み込み環境で使用されます。
  • amd64: x86-64とも呼ばれ、AMDが開発しIntelも採用している64ビットアーキテクチャです。現代のほとんどのデスクトップ、サーバー、ラップトップで使用されています。Goランタイムは、これらの異なるアーキテクチャ向けに、データ型のサイズ(例: int32 vs int64)やアライメントを適切に調整する必要があります。

技術的詳細

このコミットの技術的な核心は、GoランタイムがFreeBSD上で時間関連のシステムコールを正確に実行するために、C言語のtimespec構造体をGoランタイム内部で認識できるようにすることです。

FreeBSDのシステムコールは、C言語のABI(Application Binary Interface)に従って引数を受け取ります。Goランタイムがこれらのシステムコールを呼び出す際、Goのデータ型をC言語の対応するデータ型に正確にマッピングする必要があります。timespec構造体は、秒とナノ秒の2つのフィールドを持つため、GoランタイムがFreeBSDのシステムコールにtimespecを渡したり、システムコールからtimespecを受け取ったりする際に、この構造体のメモリレイアウトとフィールドの型が正確に一致している必要があります。

コミットでは、386とamd64の2つのアーキテクチャに対してTimespec構造体を定義しています。

  • 386アーキテクチャ (src/pkg/runtime/freebsd/386/defs.h):

    typedef struct Timespec Timespec;
    struct Timespec {
    	int32 tv_sec;
    	int32 tv_nsec;
    };
    

    32ビットシステムでは、time_tlongが通常32ビット整数として扱われるため、tv_sectv_nsecint32として定義されています。

  • amd64アーキテクチャ (src/pkg/runtime/freebsd/amd64/defs.h):

    typedef struct Timespec Timespec;
    struct Timespec {
    	int64 tv_sec;
    	int64 tv_nsec;
    };
    

    64ビットシステムでは、time_tlongが64ビット整数として扱われるため、tv_sectv_nsecint64として定義されています。これにより、2038年問題(Unix時間で2^31秒を超えることによる問題)を回避し、より大きな時間値を表現できます。

src/pkg/runtime/freebsd/defs.cでは、typedef struct timespec $Timespec;という行が追加されています。これは、C言語のstruct timespecをGoランタイムが内部で参照する際のエイリアス$Timespecとして定義していることを示唆しています。GoのツールチェーンがCのヘッダーファイルを解析し、Goの型定義を生成する際に、このエイリアスが利用される可能性があります。

この変更により、GoランタイムはFreeBSD上でtimespecを引数として取るシステムコール(例: nanosleep, clock_gettime, utimensatなど)を正確に呼び出し、またそれらのシステムコールから返されるtimespec構造体の値を正しく解釈できるようになります。これは、GoプログラムがFreeBSD上で時間関連の機能を安定して利用するための重要なステップです。

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

このコミットでは、以下の3つのファイルが変更されています。

  1. src/pkg/runtime/freebsd/386/defs.h
  2. src/pkg/runtime/freebsd/amd64/defs.h
  3. src/pkg/runtime/freebsd/defs.c

src/pkg/runtime/freebsd/386/defs.h の変更

--- a/src/pkg/runtime/freebsd/386/defs.h
+++ b/src/pkg/runtime/freebsd/386/defs.h
@@ -173,6 +173,12 @@ struct Ucontext {
 	byte pad_godefs_0[12];
 };
 
+typedef struct Timespec Timespec;
+struct Timespec {
+\tint32 tv_sec;
+\tint32 tv_nsec;
+};
+
 typedef struct Timeval Timeval;
 struct Timeval {
 \tint32 tv_sec;
  • Ucontext構造体の定義の後に、Timespec構造体が追加されています。
  • Timespectv_sec(秒)とtv_nsec(ナノ秒)の2つのフィールドを持ち、それぞれint32型で定義されています。これは32ビットアーキテクチャ向けです。

src/pkg/runtime/freebsd/amd64/defs.h の変更

--- a/src/pkg/runtime/freebsd/amd64/defs.h
+++ b/src/pkg/runtime/freebsd/amd64/defs.h
@@ -184,6 +184,12 @@ struct Ucontext {
 	byte pad_godefs_0[12];
 };
 
+typedef struct Timespec Timespec;
+struct Timespec {
+\tint64 tv_sec;
+\tint64 tv_nsec;
+};
+
 typedef struct Timeval Timeval;
 struct Timeval {
 \tint64 tv_sec;
  • こちらもUcontext構造体の定義の後に、Timespec構造体が追加されています。
  • Timespectv_sectv_nsecの2つのフィールドを持ち、それぞれint64型で定義されています。これは64ビットアーキテクチャ向けです。

src/pkg/runtime/freebsd/defs.c の変更

--- a/src/pkg/runtime/freebsd/defs.c
+++ b/src/pkg/runtime/freebsd/defs.c
@@ -104,5 +104,7 @@ typedef siginfo_t $Siginfo;\n \n typedef mcontext_t $Mcontext;\n typedef ucontext_t $Ucontext;\n+\n+typedef struct timespec $Timespec;\n typedef struct timeval $Timeval;\
 typedef struct itimerval $Itimerval;\
  • 既存の型定義のリストに、typedef struct timespec $Timespec;が追加されています。
  • これは、C言語のstruct timespecをGoランタイムが内部で利用する際のエイリアス$Timespecとして宣言しています。

コアとなるコードの解説

このコミットの主要な目的は、GoランタイムがFreeBSDのシステムコールと連携する際に、timespec構造体を正しく扱えるようにすることです。

  1. defs.hファイルでの構造体定義: src/pkg/runtime/freebsd/386/defs.hsrc/pkg/runtime/freebsd/amd64/defs.hTimespec構造体を定義することで、GoランタイムはFreeBSDのC言語ヘッダーで定義されているstruct timespecのメモリレイアウトとフィールドの型を正確に模倣します。

    • 32ビット版ではint32を使用し、64ビット版ではint64を使用しているのは、それぞれのアーキテクチャにおけるtime_tlongの標準的なサイズに合わせるためです。これにより、Goランタイムがシステムコールに渡すデータやシステムコールから受け取るデータが、FreeBSDカーネルが期待する形式と一致することが保証されます。
    • typedef struct Timespec Timespec;という行は、C言語における一般的な慣習で、struct Timespecを単にTimespecとして参照できるようにするためのものです。
  2. defs.cファイルでの型エイリアス: typedef struct timespec $Timespec;という行は、GoのビルドシステムやツールチェーンがC言語の構造体をGoの型に変換する際に利用される可能性があります。$プレフィックスは、Goランタイム内部でC言語の型を参照するための特別な命名規則であることが多いです。これにより、GoのコードからFreeBSDのtimespec構造体を安全かつ効率的に操作するための基盤が確立されます。

これらの変更により、Go言語で書かれたプログラムがFreeBSD上で時間関連の操作(例: ファイルのタイムスタンプ設定、高精度なスリープ、システム時刻の取得など)を行う際に、基盤となるランタイムがFreeBSDのシステムコールと正しく対話できるようになります。これは、Go言語のFreeBSDサポートの完全性と安定性を向上させる上で不可欠なステップです。

関連リンク

  • Go言語の公式ウェブサイト: https://golang.org/
  • Go言語のFreeBSDポートに関する情報 (古い情報を含む可能性あり): https://wiki.freebsd.org/Go
  • POSIX timespecに関する情報: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_400

参考にした情報源リンク

  • FreeBSD Handbook: https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/
  • Go言語のソースコードリポジトリ (GitHub): https://github.com/golang/go
  • Go言語のランタイムに関するドキュメント (公式): https://go.dev/doc/effective_go#concurrency (ランタイムの概要について)
  • timespecに関するC言語のドキュメントやmanページ (例: man 2 nanosleepman 3 timespec)
  • 2038年問題: https://ja.wikipedia.org/wiki/2038%E5%B9%B4%E5%95%8F%E9%A1%8C