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

[インデックス 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ビット操作のための LDREXDSTREXD 命令のペアが使用されます。

このコミットが行われる前、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) は、LDREXSTREX の64ビット版です。これらは、64ビットの値をアトミックに操作する必要がある場合(例えば、64ビットカウンタのインクリメントや64ビットポインタの交換など)に使用されます。

ARMv6とARMv6k

  • ARMv6: 2001年に発表されたARMアーキテクチャのバージョンで、LDREXSTREX 命令が導入されました。これにより、ARMプロセッサ上での効率的なロックフリープログラミングやアトミック操作の実装が可能になりました。
  • ARMv6k: ARMv6アーキテクチャの拡張版で、特にカーネルプロファイル(K-profile)向けに設計されました。このバージョンで LDREXDSTREXD 命令が導入され、64ビットのアトミック操作がサポートされるようになりました。

このコミットは、これらのARMアーキテクチャのバージョンと命令の導入時期に関する正確な知識に基づいています。

技術的詳細

このコミットの技術的な詳細は、Go言語の sync/atomic パッケージ内のARMアセンブリコードのコメント修正に集約されます。Goのランタイムは、パフォーマンスが重要なアトミック操作のために、Go言語ではなく直接アセンブリ言語で実装された関数を使用することがあります。これは、特定のCPUアーキテクチャの低レベルな命令を直接利用することで、最高の性能と正確性を引き出すためです。

修正対象となったファイルは src/pkg/sync/atomic/asm_arm.s です。このファイルには、ARMアーキテクチャ向けのアトミック操作(例: CompareAndSwapUint32, CompareAndSwapUint64, AddUint32, AddUint64, SwapUint32, SwapUint64)の実装が含まれています。

変更内容は以下の通りです。

  1. LDREXSTREX 命令に関するコメントの修正:

    • 変更前: // LDREX and STREX were introduced in ARM 6.
    • 変更後: // LDREX and STREX were introduced in ARMv6.
    • この修正は、「ARM 6」という非公式な記述を、正式なアーキテクチャバージョン名である「ARMv6」に訂正しています。LDREXSTREX はARMv6で導入された排他ロード/ストア命令であり、これにより32ビットのアトミック操作が可能になりました。
  2. LDREXDSTREXD 命令に関するコメントの修正:

    • 変更前: // LDREXD and STREXD were introduced in ARM 11.
    • 変更後: // LDREXD and STREXD were introduced in ARMv6k.
    • この修正は、「ARM 11」という不正確な記述を、正確なアーキテクチャバージョン名である「ARMv6k」に訂正しています。LDREXDSTREXD は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操作を実装するアセンブリコードのコメントです。LDREXSTREX 命令が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操作を実装するアセンブリコードのコメントです。LDREXDSTREXD 命令が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プロセッサのサポートや最適化作業において、開発者がより正確な情報を参照できるようになります。

関連リンク

参考にした情報源リンク