[インデックス 18220] ファイルの概要
このコミットは、Go言語のランタイムおよびsyscallパッケージがOpenBSDオペレーティングシステムのシステムABI(Application Binary Interface)変更に対応するためのものです。具体的には、OpenBSDがtime_t
型を32ビットから64ビットに拡張したことによる影響を吸収し、Goプログラムが新しいABI環境で正しく動作するように更新しています。
コミット
commit 471763f657df9bfe34c40d8483e0dd4b9c4122a6
Author: Joel Sing <jsing@google.com>
Date: Sat Jan 11 19:00:32 2014 +1100
runtime, syscall: update for openbsd system ABI break
Update Go so that it continues to work past the OpenBSD system ABI
break, with 64-bit time_t:
http://www.openbsd.org/faq/current.html#20130813
Note: this makes OpenBSD 5.5 (currently 5.4-current) the minimum
supported release for Go.
Fixes #7049.
R=golang-codereviews, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/13368046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/471763f657df9bfe34c40d8483e0dd4b9c4122a6
元コミット内容
OpenBSDのシステムABI変更、特にtime_t
の64ビット化に対応するため、Goランタイムとsyscallパッケージを更新する。これにより、OpenBSD 5.5(当時の5.4-current)がGoの最小サポートリリースとなる。
変更の背景
この変更の背景には、OpenBSDオペレーティングシステムが2013年8月13日に実施した重要なシステムABIブレークがあります。ABIブレークとは、コンパイル済みのバイナリ互換性が失われるような、システムコールやデータ構造の根本的な変更を指します。
具体的には、OpenBSDはシステム内で時刻を表現するために使用されるtime_t
型を、従来の32ビットから64ビットに拡張しました。32ビットのtime_t
は、2038年1月19日3時14分7秒(UTC)にオーバーフローするという「2038年問題」を抱えており、これに対処するために多くのUnix系システムが64ビットへの移行を進めていました。OpenBSDもその一環としてこの変更を行いましたが、これは既存の32ビットtime_t
を前提としていたアプリケーションやライブラリにとって互換性の問題を引き起こします。
Go言語のランタイムやsyscallパッケージは、OSのシステムコールを直接呼び出したり、OSが定義するデータ構造(例えば、時刻を表すTimespec
やTimeval
構造体、ファイルシステムの状態を表すStat_t
など)を利用したりするため、このようなABI変更に直接影響を受けます。time_t
が64ビットに変わると、これらの構造体内のフィールドのサイズやオフセットが変わり、結果としてシステムコールへの引数の渡し方や戻り値の解釈がずれてしまいます。
このコミットは、GoがOpenBSD上で引き続き正しく動作するために、このABI変更に追従することを目的としています。特に、OpenBSD 5.5以降のバージョンでGoが動作するように、Goの内部実装を調整する必要がありました。
前提知識の解説
ABI (Application Binary Interface)
ABIは、オペレーティングシステムとアプリケーション、またはアプリケーションの異なるモジュール間でのバイナリレベルのインターフェースを定義するものです。これには、以下のような要素が含まれます。
- システムコール規約: アプリケーションがOSのサービスを要求する際に、どのようにレジスタやスタックを使って引数を渡し、戻り値を受け取るか。
- データ型サイズとアラインメント: プリミティブ型(
int
,long
,pointer
など)のメモリ上でのサイズと、構造体内のフィールドがメモリ上でどのように配置されるか(アラインメント)。 - 関数呼び出し規約: 関数がどのように引数を受け取り、戻り値を返すか。スタックフレームのレイアウトなど。
- シンボル名マングリング: コンパイラが関数名や変数名をどのようにバイナリ内のシンボル名に変換するか。
ABIが変更されると、その変更以前にコンパイルされたバイナリは、新しいABIを持つシステム上で正しく動作しなくなる可能性があります。今回のケースでは、time_t
のサイズ変更がデータ型サイズとアラインメントに影響を与え、結果としてシステムコール規約にも影響を及ぼしました。
time_t
型と2038年問題
time_t
は、Unix系システムで時刻(通常はUnixエポックからの秒数)を表現するために使われるデータ型です。歴史的に32ビット符号付き整数として実装されることが多くありました。
2038年問題は、32ビット符号付き整数で表現できる最大値(2,147,483,647)が、2038年1月19日3時14分7秒(UTC)に到達することで発生します。この時刻を超えると、32ビットtime_t
はオーバーフローし、負の値として解釈されるため、時刻に関連する計算や機能が誤動作する可能性があります。これは、2000年問題と同様に、システム障害を引き起こす可能性のある重大な問題として認識されています。
この問題に対処するため、多くのOSやシステムはtime_t
を64ビット整数に拡張する移行を進めています。64ビット整数であれば、現在の宇宙の年齢よりもはるかに長い期間の時刻を表現できるため、実質的にこの問題は解消されます。
OpenBSD
OpenBSDは、セキュリティを最優先事項として開発されているUnix系オペレーティングシステムです。厳格なコードレビュー、プロアクティブなセキュリティ対策、そしてクリーンなコードベースを維持することで知られています。このようなセキュリティへの強いコミットメントは、時にABIの互換性を犠牲にしてでも、より堅牢で安全なシステムを構築するという判断につながることがあります。今回のtime_t
の64ビット化も、長期的なシステムの健全性を考慮した上での重要な変更でした。
Go言語のランタイムとsyscallパッケージ
- Goランタイム: Goプログラムの実行を管理する部分です。ガベージコレクション、スケジューラ、goroutineの管理、そしてOSとの低レベルなインタラクション(システムコール呼び出しなど)を担当します。OS固有のデータ構造やシステムコール規約に関する知識を内部に持っています。
- syscallパッケージ: GoプログラムからOSのシステムコールを直接呼び出すためのインターフェースを提供します。このパッケージはOSごとに異なる実装を持ち、各OSのシステムコール番号、データ構造、エラーコードなどをGoの型にマッピングしています。ABI変更は、このパッケージが扱うデータ構造の定義やシステムコール呼び出しの引数に直接影響を与えます。
技術的詳細
このコミットの主要な技術的変更点は、OpenBSDのtime_t
が32ビットから64ビットに拡張されたことに伴う、Goランタイムとsyscallパッケージ内のデータ構造の定義およびシステムコール呼び出しの調整です。
-
データ構造の変更:
src/pkg/runtime/defs_openbsd_386.h
およびsrc/pkg/runtime/defs_openbsd_amd64.h
: これらのファイルは、Goランタイムが使用するOpenBSD固有のC構造体の定義を含んでいます。Timespec
構造体とTimeval
構造体内のtv_sec
フィールドが、int32
からint64
に変更されています。これは、秒数を格納するフィールドが64ビットになったことを反映しています。Kevent
構造体内のdata
フィールド(386アーキテクチャの場合)およびident
フィールド(amd64アーキテクチャの場合)も、関連するデータサイズ変更に合わせてint32
からint64
またはuint32
からuint64
に変更されています。Sigcontext
構造体内のsc_onstack
フィールドが__sc_unused
に変更されています。これは、ABI変更に伴い、このフィールドがGoランタイムにとって不要になったか、別の方法で処理されるようになったことを示唆しています。
src/pkg/syscall/ztypes_openbsd_386.go
およびsrc/pkg/syscall/ztypes_openbsd_amd64.go
: これらのファイルは、Goのsyscall
パッケージが使用するOpenBSD固有のGoの型定義を含んでいます。Timespec
およびTimeval
構造体のSec
フィールドがint32
からint64
に変更されています。Stat_t
構造体内のIno
フィールド(inode番号)がuint32
からuint64
に変更されています。これは、ファイルシステムがより大きなinode番号をサポートするようになったことを示しています。また、Dev
フィールドもint32
からint64
に変更されています。Dirent
構造体内のFileno
フィールド(ディレクトリ内のファイル番号)がuint32
からuint64
に変更されています。Kevent_t
構造体内のIdent
およびData
フィールドの型が変更されています。Statfs_t
構造体内のF_ctime
フィールドがuint32
からuint64
に変更されています。- 各種
Sizeof
定数(例:SizeofIfMsghdr
,SizeofRtMsghdr
,SizeofRtMetrics
)が、構造体サイズの変更に合わせて更新されています。 RtMetrics
構造体内のExpire
フィールドの型が変更されています。
-
システムコール番号とアセンブリコードの調整:
src/pkg/runtime/sys_openbsd_386.s
およびsrc/pkg/runtime/sys_openbsd_amd64.s
: これらのアセンブリファイルは、Goランタイムが直接呼び出す低レベルのシステムコールラッパーを含んでいます。nanosleep
,setitimer
,clock_gettime
,__thrsleep
,kevent
などのシステムコール呼び出しにおいて、使用されるシステムコール番号(AX
レジスタに設定される値)が変更されています。これは、OpenBSDのABI変更により、これらのシステムコールの番号が再割り当てされたことを意味します。runtime·usleep
,time·now
,runtime·nanotime
などの関数で、Timespec
やTimeval
構造体のフィールドにアクセスする際のオフセットや、64ビット値を扱うためのレジスタ操作(例:MOVL
からMOVQ
への変更、高位32ビットの処理)が調整されています。特に、32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数のレジスタを使用する(例:DX:AX
)必要があり、そのためのコードが追加されています。
src/pkg/syscall/zsysnum_openbsd_386.go
およびsrc/pkg/syscall/zsysnum_openbsd_amd64.go
: これらのファイルは、OpenBSDのシステムコール番号の定数を定義しています。- 多くのシステムコール(
SYS_WAIT4
,SYS_GETRUSAGE
,SYS_STAT
,SYS_LSTAT
,SYS_FSTATAT
,SYS_FSTAT
,SYS_GETFSSTAT
,SYS_STATFS
,SYS_FSTATFS
,SYS_FHSTATFS
,SYS_GETTIMEOFDAY
,SYS_SETTIMEOFDAY
,SYS_SETITIMER
,SYS_GETITIMER
,SYS_SELECT
,SYS_KEVENT
,SYS_UTIMES
,SYS_FUTIMES
,SYS_UTIMENSAT
,SYS_FUTIMENS
,SYS_CLOCK_GETTIME
,SYS_CLOCK_SETTIME
,SYS_CLOCK_GETRES
,SYS_NANOSLEEP
,SYS___THRSLEEP
,SYS_GETDENTS
,SYS_PPOLL
,SYS_PSELECT
,SYS_UTRACE
など)の番号が変更されています。これは、OpenBSDがシステムコールテーブルを再編成した結果です。 - 一部のシステムコール(例:
SYS_GETDIRENTRIES
)が削除され、代わりにSYS_GETDENTS
が追加されています。
- 多くのシステムコール(
-
syscallパッケージのGoコードの変更:
src/pkg/syscall/syscall_openbsd.go
:Getdirentries
関数が削除され、代わりにgetdents
システムコールを呼び出すGetdirentries
関数が追加されています。これは、OpenBSDがディレクトリエントリーを読み取るためのシステムコールを変更したことに対応しています。src/pkg/syscall/syscall_openbsd_386.go
およびsrc/pkg/syscall/syscall_openbsd_amd64.go
:TimespecToNsec
,NsecToTimespec
,TimevalToNsec
,NsecToTimeval
などの時間変換関数で、ts.Sec
やtv.Sec
の型がint32
からint64
に変更されています。また、SetKevent
関数でk.Ident
の型がuint32
からuint64
に変更されています。src/pkg/syscall/zerrors_openbsd_386.go
およびsrc/pkg/syscall/zerrors_openbsd_amd64.go
: 各種定数(ioctlコマンド、プロトコル番号、フラグなど)の値がOpenBSDの新しい定義に合わせて更新されています。これは、ABI変更に伴い、これらの定数の値も変更されたためです。src/pkg/syscall/zsyscall_openbsd_386.go
およびsrc/pkg/syscall/zsyscall_openbsd_amd64.go
:Getdirentries
関数の実装が削除され、getdents
システムコールを呼び出す新しいgetdents
関数が追加されています。これは、OpenBSDのディレクトリエントリー読み取りAPIの変更に直接対応するものです。src/pkg/syscall/zsysctl_openbsd.go
:sysctlMib
配列からいくつかのエントリが削除または変更されています。これは、OpenBSDのsysctl
インターフェースで利用可能なカーネル情報の一部が変更されたことを示しています。
これらの変更は、GoがOpenBSDの新しいABIに完全に準拠し、time_t
の64ビット化によって引き起こされる潜在的な互換性問題を回避するために不可欠でした。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、主に以下のファイル群に集中しています。
-
src/pkg/runtime/defs_openbsd_386.h
およびsrc/pkg/runtime/defs_openbsd_amd64.h
:Timespec
構造体のtv_sec
フィールドの型がint32
からint64
へ変更。Timeval
構造体のtv_sec
フィールドの型がint32
からint64
へ変更。Kevent
構造体のdata
フィールド(386)またはident
フィールド(amd64)の型が変更。Sigcontext
構造体のsc_onstack
フィールドが__sc_unused
へ変更。
-
src/pkg/runtime/sys_openbsd_386.s
およびsrc/pkg/runtime/sys_openbsd_amd64.s
:runtime·usleep
,time·now
,runtime·nanotime
,runtime·setitimer
,runtime·kevent
,runtime·thrsleep
などのアセンブリ関数におけるシステムコール番号(AX
レジスタの値)の変更。time·now
やruntime·nanotime
における、64ビット時刻値の処理(レジスタの利用方法、オフセットの調整)の変更。
-
src/pkg/syscall/syscall_openbsd.go
:Getdirentries
関数の定義が変更され、内部でgetdents
システムコールを呼び出すように修正。
-
src/pkg/syscall/syscall_openbsd_386.go
およびsrc/pkg/syscall/syscall_openbsd_amd64.go
:NsecToTimespec
およびNsecToTimeval
関数におけるts.Sec
やtv.Sec
への代入がint32
キャストからint64
キャスト(または直接代入)へ変更。SetKevent
関数におけるk.Ident
の型がuint32
からuint64
へ変更。
-
src/pkg/syscall/zerrors_openbsd_386.go
およびsrc/pkg/syscall/zerrors_openbsd_amd64.go
:- 多数の定数値(
BIOCGRTIMEOUT
,BIOCSRTIMEOUT
,RTM_VERSION
,SIOCBRDGDADDR
,SIOCBRDGSADDR
,TIOCGTSTAMP
など)の変更。
- 多数の定数値(
-
src/pkg/syscall/zsyscall_openbsd_386.go
およびsrc/pkg/syscall/zsyscall_openbsd_amd64.go
:Getdirentries
関数の削除と、getdents
関数の追加。Syscall
関数の引数として渡されるシステムコール番号の変更。
-
src/pkg/syscall/zsysnum_openbsd_386.go
およびsrc/pkg/syscall/zsysnum_openbsd_amd64.go
:- OpenBSDのシステムコール番号の定数定義が大幅に更新。多くのシステムコール番号が変更され、一部のシステムコールが追加または削除されています。
-
src/pkg/syscall/ztypes_openbsd_386.go
およびsrc/pkg/syscall/ztypes_openbsd_amd64.go
:Timespec
,Timeval
,Stat_t
,Dirent
,Kevent_t
,Statfs_t
,RtMetrics
などの構造体内のフィールドの型(int32
からint64
、uint32
からuint64
など)およびオフセットの変更。SizeofIfMsghdr
,SizeofIfData
,SizeofRtMsghdr
,SizeofRtMetrics
などのサイズ定数の更新。
コアとなるコードの解説
このコミットの核心は、OpenBSDのABI変更、特にtime_t
の64ビット化にGoが適応することです。
-
データ型のサイズ変更への対応:
Timespec
やTimeval
といった時刻関連の構造体は、OSのシステムコールで時刻情報をやり取りする際に頻繁に使用されます。これらの構造体内の秒を表すフィールド(tv_sec
やSec
)が32ビットから64ビットに変更されたため、Goのランタイムとsyscall
パッケージ内の対応するGoの型定義もint32
からint64
に更新されました。これにより、GoプログラムがOSから取得する時刻情報が正しく解釈され、2038年問題の影響を受けなくなります。Stat_t
(ファイルの状態)、Dirent
(ディレクトリエントリー)、Kevent_t
(kqueueイベント)などの構造体も、内部のフィールド(inode番号、ファイル番号、イベントデータなど)が64ビットに拡張されたため、Goの型定義が更新されています。これにより、Goがファイルシステムやイベント通知システムと正しく連携できるようになります。- これらの構造体サイズの変更は、
Sizeof
定数の更新にもつながり、メモリ割り当てやデータコピーの際に正しいサイズが使用されることを保証します。
-
システムコール番号の変更への対応:
- OpenBSDのABI変更では、既存のシステムコールの番号が再割り当てされたり、新しいシステムコールが導入されたりすることがあります。Goのランタイムは、アセンブリコードを通じて直接システムコールを呼び出すため、これらの番号の変更に追従する必要があります。
src/pkg/runtime/sys_openbsd_*.s
ファイルでは、INT $0x80
(i386)やSYSCALL
(amd64)命令の直前にAX
レジスタに設定されるシステムコール番号が、OpenBSDの新しい定義に合わせて更新されています。src/pkg/syscall/zsysnum_openbsd_*.go
ファイルでは、Goのコードからシステムコールを呼び出す際に使用される定数(SYS_NANOSLEEP
など)が、新しいシステムコール番号に更新されています。これにより、Goプログラムが正しいシステムコールを呼び出すことが保証されます。
-
システムコールAPIの変更への対応:
Getdirentries
からgetdents
への変更は、ディレクトリの内容を読み取るためのシステムコールAPIが変更されたことを示しています。Goのsyscall
パッケージは、この新しいAPIに合わせてGetdirentries
関数の実装を更新し、内部でgetdents
システムコールを呼び出すように変更されました。これにより、GoプログラムがOpenBSDの新しいディレクトリ読み取りメカニズムを正しく利用できるようになります。
-
アセンブリコードでの64ビット値の処理:
- 特に32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数の32ビットレジスタ(例:
DX:AX
)を組み合わせて使用する必要があります。runtime·nanotime
などの関数では、tv_sec
が64ビットになったことで、秒とナノ秒を組み合わせてナノ秒単位の合計時間を計算する際に、64ビット演算を正しく行うためのアセンブリ命令が追加・修正されています。これにより、時刻計算の精度と正確性が維持されます。
- 特に32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数の32ビットレジスタ(例:
これらの変更は、GoがOpenBSDの進化するシステム環境に適合し、長期的な互換性と安定性を確保するために不可欠なものです。
関連リンク
- OpenBSD FAQ: Current - 20130813 (time_t change): http://www.openbsd.org/faq/current.html#20130813
- Go Issue 7049: OpenBSD: update for 64-bit time_t ABI break: https://github.com/golang/go/issues/7049
- Go Code Review 13368046: runtime, syscall: update for openbsd system ABI break: https://golang.org/cl/13368046
参考にした情報源リンク
- OpenBSD公式ドキュメント
- Go言語のソースコード
- ABI (Application Binary Interface) に関する一般的な情報源 (例: Wikipedia)
- 2038年問題に関する情報源 (例: Wikipedia)
- Unix系システムのシステムコールに関する情報源
- アセンブリ言語(x86/x64)の基本に関する情報源
[インデックス 18220] ファイルの概要
このコミットは、Go言語のランタイムおよびsyscallパッケージがOpenBSDオペレーティングシステムのシステムABI(Application Binary Interface)変更に対応するためのものです。具体的には、OpenBSDがtime_t
型を32ビットから64ビットに拡張したことによる影響を吸収し、Goプログラムが新しいABI環境で正しく動作するように更新しています。
コミット
commit 471763f657df9bfe34c40d8483e0dd4b9c4122a6
Author: Joel Sing <jsing@google.com>
Date: Sat Jan 11 19:00:32 2014 +1100
runtime, syscall: update for openbsd system ABI break
Update Go so that it continues to work past the OpenBSD system ABI
break, with 64-bit time_t:
http://www.openbsd.org/faq/current.html#20130813
Note: this makes OpenBSD 5.5 (currently 5.4-current) the minimum
supported release for Go.
Fixes #7049.
R=golang-codereviews, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/13368046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/471763f657df9bfe34c40d8483e0dd4b9c4122a6
元コミット内容
OpenBSDのシステムABI変更、特にtime_t
の64ビット化に対応するため、Goランタイムとsyscallパッケージを更新する。これにより、OpenBSD 5.5(当時の5.4-current)がGoの最小サポートリリースとなる。
変更の背景
この変更の背景には、OpenBSDオペレーティングシステムが2013年8月13日に実施した重要なシステムABIブレークがあります。ABIブレークとは、コンパイル済みのバイナリ互換性が失われるような、システムコールやデータ構造の根本的な変更を指します。
具体的には、OpenBSDはシステム内で時刻を表現するために使用されるtime_t
型を、従来の32ビットから64ビットに拡張しました。32ビットのtime_t
は、2038年1月19日3時14分7秒(UTC)にオーバーフローするという「2038年問題」を抱えており、これに対処するために多くのUnix系システムが64ビットへの移行を進めていました。OpenBSDもその一環としてこの変更を行いましたが、これは既存の32ビットtime_t
を前提としていたアプリケーションやライブラリにとって互換性の問題を引き起こします。
Go言語のランタイムやsyscallパッケージは、OSのシステムコールを直接呼び出したり、OSが定義するデータ構造(例えば、時刻を表すTimespec
やTimeval
構造体、ファイルシステムの状態を表すStat_t
など)を利用したりするため、このようなABI変更に直接影響を受けます。time_t
が64ビットに変わると、これらの構造体内のフィールドのサイズやオフセットが変わり、結果としてシステムコールへの引数の渡し方や戻り値の解釈がずれてしまいます。
このコミットは、GoがOpenBSD上で引き続き正しく動作するために、このABI変更に追従することを目的としています。特に、OpenBSD 5.5以降のバージョンでGoが動作するように、Goの内部実装を調整する必要がありました。
前提知識の解説
ABI (Application Binary Interface)
ABIは、オペレーティングシステムとアプリケーション、またはアプリケーションの異なるモジュール間でのバイナリレベルのインターフェースを定義するものです。これには、以下のような要素が含まれます。
- システムコール規約: アプリケーションがOSのサービスを要求する際に、どのようにレジスタやスタックを使って引数を渡し、戻り値を受け取るか。
- データ型サイズとアラインメント: プリミティブ型(
int
,long
,pointer
など)のメモリ上でのサイズと、構造体内のフィールドがメモリ上でどのように配置されるか(アラインメント)。 - 関数呼び出し規約: 関数がどのように引数を受け取り、戻り値を返すか。スタックフレームのレイアウトなど。
- シンボル名マングリング: コンパイラが関数名や変数名をどのようにバイナリ内のシンボル名に変換するか。
ABIが変更されると、その変更以前にコンパイルされたバイナリは、新しいABIを持つシステム上で正しく動作しなくなる可能性があります。今回のケースでは、time_t
のサイズ変更がデータ型サイズとアラインメントに影響を与え、結果としてシステムコール規約にも影響を及ぼしました。
time_t
型と2038年問題
time_t
は、Unix系システムで時刻(通常はUnixエポックからの秒数)を表現するために使われるデータ型です。歴史的に32ビット符号付き整数として実装されることが多くありました。
2038年問題は、32ビット符号付き整数で表現できる最大値(2,147,483,647)が、2038年1月19日3時14分7秒(UTC)に到達することで発生します。この時刻を超えると、32ビットtime_t
はオーバーフローし、負の値として解釈されるため、時刻に関連する計算や機能が誤動作する可能性があります。これは、2000年問題と同様に、システム障害を引き起こす可能性のある重大な問題として認識されています。
この問題に対処するため、多くのOSやシステムはtime_t
を64ビット整数に拡張する移行を進めています。64ビット整数であれば、現在の宇宙の年齢よりもはるかに長い期間の時刻を表現できるため、実質的にこの問題は解消されます。
OpenBSD
OpenBSDは、セキュリティを最優先事項として開発されているUnix系オペレーティングシステムです。厳格なコードレビュー、プロアクティブなセキュリティ対策、そしてクリーンなコードベースを維持することで知られています。このようなセキュリティへの強いコミットメントは、時にABIの互換性を犠牲にしてでも、より堅牢で安全なシステムを構築するという判断につながることがあります。今回のtime_t
の64ビット化も、長期的なシステムの健全性を考慮した上での重要な変更でした。
Go言語のランタイムとsyscallパッケージ
- Goランタイム: Goプログラムの実行を管理する部分です。ガベージコレクション、スケジューラ、goroutineの管理、そしてOSとの低レベルなインタラクション(システムコール呼び出しなど)を担当します。OS固有のデータ構造やシステムコール規約に関する知識を内部に持っています。
- syscallパッケージ: GoプログラムからOSのシステムコールを直接呼び出すためのインターフェースを提供します。このパッケージはOSごとに異なる実装を持ち、各OSのシステムコール番号、データ構造、エラーコードなどをGoの型にマッピングしています。ABI変更は、このパッケージが扱うデータ構造の定義やシステムコール呼び出しの引数に直接影響を与えます。
技術的詳細
このコミットの主要な技術的変更点と、OpenBSDのtime_t
が32ビットから64ビットに拡張されたことに伴う、Goランタイムとsyscallパッケージ内のデータ構造の定義およびシステムコール呼び出しの調整です。
-
データ構造の変更:
src/pkg/runtime/defs_openbsd_386.h
およびsrc/pkg/runtime/defs_openbsd_amd64.h
: これらのファイルは、Goランタイムが使用するOpenBSD固有のC構造体の定義を含んでいます。Timespec
構造体とTimeval
構造体内のtv_sec
フィールドが、int32
からint64
に変更されています。これは、秒数を格納するフィールドが64ビットになったことを反映しています。Kevent
構造体内のdata
フィールド(386アーキテクチャの場合)およびident
フィールド(amd64アーキテクチャの場合)も、関連するデータサイズ変更に合わせてint32
からint64
またはuint32
からuint64
に変更されています。Sigcontext
構造体内のsc_onstack
フィールドが__sc_unused
に変更されています。これは、ABI変更に伴い、このフィールドがGoランタイムにとって不要になったか、別の方法で処理されるようになったことを示唆しています。
src/pkg/syscall/ztypes_openbsd_386.go
およびsrc/pkg/syscall/ztypes_openbsd_amd64.go
: これらのファイルは、Goのsyscall
パッケージが使用するOpenBSD固有のGoの型定義を含んでいます。Timespec
およびTimeval
構造体のSec
フィールドがint32
からint64
に変更されています。Stat_t
構造体内のIno
フィールド(inode番号)がuint32
からuint64
に変更されています。これは、ファイルシステムがより大きなinode番号をサポートするようになったことを示しています。また、Dev
フィールドもint32
からint64
に変更されています。Dirent
構造体内のFileno
フィールド(ディレクトリ内のファイル番号)がuint32
からuint64
に変更されています。Kevent_t
構造体内のIdent
およびData
フィールドの型が変更されています。Statfs_t
構造体内のF_ctime
フィールドがuint32
からuint64
に変更されています。- 各種
Sizeof
定数(例:SizeofIfMsghdr
,SizeofRtMsghdr
,SizeofRtMetrics
)が、構造体サイズの変更に合わせて更新されています。 RtMetrics
構造体内のExpire
フィールドの型が変更されています。
-
システムコール番号とアセンブリコードの調整:
src/pkg/runtime/sys_openbsd_386.s
およびsrc/pkg/runtime/sys_openbsd_amd64.s
: これらのアセンブリファイルは、Goランタイムが直接呼び出す低レベルのシステムコールラッパーを含んでいます。nanosleep
,setitimer
,clock_gettime
,__thrsleep
,kevent
などのシステムコール呼び出しにおいて、使用されるシステムコール番号(AX
レジスタに設定される値)が変更されています。これは、OpenBSDのABI変更により、これらのシステムコールの番号が再割り当てされたことを意味します。runtime·usleep
,time·now
,runtime·nanotime
などの関数で、Timespec
やTimeval
構造体のフィールドにアクセスする際のオフセットや、64ビット値を扱うためのレジスタ操作(例:MOVL
からMOVQ
への変更、高位32ビットの処理)が調整されています。特に、32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数のレジスタを使用する(例:DX:AX
)必要があり、そのためのコードが追加されています。
src/pkg/syscall/zsysnum_openbsd_386.go
およびsrc/pkg/syscall/zsysnum_openbsd_amd64.go
: これらのファイルは、OpenBSDのシステムコール番号の定数を定義しています。- 多くのシステムコール(
SYS_WAIT4
,SYS_GETRUSAGE
,SYS_STAT
,SYS_LSTAT
,SYS_FSTATAT
,SYS_FSTAT
,SYS_GETFSSTAT
,SYS_STATFS
,SYS_FSTATFS
,SYS_FHSTATFS
,SYS_GETTIMEOFDAY
,SYS_SETTIMEOFDAY
,SYS_SETITIMER
,SYS_GETITIMER
,SYS_SELECT
,SYS_KEVENT
,SYS_UTIMES
,SYS_FUTIMES
,SYS_UTIMENSAT
,SYS_FUTIMENS
,SYS_CLOCK_GETTIME
,SYS_CLOCK_SETTIME
,SYS_CLOCK_GETRES
,SYS_NANOSLEEP
,SYS___THRSLEEP
,SYS_GETDENTS
,SYS_PPOLL
,SYS_PSELECT
,SYS_UTRACE
など)の番号が変更されています。これは、OpenBSDがシステムコールテーブルを再編成した結果です。 - 一部のシステムコール(例:
SYS_GETDIRENTRIES
)が削除され、代わりにSYS_GETDENTS
が追加されています。
- 多くのシステムコール(
-
syscallパッケージのGoコードの変更:
src/pkg/syscall/syscall_openbsd.go
:Getdirentries
関数が削除され、代わりにgetdents
システムコールを呼び出すGetdirentries
関数が追加されています。これは、OpenBSDがディレクトリエントリーを読み取るためのシステムコールを変更したことに対応しています。src/pkg/syscall/syscall_openbsd_386.go
およびsrc/pkg/syscall/syscall_openbsd_amd64.go
:TimespecToNsec
,NsecToTimespec
,TimevalToNsec
,NsecToTimeval
などの時間変換関数で、ts.Sec
やtv.Sec
の型がint32
からint64
に変更されています。また、SetKevent
関数でk.Ident
の型がuint32
からuint64
に変更されています。src/pkg/syscall/zerrors_openbsd_386.go
およびsrc/pkg/syscall/zerrors_openbsd_amd64.go
: 各種定数(ioctlコマンド、プロトコル番号、フラグなど)の値がOpenBSDの新しい定義に合わせて更新されています。これは、ABI変更に伴い、これらの定数の値も変更されたためです。src/pkg/syscall/zsyscall_openbsd_386.go
およびsrc/pkg/syscall/zsyscall_openbsd_amd64.go
:Getdirentries
関数の実装が削除され、getdents
システムコールを呼び出す新しいgetdents
関数が追加されています。これは、OpenBSDのディレクトリエントリー読み取りAPIの変更に直接対応するものです。src/pkg/syscall/zsysctl_openbsd.go
:sysctlMib
配列からいくつかのエントリが削除または変更されています。これは、OpenBSDのsysctl
インターフェースで利用可能なカーネル情報の一部が変更されたことを示しています。
これらの変更は、GoがOpenBSDの新しいABIに完全に準拠し、time_t
の64ビット化によって引き起こされる潜在的な互換性問題を回避するために不可欠でした。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、主に以下のファイル群に集中しています。
-
src/pkg/runtime/defs_openbsd_386.h
およびsrc/pkg/runtime/defs_openbsd_amd64.h
:Timespec
構造体のtv_sec
フィールドの型がint32
からint64
へ変更。Timeval
構造体のtv_sec
フィールドの型がint32
からint64
へ変更。Kevent
構造体のdata
フィールド(386)またはident
フィールド(amd64)の型が変更。Sigcontext
構造体のsc_onstack
フィールドが__sc_unused
へ変更。
-
src/pkg/runtime/sys_openbsd_386.s
およびsrc/pkg/runtime/sys_openbsd_amd64.s
:runtime·usleep
,time·now
,runtime·nanotime
,runtime·setitimer
,runtime·kevent
,runtime·thrsleep
などのアセンブリ関数におけるシステムコール番号(AX
レジスタの値)の変更。time·now
やruntime·nanotime
における、64ビット時刻値の処理(レジスタの利用方法、オフセットの調整)の変更。
-
src/pkg/syscall/syscall_openbsd.go
:Getdirentries
関数の定義が変更され、内部でgetdents
システムコールを呼び出すように修正。
-
src/pkg/syscall/syscall_openbsd_386.go
およびsrc/pkg/syscall/syscall_openbsd_amd64.go
:NsecToTimespec
およびNsecToTimeval
関数におけるts.Sec
やtv.Sec
への代入がint32
キャストからint64
キャスト(または直接代入)へ変更。SetKevent
関数におけるk.Ident
の型がuint32
からuint64
へ変更。
-
src/pkg/syscall/zerrors_openbsd_386.go
およびsrc/pkg/syscall/zerrors_openbsd_amd64.go
:- 多数の定数値(
BIOCGRTIMEOUT
,BIOCSRTIMEOUT
,RTM_VERSION
,SIOCBRDGDADDR
,SIOCBRDGSADDR
,TIOCGTSTAMP
など)の変更。
- 多数の定数値(
-
src/pkg/syscall/zsyscall_openbsd_386.go
およびsrc/pkg/syscall/zsyscall_openbsd_amd64.go
:Getdirentries
関数の削除と、getdents
関数の追加。Syscall
関数の引数として渡されるシステムコール番号の変更。
-
src/pkg/syscall/zsysnum_openbsd_386.go
およびsrc/pkg/syscall/zsysnum_openbsd_amd64.go
:- OpenBSDのシステムコール番号の定数定義が大幅に更新。多くのシステムコール番号が変更され、一部のシステムコールが追加または削除されています。
-
src/pkg/syscall/ztypes_openbsd_386.go
およびsrc/pkg/syscall/ztypes_openbsd_amd64.go
:Timespec
,Timeval
,Stat_t
,Dirent
,Kevent_t
,Statfs_t
,RtMetrics
などの構造体内のフィールドの型(int32
からint64
、uint32
からuint64
など)およびオフセットの変更。SizeofIfMsghdr
,SizeofIfData
,SizeofRtMsghdr
,SizeofRtMetrics
などのサイズ定数の更新。
コアとなるコードの解説
このコミットの核心は、OpenBSDのABI変更、特にtime_t
の64ビット化にGoが適応することです。
-
データ型のサイズ変更への対応:
Timespec
やTimeval
といった時刻関連の構造体は、OSのシステムコールで時刻情報をやり取りする際に頻繁に使用されます。これらの構造体内の秒を表すフィールド(tv_sec
やSec
)が32ビットから64ビットに変更されたため、Goのランタイムとsyscall
パッケージ内の対応するGoの型定義もint32
からint64
に更新されました。これにより、GoプログラムがOSから取得する時刻情報が正しく解釈され、2038年問題の影響を受けなくなります。Stat_t
(ファイルの状態)、Dirent
(ディレクトリエントリー)、Kevent_t
(kqueueイベント)などの構造体も、内部のフィールド(inode番号、ファイル番号、イベントデータなど)が64ビットに拡張されたため、Goの型定義が更新されています。これにより、Goがファイルシステムやイベント通知システムと正しく連携できるようになります。- これらの構造体サイズの変更は、
Sizeof
定数の更新にもつながり、メモリ割り当てやデータコピーの際に正しいサイズが使用されることを保証します。
-
システムコール番号の変更への対応:
- OpenBSDのABI変更では、既存のシステムコールの番号が再割り当てされたり、新しいシステムコールが導入されたりすることがあります。Goのランタイムは、アセンブリコードを通じて直接システムコールを呼び出すため、これらの番号の変更に追従する必要があります。
src/pkg/runtime/sys_openbsd_*.s
ファイルでは、INT $0x80
(i386)やSYSCALL
(amd64)命令の直前にAX
レジスタに設定されるシステムコール番号が、OpenBSDの新しい定義に合わせて更新されています。src/pkg/syscall/zsysnum_openbsd_*.go
ファイルでは、Goのコードからシステムコールを呼び出す際に使用される定数(SYS_NANOSLEEP
など)が、新しいシステムコール番号に更新されています。これにより、Goプログラムが正しいシステムコールを呼び出すことが保証されます。
-
システムコールAPIの変更への対応:
Getdirentries
からgetdents
への変更は、ディレクトリの内容を読み取るためのシステムコールAPIが変更されたことを示しています。Goのsyscall
パッケージは、この新しいAPIに合わせてGetdirentries
関数の実装を更新し、内部でgetdents
システムコールを呼び出すように変更されました。これにより、GoプログラムがOpenBSDの新しいディレクトリ読み取りメカニズムを正しく利用できるようになります。
-
アセンブリコードでの64ビット値の処理:
- 特に32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数の32ビットレジスタ(例:
DX:AX
)を組み合わせて使用する必要があります。runtime·nanotime
などの関数では、tv_sec
が64ビットになったことで、秒とナノ秒を組み合わせてナノ秒単位の合計時間を計算する際に、64ビット演算を正しく行うためのアセンブリ命令が追加・修正されています。これにより、時刻計算の精度と正確性が維持されます。
- 特に32ビットアーキテクチャ(i386)では、64ビット値を扱うために複数の32ビットレジスタ(例:
これらの変更は、GoがOpenBSDの進化するシステム環境に適合し、長期的な互換性と安定性を確保するために不可欠なものです。
関連リンク
- OpenBSD FAQ: Current - 20130813 (time_t change): http://www.openbsd.org/faq/current.html#20130813
- Go Issue 7049: OpenBSD: update for 64-bit time_t ABI break: https://github.com/golang/go/issues/7049
- Go Code Review 13368046: runtime, syscall: update for openbsd system ABI break: https://golang.org/cl/13368046
参考にした情報源リンク
- OpenBSD公式ドキュメント
- Go言語のソースコード
- ABI (Application Binary Interface) に関する一般的な情報源 (例: Wikipedia)
- 2038年問題に関する情報源 (例: Wikipedia)
- Unix系システムのシステムコールに関する情報源
- アセンブリ言語(x86/x64)の基本に関する情報源