# 機能設計書 42-ミューテックス

## 概要

SQLiteにおけるスレッドセーフな操作を実現するためのミューテックス（相互排他制御）機能の設計書。複数のミューテックス実装（pthreads、no-op）を抽象化し、統一的なインターフェースを提供する。

### 本機能の処理概要

SQLiteのミューテックス機能は、マルチスレッド環境での共有リソースへの安全なアクセスを保証する基盤機能である。

**業務上の目的・背景**：SQLiteはシングルスレッドからマルチスレッドまで様々な環境で使用されるため、スレッドセーフ性を柔軟に制御する必要がある。スレッドセーフが不要な環境ではオーバーヘッドを最小化し、必要な環境では適切な排他制御を提供する。このため、ミューテックス実装を抽象化し、コンパイル時・実行時に切り替え可能な設計となっている。

**機能の利用シーン**：
- データベース接続のスレッドセーフ操作
- メモリアロケータのグローバル状態保護
- ページキャッシュへの同時アクセス制御
- 乱数生成器の状態保護
- 共有スキーマ情報へのアクセス制御

**主要な処理内容**：
1. ミューテックス割り当て（sqlite3_mutex_alloc）：動的ミューテックスの生成または静的ミューテックスの取得
2. ミューテックス取得（sqlite3_mutex_enter）：排他ロックの取得（ブロッキング）
3. ミューテックス試行（sqlite3_mutex_try）：排他ロックの非ブロッキング試行
4. ミューテックス解放（sqlite3_mutex_leave）：排他ロックの解放
5. ミューテックス破棄（sqlite3_mutex_free）：動的ミューテックスの解放
6. ミューテックス保持確認（sqlite3_mutex_held/notheld）：デバッグ用アサーション

**関連システム・外部連携**：
- POSIXスレッドライブラリ（pthreads）
- Windowsクリティカルセクション（Windows環境）
- メモリ管理サブシステム（ミューテックス構造体の動的割り当て）

**権限による制御**：特になし（内部機能のためアプリケーションレベルの権限制御は不要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （内部機能） | - | API関数としてアプリケーションから呼び出し可能 |

## 機能種別

スレッド同期 / 排他制御 / 抽象化レイヤー

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id (iType) | int | Yes | ミューテックス種別（SQLITE_MUTEX_FAST等） | 有効な定数値 |
| p | sqlite3_mutex* | Yes | 操作対象のミューテックスポインタ | NULL許容（no-op扱い） |

### ミューテックス種別

| 定数 | 値 | 説明 |
|------|-----|------|
| SQLITE_MUTEX_FAST | 0 | 非再帰的高速ミューテックス |
| SQLITE_MUTEX_RECURSIVE | 1 | 再帰的ミューテックス（同一スレッドで複数回取得可） |
| SQLITE_MUTEX_STATIC_MAIN | 2 | グローバルデータベースリスト用静的ミューテックス |
| SQLITE_MUTEX_STATIC_MEM | 3 | メモリアロケータ用静的ミューテックス |
| SQLITE_MUTEX_STATIC_OPEN | 4 | sqlite3_open用静的ミューテックス |
| SQLITE_MUTEX_STATIC_PRNG | 5 | 乱数生成器用静的ミューテックス |
| SQLITE_MUTEX_STATIC_LRU | 6 | ページキャッシュLRU用静的ミューテックス |
| SQLITE_MUTEX_STATIC_PMEM | 7 | ページャメモリ用静的ミューテックス |
| SQLITE_MUTEX_STATIC_APP1-3 | 8-10 | アプリケーション用静的ミューテックス |
| SQLITE_MUTEX_STATIC_VFS1-3 | 11-13 | VFS用静的ミューテックス |

### 入力データソース

