[インデックス 10248] ファイルの概要
このコミットは、Go言語のランタイムにおけるOpenBSD/amd64アーキテクチャでのnanotime
関数の修正に関するものです。具体的には、gettimeofday
システムコールから返されるマイクロ秒の値を受け取るレジスタが誤っていたのを修正し、高精度な時間計測の正確性を向上させています。
コミット
commit cb2040b2ab68ab7d2863e65920749ed1266f7acd
Author: Russ Cox <rsc@golang.org>
Date: Fri Nov 4 07:24:39 2011 -0400
runtime: fix openbsd nanotime?
TBR=r
CC=golang-dev
https://golang.org/cl/5353041
---
src/pkg/runtime/openbsd/amd64/sys.s | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n
diff --git a/src/pkg/runtime/openbsd/amd64/sys.s b/src/pkg/runtime/openbsd/amd64/sys.s
index dfbb2547fa..7bb44d6a95 100644
--- a/src/pkg/runtime/openbsd/amd64/sys.s
+++ b/src/pkg/runtime/openbsd/amd64/sys.s
@@ -139,7 +139,7 @@ TEXT runtime·nanotime(SB),7,$32
MOVL $116, AX // sys_gettimeofday
SYSCALL
MOVQ 8(SP), AX // sec
-\tMOVL 16(SP), BX // usec
+\tMOVL 16(SP), DX // usec
// sec is in AX, usec in DX
// return nsec in AX
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cb2040b2ab68ab7d2863e65920749ed1266f7acd
元コミット内容
コミットメッセージは「runtime: fix openbsd nanotime?」と非常に簡潔です。これは、GoランタイムにおけるOpenBSD環境でのnanotime
関数の修正を示唆しています。末尾の疑問符は、この修正が問題の解決策として適切であるか、あるいはさらなる検証が必要であるかを示唆している可能性があります。TBR=r
とCC=golang-dev
は、コードレビューの担当者とメーリングリストを示しています。https://golang.org/cl/5353041
は、この変更に対応するGerritのチェンジリストへのリンクです。
変更の背景
Go言語のruntime.nanotime
関数は、プログラムの実行時間を高精度で計測するために使用されます。これは、プロファイリング、ベンチマーク、または時間ベースのアルゴリズムにおいて非常に重要です。多くのオペレーティングシステムでは、clock_gettime
のようなシステムコールがナノ秒単位の精度を提供しますが、古いシステムや特定の環境ではgettimeofday
が使用されることがあります。
gettimeofday
システムコールは、通常、秒とマイクロ秒(100万分の1秒)の精度で時刻を返します。このコミットの背景には、OpenBSD/amd64環境において、gettimeofday
システムコールが返したマイクロ秒の値が、Goランタイムのアセンブリコードで誤ったレジスタに読み込まれていたという問題があったと考えられます。これにより、nanotime
関数が不正確な値を返し、時間計測の信頼性が損なわれる可能性がありました。
アセンブリ言語レベルでのレジスタの誤用は、システムコール規約の誤解、または特定のOSバージョンやアーキテクチャにおけるレジスタ使用法の違いに起因することがあります。この修正は、OpenBSD/amd64におけるgettimeofday
の戻り値の処理が、Goランタイムの期待と一致するように調整されたことを示しています。
前提知識の解説
- Go言語のruntime: Goプログラムは、Goランタイムと呼ばれる独自の実行環境上で動作します。ランタイムは、ガベージコレクション、スケジューリング、システムコールインターフェースなど、プログラムの実行に必要な低レベルの機能を提供します。
nanotime
のような関数は、このランタイムの一部として実装されています。 nanotime
: Go言語の内部関数で、ナノ秒単位の精度でモノトニックな時間(システムの起動からの経過時間など、システム時刻の変更に影響されない時間)を返します。これは、プログラムのパフォーマンス測定や、時間差の計算に利用されます。- OpenBSD: セキュリティを重視したUNIX系オペレーティングシステムです。異なるOSは、システムコールやアセンブリレベルでの規約が異なる場合があります。
- amd64アーキテクチャ: IntelおよびAMDの64ビットプロセッサアーキテクチャです。x86-64とも呼ばれます。このアーキテクチャでは、システムコールや関数呼び出しにおいて、特定のレジスタが引数や戻り値の受け渡しに使用されるという規約(Calling Convention)があります。
- システムコール (SYSCALL): ユーザー空間で動作するプログラムが、カーネル(OSの核心部分)が提供するサービス(ファイルI/O、メモリ管理、時間取得など)を利用するためのメカニズムです。
SYSCALL
命令は、CPUを特権モードに切り替え、カーネル内の対応するハンドラを実行します。 gettimeofday
: UNIX系システムで利用されるシステムコールの一つで、現在の時刻を秒とマイクロ秒の精度で取得します。通常、struct timeval
構造体に秒とマイクロ秒が格納されて返されます。- アセンブリ言語: コンピュータのプロセッサが直接理解できる機械語に非常に近い低レベルのプログラミング言語です。レジスタ(
AX
,BX
,DX
など)は、CPU内部の高速な記憶領域であり、データの一時的な格納や演算に使用されます。AX
(Accumulator Register): 演算結果や関数の戻り値を格納するためによく使われます。BX
(Base Register): ベースアドレスの指定など、汎用的に使われます。DX
(Data Register): 汎用的に使われますが、AX
と組み合わせて32ビットや64ビットの演算結果を格納したり、I/Oポートのアドレス指定に使われたりすることもあります。システムコールによっては、特定の戻り値を格納するレジスタとして使用されることがあります。MOVL
: 32ビットの値を移動するアセンブリ命令です。MOVQ
: 64ビットの値を移動するアセンブリ命令です。SP
(Stack Pointer): スタックの現在のトップを指すレジスタです。8(SP)
や16(SP)
は、スタックポインタからのオフセットを示し、スタック上のメモリ位置にアクセスします。
技術的詳細
このコミットは、src/pkg/runtime/openbsd/amd64/sys.s
ファイル内のruntime·nanotime
関数のアセンブリコードを修正しています。この関数は、OpenBSD/amd64環境でgettimeofday
システムコールを使用して時刻を取得しています。
元のコードでは、gettimeofday
システムコールが実行された後、秒の値はAX
レジスタに、マイクロ秒の値はBX
レジスタに読み込まれると想定されていました。
MOVL $116, AX // sys_gettimeofday
SYSCALL
MOVQ 8(SP), AX // sec
MOVL 16(SP), BX // usec <-- ここが問題
しかし、OpenBSD/amd64のシステムコール規約、またはgettimeofday
システムコールの特定の動作において、マイクロ秒の値がBX
ではなくDX
レジスタに格納されることが判明したと考えられます。この誤ったレジスタからの読み込みが、nanotime
が不正確なマイクロ秒の値を使用する原因となっていました。
修正は、マイクロ秒の値をBX
からDX
に読み込むように変更することで、このレジスタの不一致を解消しています。
MOVL $116, AX // sys_gettimeofday
SYSCALL
MOVQ 8(SP), AX // sec
MOVL 16(SP), DX // usec <-- 修正後
この変更により、nanotime
関数はgettimeofday
から返される正しいマイクロ秒の値を取得できるようになり、結果としてより正確な時間計測が可能になります。Goランタイムは、取得した秒とマイクロ秒の値をナノ秒に変換して返します。
Web検索の結果によると、現代のGoランタイムは通常、より高精度なclock_gettime
を使用していますが、このコミットは2011年のものであり、当時のOpenBSD環境でのgettimeofday
の利用と、そのアセンブリレベルでの正確なレジスタハンドリングの重要性を示しています。
コアとなるコードの変更箇所
--- a/src/pkg/runtime/openbsd/amd64/sys.s
+++ b/src/pkg/runtime/openbsd/amd64/sys.s
@@ -139,7 +139,7 @@ TEXT runtime·nanotime(SB),7,$32
MOVL $116, AX // sys_gettimeofday
SYSCALL
MOVQ 8(SP), AX // sec
-\tMOVL 16(SP), BX // usec
+\tMOVL 16(SP), DX // usec
// sec is in AX, usec in DX
// return nsec in AX
コアとなるコードの解説
変更は、src/pkg/runtime/openbsd/amd64/sys.s
ファイル内のruntime·nanotime
関数にあります。
TEXT runtime·nanotime(SB),7,$32
:runtime·nanotime
関数の定義。SB
はシンボルベース、7
はフラグ、$32
はスタックフレームサイズを示します。MOVL $116, AX
:AX
レジスタに116
をロードします。116
はOpenBSD/amd64におけるgettimeofday
システムコールの番号です。SYSCALL
: システムコールを実行します。これにより、カーネルがgettimeofday
関数を実行し、結果をレジスタやスタックに配置します。MOVQ 8(SP), AX
: スタックポインタSP
から8バイトオフセットしたメモリ位置から64ビットの値(秒)をAX
レジスタに移動します。これはgettimeofday
が返す秒の部分です。- MOVL 16(SP), BX // usec
: 変更前の行です。スタックポインタSP
から16バイトオフセットしたメモリ位置から32ビットの値(マイクロ秒)をBX
レジスタに移動しようとしていました。+ MOVL 16(SP), DX // usec
: 変更後の行です。同じメモリ位置からマイクロ秒の値をDX
レジスタに移動します。この変更が、OpenBSD/amd64のシステムコール規約に合致し、正しいマイクロ秒の値を取得できるようにします。// sec is in AX, usec in DX
: コメントは、秒がAX
に、マイクロ秒がDX
にあることを示しており、修正後の状態を反映しています。// return nsec in AX
: 最終的に、秒とマイクロ秒から計算されたナノ秒の値がAX
レジスタに格納されて関数から返されます。
この修正は、システムコールから返されるデータが、アセンブリコードが期待するレジスタに正しく配置されるようにするための、低レベルかつ重要な調整です。
関連リンク
- Go Gerrit Change-ID: https://golang.org/cl/5353041
参考にした情報源リンク
- Go runtime nanotime OpenBSD gettimeofday assembly register BX DXに関するWeb検索結果
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH2vlr9vc1hGaoso8qnQ7PoMux-WI_DYCFk8chc5CRGB7kBQUIr8l13eRBzHVumAtke1RxbUh-TBgnfroL7XAhmJ7wFgNlnGKApKNC49fOm8WuanY69XBNWvHWSaDhURFR-Daw-JbrhLXCllxY4RcLlko3esNasY3TLIQLF
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFp-xbDR1yFPyYD7yptYWp3XvHJrdjDNxurk8i3182mgMeKp1larhs1AYMqiJsBBeolwL05-W00mL2LiJzrB_klMRlsSlHtR_boryBeIMOfszqFp0YMWC8DyiqmMxhxqs6L
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFqltEebXx_aCqN-Te8CrDjiqQ-4wYwkosGaFYml4qlaBe8ot1kWDj9A5CvmAyVEXc2PZhWKKwK7zEDMrgRe3tjlK2C0en91RNcjOoGgA283qxdZbhFixP1sRCfz7cO11c=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHQ1mbBk5hYYsq9CNnHX4qx6kLAzh4n3ALQNLUHiK_h5dVnqQSBHWB03ok5BdEw7DHlYrYih2DpNNzRShHvQNL-RJOLEXOH82KSIVBamAiR_sdx6gN4C96LhUqQZIiaDpB
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEFE29dF8IWQGxMmXQxi8LpnH8_2fiXk5YxPCJtzHkYyCoygR5UznviQ0Eggz5YVsQ04k26jazsJ03dHTaJEsqyHjoWxObRSu3YlyK9HeCIEnsYqi60ZKWiVsf6q_0mpNQk3nyaB9BMYuoLyIgx3f-SFJi58RkcfATRFrOtp2cGIo3gtqiG8giOZ1RIt2vQWC5QdtZx2QXkZ3XoYXkxvACyw==
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFE56fGMcJI_Qhd_SD-jqQmf89d9cXa7AeNYFozYcPJ3El_Am1vwAZy_Gg__-PGM_QRrPKIPBNCMO_Zo0akyouaxY-1iAH-guP6JAtXwDMXlo5-56RgdjYfEXURsQ==