# 排他制御(SpinLock) (overview)

SpinLock (スピンロック) は、ARMプロセッサの swp 命令を使い、スレッド間やプロセッサ間の排他制御を行なうための機構です。

スレッド間の排他制御を行なうものとしては、Mutex や Message もありますが、スピンロックはそれらと異なり、ロック時のスレッド切り替えは発生しません。その場でループしてロックの解除を待ちます。

TWL-SDK内部では、スピンロックを以下の用途で使用しています。

- プロセッサ間での、カートリッジへのアクセス排他制御
- プロセッサ間での、カードへのアクセス排他制御
- プロセッサ間での、VRAM C と VRAM D へのアクセス排他制御
- プロセッサ間での、初期化時( `OS_InitLock()` ) の同期取り

このページでは、これら TWL-SDK で扱われているスピンロックを用いた同期処理の関数について説明します。

## SDK で使用する spin lock の初期化

SDK で使用しているスピンロックに関しての初期化を行なう関数は `OS_InitLock()` です。ただしこれは `OS_Init()` の中で呼ばれていますので、特にアプリケーションで呼び出す必要はありません。

`OS_InitLock()` では他方のプロセッサの `OS_InitLock()` と同期を取るという処理も行なっています。

## カードアクセスの排他制御

カードへのアクセス権は通常 ARM7 にあります。`OS_LockCard()` を呼ぶことで、アクセス権は ARM9 となり、ARM7 からのアクセスをロックします。

`OS_UnlockCard()` を呼ぶと、カードへのアクセス権を ARM7 にして、ロックを解除します。

`OS_LockCard()` はロック出来るまで関数から戻りませんが、`OS_TryLockCard()` では一度だけロックを試行します。返り値でロックできたかどうかを知ることが出来ます。

## カートリッジアクセスの排他制御

カートリッジのアクセス権は通常 ARM7 にあります。`OS_LockCartridge()` を呼ぶことで、アクセス権は ARM9 となり、ARM7 からのアクセスをロックします。

`OS_UnlockCartridge()` を呼ぶと、カートリッジへのアクセス権を ARM7 にして、ロックを解除します。

`OS_LockCartridge()` はロック出来るまで関数から戻りませんが、`OS_TryLockCartridge()` では一度だけロックを試行します。返り値でロックできたかどうかを知ることが出来ます。

## ロック関数に使用される ID

ロックに使用する ID ( u16 値 ) は、スレッド間、あるいはプロセッサ間で ( カードやカートリッジなどの) 同じリソースにアクセスしようとしたときは、異なる値でなければなりません。TWL-SDK ではこのロック ID に関する以下の関数を用意しています。

`OS_GetLockID()` は、ARM9 で用意されている ID 候補のなかから使用されていない値を返します。この値は ARM9、ARM7 問わず他のモジュールで使用されていないことが保証されています。 但し他のモジュールも `OS_GetLockID()` で値を取得していることが条件となります。TWL-SDK 内部でも必要な個所では `OS_GetLockID()` を使用していますので、アプリケーションが設定する値と重なることはありません。

その ID を使い終わったら `OS_ReleaseLockID()` で解放してください。この関数を呼ぶことで その ID は `OS_GetLockID()` の候補に戻され、次の `OS_GetLockID()` 以降で他のロックに使用されます。

なお、`OS_GetLockID()` で取得出来る値は、0x40 〜 0x6F のうちの何れかです。

(参考) 同じ関数は ARM7 側のライブラリにもあり、取得出来る値は 0x80 〜 0xA0 のうちの何れかです。

## 参照

`OS関数一覧(排他制御)
`

## 履歴

2009/06/03 `OS_Init()` が必須になったための記述修正
2004/12/14 用語や語尾など修正
2004/11/15 初版