# 機能設計書 3-スレッド管理

## 概要

本ドキュメントは、FreeBSDカーネルにおけるスレッド管理機能の設計を記述する。カーネルスレッドおよびユーザスレッドの生成・終了・同期・排他制御を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：スレッドはプロセス内の軽量な実行単位であり、同一アドレス空間を共有しながら並行処理を実現する。マルチコアCPUの性能を最大限に引き出すためには効率的なスレッド管理と同期機構が不可欠である。FreeBSDは1:1スレッドモデルを採用しており、各ユーザスレッドが1つのカーネルスレッドに対応する。

**機能の利用シーン**：マルチスレッドアプリケーション（Webサーバ、データベースエンジン等）の実行、カーネル内ワーカースレッドの管理、POSIXスレッド（pthread）ライブラリの基盤、スレッド間の排他制御（mutex）と条件同期（condvar）が利用される。

**主要な処理内容**：
1. **スレッド生成・終了**: thread_create()によるカーネルスレッド生成、thread_exit()による終了処理。ユーザスレッドはthr_new()システムコール経由で生成される。
2. **スレッド同期（mutex）**: kern_mutex.cによるカーネルmutex実装。スピンロックとスリープロック（adaptive mutex）を提供する。
3. **条件変数（condvar）**: kern_condvar.cによるカーネル条件変数。cv_wait()/cv_signal()/cv_broadcast()を提供する。
4. **スレッドサスペンド・シングルスレッド化**: thread_single()によるプロセス内の他スレッド停止。exit/exec時に使用される。
5. **スリープキュー・ターンスタイル**: スレッドのブロッキングと優先度継承を管理する機構。

**関連システム・外部連携**：プロセス管理（kern_fork.c）、スケジューラ（sched_ule.c）、POSIXスレッドライブラリ（libthr）、umtx（ユーザ空間mutex）サブシステムとの連携がある。

**権限による制御**：スレッド生成は所属プロセスのリソース制限（RLIMIT_NTHR）およびracctサブシステムによるスレッド数制限に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | スレッド管理はカーネル内部機能であり、直接的なUI画面は存在しない |

## 機能種別

カーネル基盤機能（スレッドライフサイクル管理・同期プリミティブ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| thr_new_args.param | struct thr_param * | Yes | スレッド生成パラメータ | start_func非NULL |
| thr_new_args.param_size | int | Yes | パラメータ構造体サイズ | sizeof(struct thr_param) |
| thr_param.start_func | void (*)(void *) | Yes | スレッド開始関数 | 有効な関数ポインタ |
| thr_param.arg | void * | No | スレッド開始関数への引数 | - |
| thr_param.stack_base | char * | No | スタックベースアドレス | ページアライメント推奨 |
| thr_param.stack_size | size_t | No | スタックサイズ | 0の場合デフォルト |

### 入力データソース

thr_new()システムコール経由のユーザ空間要求、およびカーネル内からのkthread_add()呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| thr_new戻り値 | int | 成功時0、失敗時errno |
| child_tid | long * | 生成されたスレッドのTID |

### 出力先

カーネル内スレッドテーブル（proc->p_threadsリスト）。

## 処理フロー

### 処理シーケンス

```
1. スレッド生成
   ├─ thr_new() システムコール
   │    ├─ thread_create(): thread構造体割り当て
   │    ├─ cpu_copy_thread(): CPUコンテキスト初期化
   │    ├─ sched_fork_thread(): スケジューラ登録
   │    └─ thread_stash(): 旧スレッドの後処理
   │
2. スレッド終了
   ├─ thr_exit() システムコール → thread_exit()
   │    ├─ リソース解放
   │    ├─ proc->p_numthreadsデクリメント
   │    └─ sched_throw(): スケジューラからの離脱
   │
3. スレッド同期
   ├─ mutex: mtx_lock() / mtx_unlock()
   │    ├─ adaptive spinning（所有者が実行中なら短時間スピン）
   │    └─ turnstile（ブロック時の優先度継承）
   ├─ condvar: cv_wait() / cv_signal()
   │    └─ sleepqueue（条件変数待ちキュー）
```

