[インデックス 17197] ファイルの概要
このコミットは、Go言語の sync/atomic
パッケージにおけるARMアーキテクチャ向けアセンブリコード内のコメントの記述を修正するものです。具体的には、アトミック操作に使用される LDREX
/STREX
および LDREXD
/STREXD
命令が導入されたARMアーキテクチャのバージョンに関する記述の誤りを訂正し、より正確な「ARMv6」および「ARMv6k」という用語に修正しています。
コミット
commit 7eb6a6f46d8e9443f8c827c0ae456689b97de629
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Tue Aug 13 22:07:21 2013 +0400
sync/atomic: fix ARM nomenclature in comments
R=cshapiro
CC=golang-dev
https://golang.org/cl/12877043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/7eb6a6f46d8e9443f8c827c0ae456689b97de629
元コミット内容
sync/atomic: fix ARM nomenclature in comments
変更の背景
Go言語の sync/atomic
パッケージは、マルチコアプロセッサ環境において、複数のゴルーチン(Goの軽量スレッド)が共有データに安全にアクセスするためのアトミック操作を提供します。これらの操作は、通常、CPUが提供する特殊なアトミック命令(例: Compare-and-Swap, Fetch-and-Add)を利用して実装されます。ARMアーキテクチャでは、これらのアトミック操作を実現するために LDREX
(Load-Exclusive) と STREX
(Store-Exclusive) 命令のペア、および64ビット操作のための LDREXD
と STREXD
命令のペアが使用されます。
このコミットが行われる前、GoのARMアセンブリコード内のコメントでは、これらの命令が導入されたARMアーキテクチャのバージョンについて「ARM 6」や「ARM 11」といった記述がされていました。しかし、これはARMアーキテクチャのバージョン命名規則や、特定の命令セット拡張が導入された正確なバージョンを反映していませんでした。
具体的には、LDREX
/STREX
命令はARMv6アーキテクチャで導入され、LDREXD
/STREXD
命令はARMv6kアーキテクチャ(ARMv6の拡張版で、カーネルプロファイル向け)で導入されました。コメントの記述が不正確であると、コードの可読性や保守性が低下し、将来的なARMアーキテクチャのサポートや最適化において混乱を招く可能性がありました。
このコミットは、このような不正確なコメントを修正し、ARMアーキテクチャの正確な命名規則と命令セットの導入時期に合致させることを目的としています。これにより、コードの正確性が向上し、開発者がARMアーキテクチャ固有の動作をより正確に理解できるようになります。
前提知識の解説
ARMアーキテクチャ
ARM (Advanced RISC Machine) は、モバイルデバイス、組み込みシステム、サーバーなど、幅広い分野で利用されているRISC (Reduced Instruction Set Computer) ベースのプロセッサアーキテクチャです。ARMアーキテクチャは、その電力効率の高さと性能のバランスから広く採用されています。
ARMアーキテクチャには、ARMv4、ARMv5、ARMv6、ARMv7、ARMv8など、多くのバージョンが存在し、それぞれ異なる命令セットや機能拡張が導入されています。
アトミック操作と排他ロード/ストア命令
マルチスレッドプログラミングにおいて、複数のスレッドが共有データに同時にアクセスすると、競合状態(Race Condition)が発生し、データの整合性が損なわれる可能性があります。これを防ぐために、アトミック操作が用いられます。アトミック操作とは、その操作全体が不可分(中断されない)であることを保証する操作です。
ARMアーキテクチャでは、アトミック操作を効率的に実現するために、以下の排他ロード/ストア命令が提供されています。
- LDREX (Load-Exclusive): 指定されたメモリアドレスから値をロードし、そのアドレスに対する排他アクセスをマークします。
- STREX (Store-Exclusive): 指定されたメモリアドレスに値をストアしようとします。このストアが成功するのは、
LDREX
以降、他のプロセッサやスレッドが同じアドレスに書き込みを行っていない場合のみです。成功した場合は0を、失敗した場合は非ゼロの値を返します。
これらの命令はペアで使用され、Compare-and-Swap (CAS) のようなアトミック操作をループ内で実装する際に利用されます。LDREX
で値を読み込み、変更を計算し、STREX
で書き戻そうとします。もし STREX
が失敗した場合(他のスレッドがその間にメモリを変更したため)、ループを再試行して競合を解決します。
LDREXD / STREXD
LDREXD
(Load-Exclusive Doubleword) と STREXD
(Store-Exclusive Doubleword) は、LDREX
と STREX
の64ビット版です。これらは、64ビットの値をアトミックに操作する必要がある場合(例えば、64ビットカウンタのインクリメントや64ビットポインタの交換など)に使用されます。
ARMv6とARMv6k
- ARMv6: 2001年に発表されたARMアーキテクチャのバージョンで、
LDREX
とSTREX
命令が導入されました。これにより、ARMプロセッサ上での効率的なロックフリープログラミングやアトミック操作の実装が可能になりました。 - ARMv6k: ARMv6アーキテクチャの拡張版で、特にカーネルプロファイル(K-profile)向けに設計されました。このバージョンで
LDREXD
とSTREXD
命令が導入され、64ビットのアトミック操作がサポートされるようになりました。
このコミットは、これらのARMアーキテクチャのバージョンと命令の導入時期に関する正確な知識に基づいています。
技術的詳細
このコミットの技術的な詳細は、Go言語の sync/atomic
パッケージ内のARMアセンブリコードのコメント修正に集約されます。Goのランタイムは、パフォーマンスが重要なアトミック操作のために、Go言語ではなく直接アセンブリ言語で実装された関数を使用することがあります。これは、特定のCPUアーキテクチャの低レベルな命令を直接利用することで、最高の性能と正確性を引き出すためです。
修正対象となったファイルは src/pkg/sync/atomic/asm_arm.s
です。このファイルには、ARMアーキテクチャ向けのアトミック操作(例: CompareAndSwapUint32
, CompareAndSwapUint64
, AddUint32
, AddUint64
, SwapUint32
, SwapUint64
)の実装が含まれています。
変更内容は以下の通りです。
-
LDREX
とSTREX
命令に関するコメントの修正:- 変更前:
// LDREX and STREX were introduced in ARM 6.
- 変更後:
// LDREX and STREX were introduced in ARMv6.
- この修正は、「ARM 6」という非公式な記述を、正式なアーキテクチャバージョン名である「ARMv6」に訂正しています。
LDREX
とSTREX
はARMv6で導入された排他ロード/ストア命令であり、これにより32ビットのアトミック操作が可能になりました。
- 変更前:
-
LDREXD
とSTREXD
命令に関するコメントの修正:- 変更前:
// LDREXD and STREXD were introduced in ARM 11.
- 変更後:
// LDREXD and STREXD were introduced in ARMv6k.
- この修正は、「ARM 11」という不正確な記述を、正確なアーキテクチャバージョン名である「ARMv6k」に訂正しています。
LDREXD
とSTREXD
はARMv6kで導入された64ビットの排他ロード/ストア命令であり、これにより64ビットのアトミック操作が可能になりました。
- 変更前:
これらの修正は、コードの機能には影響を与えませんが、ドキュメンテーションとしてのコメントの正確性を大幅に向上させます。特に、ARMアーキテクチャの進化と命令セットの導入時期に関する正確な情報を提供することで、将来のメンテナンスやデバッグ、あるいはARMアーキテクチャに特化した最適化を行う際に、開発者が誤った情報に基づいて判断することを防ぎます。
Go言語のようなクロスプラットフォームを強く意識した言語では、各アーキテクチャ固有のアセンブリコードの正確な記述とコメントは非常に重要です。このコミットは、その品質と正確性を維持するための細かな、しかし重要な改善と言えます。
コアとなるコードの変更箇所
--- a/src/pkg/sync/atomic/asm_arm.s
+++ b/src/pkg/sync/atomic/asm_arm.s
@@ -13,7 +13,7 @@ TEXT ·armCompareAndSwapUint32(SB),NOSPLIT,$0-13
MOVW old+4(FP), R2
MOVW new+8(FP), R3
casloop:
- // LDREX and STREX were introduced in ARM 6.
+ // LDREX and STREX were introduced in ARMv6.
LDREX (R1), R0
CMP R0, R2
BNE casfail
@@ -40,7 +40,7 @@ TEXT ·armCompareAndSwapUint64(SB),NOSPLIT,$0-21
MOVW newlo+12(FP), R4
MOVW newhi+16(FP), R5
cas64loop:
- // LDREXD and STREXD were introduced in ARM 11.
+ // LDREXD and STREXD were introduced in ARMv6k.
LDREXD (R1), R6 // loads R6 and R7
CMP R2, R6
BNE cas64fail
@@ -61,7 +61,7 @@ TEXT ·armAddUint32(SB),NOSPLIT,$0-12
MOVW addr+0(FP), R1
MOVW delta+4(FP), R2
addloop:
- // LDREX and STREX were introduced in ARM 6.
+ // LDREX and STREX were introduced in ARMv6.
LDREX (R1), R3
ADD R2, R3
STREX R3, (R1), R0
@@ -80,7 +80,7 @@ TEXT ·armAddUint64(SB),NOSPLIT,$0-20
MOVW deltalo+4(FP), R2
MOVW deltahi+8(FP), R3
add64loop:
- // LDREXD and STREXD were introduced in ARM 11.
+ // LDREXD and STREXD were introduced in ARMv6k.
LDREXD (R1), R4 // loads R4 and R5
ADD.S R2, R4
ADC R3, R5
@@ -95,7 +95,7 @@ TEXT ·armSwapUint32(SB),NOSPLIT,$0-12
MOVW addr+0(FP), R1
MOVW new+4(FP), R2
swaploop:
- // LDREX and STREX were introduced in ARM 6.
+ // LDREX and STREX were introduced in ARMv6.
LDREX (R1), R3
STREX R2, (R1), R0
CMP $0, R0
@@ -113,7 +113,7 @@ TEXT ·armSwapUint64(SB),NOSPLIT,$0-20
MOVW newlo+4(FP), R2
MOVW newhi+8(FP), R3
swap64loop:
- // LDREXD and STREXD were introduced in ARM 11.
+ // LDREXD and STREXD were introduced in ARMv6k.
LDREXD (R1), R4 // loads R4 and R5
STREXD R2, (R1), R0 // stores R2 and R3
CMP $0, R0
コアとなるコードの解説
変更はすべて src/pkg/sync/atomic/asm_arm.s
ファイル内のコメント行にあります。
-
TEXT ·armCompareAndSwapUint32(SB),NOSPLIT,$0-13
関数内:// LDREX and STREX were introduced in ARM 6.
が// LDREX and STREX were introduced in ARMv6.
に変更されました。- これは、32ビットのCompare-and-Swap操作を実装するアセンブリコードのコメントです。
LDREX
とSTREX
命令がARMv6アーキテクチャで導入されたことを正確に示しています。
-
TEXT ·armCompareAndSwapUint64(SB),NOSPLIT,$0-21
関数内:// LDREXD and STREXD were introduced in ARM 11.
が// LDREXD and STREXD were introduced in ARMv6k.
に変更されました。- これは、64ビットのCompare-and-Swap操作を実装するアセンブリコードのコメントです。
LDREXD
とSTREXD
命令がARMv6kアーキテクチャで導入されたことを正確に示しています。
-
TEXT ·armAddUint32(SB),NOSPLIT,$0-12
関数内:// LDREX and STREX were introduced in ARM 6.
が// LDREX and STREX were introduced in ARMv6.
に変更されました。- これは、32ビットのAdd操作を実装するアセンブリコードのコメントです。
-
TEXT ·armAddUint64(SB),NOSPLIT,$0-20
関数内:// LDREXD and STREXD were introduced in ARM 11.
が// LDREXD and STREXD were introduced in ARMv6k.
に変更されました。- これは、64ビットのAdd操作を実装するアセンブリコードのコメントです。
-
TEXT ·armSwapUint32(SB),NOSPLIT,$0-12
関数内:// LDREX and STREX were introduced in ARM 6.
が// LDREX and STREX were introduced in ARMv6.
に変更されました。- これは、32ビットのSwap操作を実装するアセンブリコードのコメントです。
-
TEXT ·armSwapUint64(SB),NOSPLIT,$0-20
関数内:// LDREXD and STREXD were introduced in ARM 11.
が// LDREXD and STREXD were introduced in ARMv6k.
に変更されました。- これは、64ビットのSwap操作を実装するアセンブリコードのコメントです。
これらの変更はすべてコメントの修正であり、アセンブリコードの実行ロジック自体には影響を与えません。しかし、Go言語のランタイムコードベースにおけるドキュメンテーションの正確性を高める上で重要な役割を果たします。特に、ARMアーキテクチャのバージョンと命令セットの関連性を正確に記述することで、将来のARMプロセッサのサポートや最適化作業において、開発者がより正確な情報を参照できるようになります。
関連リンク
- ARMアーキテクチャのバージョン履歴: https://en.wikipedia.org/wiki/ARM_architecture#Architecture_versions
- ARMv6命令セット: https://developer.arm.com/documentation/ddi0301/e/
- ARMv6k命令セット: https://developer.arm.com/documentation/ddi0301/e/ (ARMv6のドキュメントに含まれることが多い)
- Go言語の
sync/atomic
パッケージ: https://pkg.go.dev/sync/atomic
参考にした情報源リンク
- GitHub: golang/go commit 7eb6a6f46d8e9443f8c827c0ae456689b97de629: https://github.com/golang/go/commit/7eb6a6f46d8e9443f8c827c0ae456689b97de629
- Go CL 12877043: https://golang.org/cl/12877043
- ARM Architecture Reference Manuals (ARM Developer): https://developer.arm.com/documentation/
- Wikipedia: ARMアーキテクチャ: https://ja.wikipedia.org/wiki/ARM%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
- Wikipedia: Load-link/store-conditional: https://en.wikipedia.org/wiki/Load-link/store-conditional
- Stack Overflow: What is the difference between ARMv6 and ARMv6k?: https://stackoverflow.com/questions/1000000/what-is-the-difference-between-armv6-and-armv6k
- ARM Cortex-A Series Programmer's Guide for ARMv7-A: https://developer.arm.com/documentation/den0013/d/ (LDREX/STREXの概念理解に利用)
- ARMv6-M Architecture Reference Manual: https://developer.arm.com/documentation/ddi0419/latest/ (ARMv6の命令セットに関する情報)
- ARMv6-R Architecture Reference Manual: https://developer.arm.com/documentation/ddi0406/latest/ (ARMv6の命令セットに関する情報)
- ARMv7-A and ARMv7-R Architecture Reference Manual: https://developer.arm.com/documentation/ddi0406/latest/ (LDREXD/STREXDの概念理解に利用)
- ARMv8-A Architecture Reference Manual: https://developer.arm.com/documentation/ddi0487/latest/ (より新しいARMアーキテクチャの参考)
- Go言語のソースコード:
src/pkg/sync/atomic/asm_arm.s
(コミット対象ファイル)