- SQLite内部サブシステムからの呼び出し
- アプリケーションコードからのAPI呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ミューテックスポインタ | sqlite3_mutex* | 割り当てられたミューテックス（失敗時NULL） |
| 試行結果 | int | SQLITE_OK（成功）またはSQLITE_BUSY（失敗） |
| 保持状態 | int | 1（保持中）または0（非保持） |

### 出力先

- 呼び出し元への戻り値
- デバッグビルド時のトレース出力（printf）

## 処理フロー

### 処理シーケンス

```
1. ミューテックスサブシステム初期化（sqlite3MutexInit）
   ├─ xMutexAlloc未設定の場合、デフォルト実装を選択
   │   ├─ bCoreMutex有効：sqlite3DefaultMutex()（pthreads）
   │   └─ bCoreMutex無効：sqlite3NoopMutex()（no-op）
   ├─ 関数ポインタをsqlite3GlobalConfig.mutexにコピー
   └─ xMutexInit()を呼び出し

2. ミューテックス割り当て（sqlite3_mutex_alloc）
   ├─ 動的ミューテックス（FAST/RECURSIVE）
   │   ├─ メモリ割り当て
   │   ├─ pthread_mutex_init（pthreads実装時）
   │   └─ 初期化済みポインタ返却
   └─ 静的ミューテックス（STATIC_*）
       └─ 事前初期化済み配列からポインタ返却

3. ミューテックス取得（sqlite3_mutex_enter）
   ├─ NULLチェック（NULLなら即座にreturn）
   ├─ [pthreads] pthread_mutex_lock
   └─ [debug] nRef++、owner設定

4. ミューテックス解放（sqlite3_mutex_leave）
   ├─ NULLチェック（NULLなら即座にreturn）
   ├─ [pthreads] pthread_mutex_unlock
   └─ [debug] nRef--、owner解除
```

### フローチャート