### フローチャート

```mermaid
flowchart TD
    A[thr_new システムコール] --> B[thread_create]
    B --> C[thread構造体UMA割当]
    C --> D[cpu_copy_thread]
    D --> E[sched_fork_thread]
    E --> F[新スレッド実行可能]
    F --> G{スケジューリング}
    G --> H[スレッド実行]
    H --> I{終了?}
    I -->|No| G
    I -->|Yes| J[thread_exit]
    J --> K[リソース解放]
    K --> L[sched_throw]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 1:1スレッドモデル | 1ユーザスレッドに1カーネルスレッドが対応 | 全スレッド生成時 |
| BR-02 | スレッド数制限 | RLIMIT_NTHRによるプロセス当たりスレッド数上限 | thread_create()時 |
| BR-03 | 優先度継承 | mutexブロック時に所有スレッドの優先度を一時的に引き上げ | turnstile使用時 |
| BR-04 | シングルスレッド化 | exec/exit時に他スレッドを停止 | thread_single()呼び出し時 |

### 計算ロジック

mutex取得時のadaptive spinningは、mutex所有者が他のCPUで実行中である場合に短時間スピンし、コンテキスト切替のコストを回避する。

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

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

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| thr_new | proc->p_threads | INSERT | スレッドリストへの追加 |
| thread_exit | proc->p_threads | DELETE | スレッドリストからの削除 |
| mtx_lock | turnstile | UPDATE | 競合時のブロッキング状態管理 |
| cv_wait | sleepqueue | INSERT | 待機キューへの追加 |

### テーブル別操作詳細

#### struct thread

| 操作 | 項目（フィールド名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | td_tid | 新規TID | UMA割り当て時 |
| INSERT | td_proc | 所属プロセス | 親プロセスのポインタ |
| UPDATE | td_state | TDS_RUNNING/TDS_INHIBITED等 | 状態遷移時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EAGAIN | リソース制限 | スレッド数上限到達 | 既存スレッド終了後に再試行 |
| ENOMEM | メモリ不足 | thread構造体割り当て失敗 | メモリ解放後に再試行 |
| EFAULT | 不正アドレス | thr_paramのcopyin失敗 | 正しいポインタを指定 |
| EDEADLK | デッドロック | mutexの再帰ロック（WITNESS検出） | ロック順序の修正 |

### リトライ仕様

カーネル内部でのスレッド生成失敗時は呼び出し元に即座にエラーを返す。ユーザ空間での再試行は呼び出し側の責任。

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

スレッド操作はプロセスロック（PROC_LOCK）およびスレッド固有ロック（thread lock）により保護される。mutex操作はturnstileチェーンロックで保護される。condvar操作はsleepqueueチェーンロックで保護される。WITNESSフレームワークによりロック順序違反が検出される。

## パフォーマンス要件

- スレッド生成: フォーク処理より軽量（アドレス空間コピー不要）
- mutex取得（非競合時）: CASによるアトミック操作で数十ナノ秒
- adaptive spinning: コンテキスト切替コストの回避
- スレッド切替: マイクロ秒オーダー

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

- スレッドはプロセスの資格情報（ucred）を共有するため、同一プロセス内のスレッドは同一の権限を持つ
- WITNESSフレームワークによるデッドロック検出
- ASan/MSan（Address Sanitizer / Memory Sanitizer）のスレッド対応

## 備考

- FreeBSDの1:1スレッドモデルはlibthr（lib/libthr/）で実装され、POSIX pthreadsインタフェースを提供
- umtx（ユーザ空間mutex）サブシステムにより、可能な限りカーネル呼び出しを回避して同期を行う
- kern_thread.cの934行目にthread_exit()が定義されており、スレッド終了時のリソース解放処理の中核

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | proc.h | `sys/sys/proc.h` | struct threadの定義。td_state、td_tid、td_proc等の主要フィールド |
| 1-2 | mutex.h | `sys/sys/mutex.h` | struct mtxの定義。mutexの種別（MTX_DEF, MTX_SPIN） |
| 1-3 | condvar.h | `sys/sys/condvar.h` | struct cvの定義。条件変数のインタフェース |

**読解のコツ**: struct threadはstruct procのp_threadsリスト（TAILQ_HEAD）で管理される。td_stateの状態遷移（TDS_INACTIVE→TDS_CAN_RUN→TDS_RUNNING→TDS_INHIBITED）を追跡することがスレッド動作理解の鍵。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kern_thread.c | `sys/kern/kern_thread.c` | thread_exit()（934行目）、thread_single()（1222行目）が主要関数 |

**主要処理フロー**:
1. **934行目**: thread_exit()でランタイム計算、リソース解放、p_numthreadsデクリメント
2. **1222行目**: thread_single()で他スレッドを停止（SINGLE_EXIT/SINGLE_BOUNDARY等のモード）
3. **1407行目**: thread_suspend_check()でサスペンド要求の確認

#### Step 3: 同期プリミティブを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kern_mutex.c | `sys/kern/kern_mutex.c` | mutex実装（1371行）。adaptive spinningロジック |
| 3-2 | kern_condvar.c | `sys/kern/kern_condvar.c` | 条件変数実装（475行）。cv_wait/cv_signal/cv_broadcast |

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

```
thr_new() [システムコール]
    |
    +-- thread_create()
    |       +-- thread_alloc() [UMAゾーンから割当]
    |       +-- cpu_copy_thread() [CPUコンテキスト初期化]
    |       +-- sched_fork_thread() [スケジューラ登録]
    |