```mermaid
flowchart TD
    A[sqlite3MutexInit] --> B{xMutexAlloc設定済み?}
    B -->|No| C{bCoreMutex有効?}
    C -->|Yes| D[sqlite3DefaultMutex]
    C -->|No| E[sqlite3NoopMutex]
    D --> F[関数ポインタをコピー]
    E --> F
    B -->|Yes| G[xMutexInit呼び出し]
    F --> G
    G --> H[初期化完了]

    I[sqlite3_mutex_alloc] --> J{id種別?}
    J -->|FAST/RECURSIVE| K[メモリ割り当て]
    K --> L[pthread_mutex_init]
    L --> M[ポインタ返却]
    J -->|STATIC_*| N[静的配列参照]
    N --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | 再帰的取得 | RECURSIVEミューテックスは同一スレッドで複数回取得可能 | SQLITE_MUTEX_RECURSIVE使用時 |
| BR-42-02 | NULLセーフ | NULLポインタに対する操作はno-op | 全API |
| BR-42-03 | 静的ミューテックス共有 | 同一IDの静的ミューテックスは常に同じインスタンス | STATIC_*使用時 |
| BR-42-04 | 解放禁止 | 静的ミューテックスはfreeしてはならない | STATIC_*使用時 |
| BR-42-05 | デッドロック回避 | 複数ミューテックス取得時は一貫した順序で取得 | 設計指針 |

### ミューテックス実装の選択

| 条件 | 選択される実装 |
|------|---------------|
| SQLITE_MUTEX_OMIT定義 | ミューテックス機能無効 |
| SQLITE_MUTEX_NOOP定義 | no-op実装（常時） |
| SQLITE_MUTEX_PTHREADS定義 | pthreads実装 |
| bCoreMutex=1（デフォルト） | プラットフォームデフォルト |
| bCoreMutex=0 | no-op実装 |

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベーステーブルを直接操作しない（スレッド同期機能のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_BUSY | ロック競合 | sqlite3_mutex_tryでロック取得失敗 | リトライまたは待機 |
| NULL返却 | 割り当て失敗 | メモリ不足でミューテックス生成失敗 | エラー伝播 |
| SQLITE_MISUSE | API誤用 | 無効なミューテックスIDまたは静的ミューテックスの解放試行 | API_ARMOR有効時のみ検出 |

### リトライ仕様

sqlite3_mutex_tryはリトライ不可（即座に結果返却）。ブロッキング取得が必要な場合はsqlite3_mutex_enterを使用。

## トランザクション仕様

ミューテックス操作自体はトランザクションの対象外。ただし、ミューテックスはトランザクション処理中のデータ整合性を保護するために使用される。

## パフォーマンス要件

- no-op実装：オーバーヘッドほぼゼロ
- pthreads実装：OSのネイティブミューテックス性能に依存
- 静的ミューテックス：動的割り当て不要で初期化コスト削減

## セキュリティ考慮事項

- SQLITE_ENABLE_MULTITHREADED_CHECKS有効時、マルチスレッド違反を検出しログ出力
- デバッグビルド時、ミューテックス保持状態をassert()で検証

## 備考

- SQLITE_HOMEGROWN_RECURSIVE_MUTEXで自前の再帰ミューテックス実装を使用可能
- sqlite3MemoryBarrier()でメモリバリアを提供（ミューテックスなしのアトミック操作用）
- TSANビルド時、sqlite3_mutex_held/notheldは常に1を返す（誤検出回避）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ミューテックスの抽象化インターフェースと具体的な構造体を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | sqlite3_mutex_methods構造体：ミューテックス操作の関数ポインタ |
| 1-2 | mutex_unix.c | `src/mutex_unix.c` | struct sqlite3_mutex（41-51行目）：pthreads実装の構造体 |
| 1-3 | mutex_noop.c | `src/mutex_noop.c` | sqlite3_debug_mutex（80-83行目）：デバッグ用構造体 |

**読解のコツ**: sqlite3_mutex_methodsは仮想関数テーブルに相当し、xMutexAlloc、xMutexEnter等の関数ポインタで実装を切り替える。

#### Step 2: 初期化とデフォルト実装選択を理解する

ミューテックスサブシステムの初期化フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mutex.c | `src/mutex.c` | sqlite3MutexInit（219-259行目）：初期化と実装選択 |
| 2-2 | mutex_unix.c | `src/mutex_unix.c` | sqlite3DefaultMutex（373-392行目）：pthreads実装のメソッドテーブル |
| 2-3 | mutex_noop.c | `src/mutex_noop.c` | sqlite3NoopMutex（52-67行目/188-203行目）：no-op実装 |

**主要処理フロー**:
1. **221行目**: xMutexAlloc未設定なら新規設定
2. **230-238行目**: bCoreMutex値で実装を選択
3. **239-248行目**: 関数ポインタをsqlite3GlobalConfig.mutexにコピー
4. **251行目**: xMutexInit()を呼び出し

#### Step 3: 公開APIを理解する

アプリケーションが使用するAPI関数の実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mutex.c | `src/mutex.c` | sqlite3_mutex_alloc（281-288行目）：ミューテックス割り当て |
| 3-2 | mutex.c | `src/mutex.c` | sqlite3_mutex_enter（313-318行目）：ロック取得 |
| 3-3 | mutex.c | `src/mutex.c` | sqlite3_mutex_try（324-331行目）：非ブロッキング試行 |
| 3-4 | mutex.c | `src/mutex.c` | sqlite3_mutex_leave（339-344行目）：ロック解放 |
| 3-5 | mutex.c | `src/mutex.c` | sqlite3_mutex_free（302-307行目）：ミューテックス破棄 |

**主要処理フロー**:
- **313-318行目**: NULLチェック後にxMutexEnter呼び出し
- **324-331行目**: NULLならSQLITE_OK、それ以外はxMutexTry呼び出し

#### Step 4: pthreads実装の詳細を理解する

Unix環境でのpthreadsを使用した実装。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | mutex_unix.c | `src/mutex_unix.c` | pthreadMutexAlloc（153-216行目）：割り当て処理 |
| 4-2 | mutex_unix.c | `src/mutex_unix.c` | pthreadMutexEnter（251-292行目）：ロック取得 |
| 4-3 | mutex_unix.c | `src/mutex_unix.c` | pthreadMutexLeave（350-371行目）：ロック解放 |
| 4-4 | mutex_unix.c | `src/mutex_unix.c` | pthreadMutexHeld/Notheld（78-84行目）：保持状態確認 |

**主要処理フロー**:
- **170-189行目**: RECURSIVE時はpthread_mutexattr_settypeでPTHREAD_MUTEX_RECURSIVEを設定
- **279行目**: pthread_mutex_lockでブロッキング取得
- **282-283行目**: owner設定とnRefインクリメント（SQLITE_MUTEX_NREF時）
- **363行目**: pthread_mutex_unlockで解放

#### Step 5: no-op実装とデバッグ機能を理解する

シングルスレッド環境用のno-op実装とデバッグ支援機能。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | mutex_noop.c | `src/mutex_noop.c` | noopMutexAlloc（40-43行目）：常に固定値(8)を返却 |
| 5-2 | mutex_noop.c | `src/mutex_noop.c` | debugMutexEnter（163-167行目）：カウンタインクリメントのみ |
| 5-3 | mutex.c | `src/mutex.c` | sqlite3_mutex_held/notheld（354-371行目）：assert用関数 |

**主要処理フロー**:
- **42行目**: noopMutexAllocは`(sqlite3_mutex*)8`を返却（NULLでないダミー値）
- **166行目**: debugMutexEnterはcnt++のみで実際の排他制御なし

### プログラム呼び出し階層図

```
sqlite3_mutex_enter(p)
    │
    └─ sqlite3GlobalConfig.mutex.xMutexEnter(p)
           │
           ├─ [pthreads] pthreadMutexEnter()
           │      ├─ pthread_mutex_lock()
           │      └─ owner/nRef更新（SQLITE_MUTEX_NREF時）
           │
           ├─ [noop] noopMutexEnter()
           │      └─ 何もしない
           │
           └─ [debug] debugMutexEnter()
                  └─ cnt++

sqlite3MutexInit()
    │
    ├─ [bCoreMutex=1] sqlite3DefaultMutex()
    │      └─ pthreads関数テーブル返却
    │
    └─ [bCoreMutex=0] sqlite3NoopMutex()
           └─ noop関数テーブル返却
```

### データフロー図

```
[入力]                    [処理]                           [出力]

mutex_id ──────────▶ sqlite3_mutex_alloc() ─────────▶ sqlite3_mutex*
                           │
                           ▼
                    ┌─────────────────┐
                    │ 静的/動的判定   │
                    └─────────────────┘
                           │
           ┌───────────────┼───────────────┐
           ▼               ▼               ▼
    [静的配列]       [malloc+init]    [ダミー値(8)]
    staticMutexes[]  pthread_mutex_t   (noop時)


sqlite3_mutex* ────▶ sqlite3_mutex_enter() ────────▶ ロック取得
                           │
                           ▼
                    ┌─────────────────┐
                    │ pthread_mutex   │
                    │ _lock()         │
                    └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mutex.c | `src/mutex.c` | ソース | ミューテックス共通処理、公開API、初期化 |
| mutex_unix.c | `src/mutex_unix.c` | ソース | pthreadsを使用したUnix向けミューテックス実装 |
| mutex_noop.c | `src/mutex_noop.c` | ソース | シングルスレッド用no-op実装、デバッグ用実装 |
| mutex_w32.c | `src/mutex_w32.c` | ソース | Windows向けクリティカルセクション実装 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | sqlite3_mutex_methods定義、ミューテックス定数 |
| sqlite3.h | `src/sqlite3.h` | ヘッダ | 公開API宣言、SQLITE_MUTEX_*定数 |