thread_exit()
    |
    +-- PROC_LOCK(p)
    +-- ruxagg(td) [リソース使用量集計]
    +-- sched_throw() [CPU放棄]

mtx_lock()
    |
    +-- __mtx_lock_flags()
            +-- _mtx_lock_spin_cookie() [スピンロック]
            +-- _mtx_lock_sleep() [スリープロック]
                    +-- turnstile_wait() [優先度継承付きブロック]

cv_wait()
    |
    +-- sleepq_add() [スリープキュー追加]
    +-- sleepq_wait() [ブロック]
```

### データフロー図

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

thr_param構造体 ───> thr_new() → thread_create() ──> 新スレッドTID
                                                       スレッド実行開始

thread実行完了 ────> thr_exit() → thread_exit() ───> スレッド破棄
                                                       リソース解放

mutex要求 ─────────> mtx_lock() ───────────────────> ロック取得/ブロック

cv_wait()呼出 ─────> sleepq_add() ─────────────────> 条件充足まで待機
cv_signal()呼出 ───> sleepq_signal() ──────────────> 待機スレッド起床
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kern_thread.c | `sys/kern/kern_thread.c` | ソース | スレッド生成・終了・サスペンド（1815行） |
| kern_mutex.c | `sys/kern/kern_mutex.c` | ソース | カーネルmutex実装（1371行） |
| kern_condvar.c | `sys/kern/kern_condvar.c` | ソース | カーネル条件変数実装（475行） |
| kern_sx.c | `sys/kern/kern_sx.c` | ソース | 共有/排他ロック実装 |
| kern_rwlock.c | `sys/kern/kern_rwlock.c` | ソース | リーダ・ライタロック実装 |
| subr_sleepqueue.c | `sys/kern/subr_sleepqueue.c` | ソース | スリープキュー管理 |
| subr_turnstile.c | `sys/kern/subr_turnstile.c` | ソース | ターンスタイル（優先度継承）管理 |
| subr_witness.c | `sys/kern/subr_witness.c` | ソース | WITNESSロック順序検証 |
| proc.h | `sys/sys/proc.h` | ヘッダ | struct thread定義 |
| mutex.h | `sys/sys/mutex.h` | ヘッダ | struct mtx定義 |
| condvar.h | `sys/sys/condvar.h` | ヘッダ | struct cv定義 |
