# 機能設計書 125-スレッド作成

## 概要

本ドキュメントは、libuvが提供するスレッド作成機能 `uv_thread_create()` / `uv_thread_create_ex()` の設計仕様を記述する。OSネイティブスレッドを作成し、指定されたエントリー関数を実行するためのクロスプラットフォームAPIである。

### 本機能の処理概要

**業務上の目的・背景**：マルチスレッドプログラミングにおいて、スレッドの作成はプラットフォーム依存のAPIを使用する必要がある（POSIXではpthread_create、WindowsではCreateThread/_beginthreadex）。libuvは統一されたAPIを提供することで、クロスプラットフォームでのスレッド管理を容易にしている。拡張版の `uv_thread_create_ex()` はスタックサイズの指定にも対応している。

**機能の利用シーン**：独自のワーカースレッドを作成して並列処理を行う場合に使用される。libuvのスレッドプール（threadpool.c）内部でもこのAPIを使用してワーカースレッドを生成している。

**主要な処理内容**：
1. スタックサイズの決定（指定なしの場合はプラットフォームデフォルト）
2. スタックサイズのページアラインメント調整と最小スタックサイズの保証
3. pthread_attr_t/スレッド属性の設定（スタックサイズ指定時）
4. pthread_create() / _beginthreadex() によるOSスレッド作成
5. スレッドIDの返却

**関連システム・外部連携**：POSIX pthread API、Windows Thread API。

**権限による制御**：OS側のスレッド作成権限に依存する。リソースリミット（RLIMIT_NPROC等）により制限される場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | スレッド | 主機能 | uv_thread_create()/create_ex()によるスレッド作成のAPI定義 |
| 36 | スレッド | 主機能 | uv_thread_create()を使ったスレッド作成のサンプル解説 |

## 機能種別

リソース管理（OSスレッド作成）

## 入力仕様

### 入力パラメータ

#### uv_thread_create()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tid | uv_thread_t* | Yes | スレッドIDの格納先 | - |
| entry | uv_thread_cb | Yes | スレッドのエントリー関数 | - |
| arg | void* | No | エントリー関数に渡す引数 | - |

#### uv_thread_create_ex()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tid | uv_thread_t* | Yes | スレッドIDの格納先 | - |
| params | const uv_thread_options_t* | Yes | スレッドオプション（flags, stack_size） | - |
| entry | uv_thread_cb | Yes | スレッドのエントリー関数 | - |
| arg | void* | No | エントリー関数に渡す引数 | - |

### 入力データソース

ユーザーからの関数呼び出しパラメータ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 0:成功、負値:エラーコード |
| *tid | uv_thread_t | 作成されたスレッドのID |

### 出力先

tidポインタが指す領域にスレッドIDを格納。

## 処理フロー

### 処理シーケンス

```
1. uv_thread_create()の場合
   └─ UV_THREAD_NO_FLAGSでuv_thread_create_ex()を呼び出し
2. スタックサイズの決定
   └─ UV_THREAD_HAS_STACK_SIZEフラグがある場合: params->stack_sizeを使用
   └─ フラグなしの場合: 0（プラットフォームデフォルト）
3. スタックサイズの調整（Unix）
   └─ 0の場合: uv__thread_stack_size()でシステム設定から取得
   └─ 0以外: ページサイズでアラインメント、最小スタックサイズの保証
4. pthread属性設定（Unix、stack_size > 0の場合）
   └─ pthread_attr_init() + pthread_attr_setstacksize()
5. スレッド作成
   └─ Unix: pthread_create()
   └─ Windows: _beginthreadex()（SUSPENDED状態で作成後Resume）
6. リソースクリーンアップ
   └─ pthread_attr_destroy()（属性使用時）
```

### フローチャート

```mermaid
flowchart TD
    A[uv_thread_create_ex呼び出し] --> B{HAS_STACK_SIZEフラグ?}
    B -->|Yes| C[params->stack_sizeを使用]
    B -->|No| D[stack_size = 0]
    C --> E{stack_size == 0?}
    D --> E
    E -->|Yes| F[uv__thread_stack_size取得]
    E -->|No| G[ページアラインメント・最小サイズ保証]
    F --> H{stack_size > 0?}
    G --> H
    H -->|Yes| I[pthread_attr設定]
    H -->|No| J[attr = NULL]
    I --> K[pthread_create]
    J --> K
    K -->|成功| L[0返却]
    K -->|失敗| M[エラーコード返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-125-1 | 簡易版は拡張版のラッパー | uv_thread_create()はUV_THREAD_NO_FLAGSでuv_thread_create_ex()を呼ぶ | uv_thread_create()呼び出し時 |
| BR-125-2 | ページアラインメント | スタックサイズはページサイズの倍数に切り上げられる | stack_size > 0 |
| BR-125-3 | 最小スタックサイズ | PTHREAD_STACK_MINまたは8192バイトの大きい方が最小値 | Unix、stack_size指定時 |
| BR-125-4 | macOS/Linuxスタックサイズ | RLIMIT_STACKに基づくスタックサイズ調整が行われる | macOS/Linux |
| BR-125-5 | Windows一時停止作成 | WindowsではCREATE_SUSPENDED状態でスレッドを作成し、自身のハンドルを渡してからResumeする | Windows |

### 計算ロジック

スタックサイズ調整:
```
pagesize = getpagesize()
stack_size = (stack_size + pagesize - 1) & ~(pagesize - 1)  // 切り上げ
if (stack_size < min_stack_size) stack_size = min_stack_size
```

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EAGAIN | リソース不足 | スレッド作成リソース不足 | 後でリトライ |
| UV_ENOMEM | メモリ不足 | メモリ確保失敗（Windows） | メモリを確認 |
| UV_EINVAL | パラメータエラー | スタックサイズオーバーフロー（Windows） | スタックサイズを調整 |
| UV_EACCES | 権限不足 | スレッド作成権限なし | 権限を確認 |

### リトライ仕様

UV_EAGAIN発生時はリソースが解放された後にリトライ可能。

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

該当なし。

## パフォーマンス要件

スレッド作成はOS側のコストが発生する。頻繁なスレッド作成・破棄が必要な場合はスレッドプール（uv_queue_work()）の使用を推奨する。

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

- スレッド間でのデータ共有には適切な同期機構を使用する必要がある
- スタックオーバーフローを防ぐため、十分なスタックサイズを確保すること

## 備考

- Linuxのmuslはglibcより小さいデフォルトスタックサイズ（80KB vs 2-4MB）を持つため、uv__default_stack_size()でglibcに合わせた補正が行われる
- macOSではメインスレッド以外のスタックサイズがデフォルトで小さいため、RLIMIT_STACKに基づく調整が行われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1894行目**: `uv_thread_create()`の関数シグネチャ |
| 1-2 | uv.h | `include/uv.h` | **1897-1908行目**: `uv_thread_create_flags`列挙型と`uv_thread_options_s`構造体の定義 |
| 1-3 | uv.h | `include/uv.h` | **1910-1913行目**: `uv_thread_create_ex()`の関数シグネチャ |

**読解のコツ**: `uv_thread_t`はUnixではpthread_t、WindowsではHANDLE型である。`uv_thread_options_t`のflagsメンバでUV_THREAD_HAS_STACK_SIZEが設定されている場合のみstack_sizeが参照される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread.c | `src/unix/thread.c` | **126-130行目**: `uv_thread_create()`。UV_THREAD_NO_FLAGSでuv_thread_create_ex()を呼ぶシンプルなラッパー |
| 2-2 | thread.c | `src/unix/thread.c` | **138-187行目**: `uv_thread_create_ex()`。スタックサイズ決定、pthread属性設定、pthread_create()呼び出し |

**主要処理フロー**:
1. **155-156行目**: フラグに応じたスタックサイズの取得
2. **159-168行目**: スタックサイズのページアラインメントと最小値保証
3. **170-178行目**: pthread_attr設定
4. **180-181行目**: pthread_create()によるスレッド作成

#### Step 3: スタックサイズ決定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | thread.c | `src/unix/thread.c` | **72-81行目**: `uv__min_stack_size()`。最小スタックサイズの決定 |
| 3-2 | thread.c | `src/unix/thread.c` | **87-95行目**: `uv__default_stack_size()`。Linuxでのデフォルトスタックサイズ |
| 3-3 | thread.c | `src/unix/thread.c` | **101-123行目**: `uv__thread_stack_size()`。RLIMIT_STACKに基づくスタックサイズ調整 |

#### Step 4: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | thread.c | `src/win/thread.c` | **95-99行目**: `uv_thread_create()`。Unix版と同じラッパー |
| 4-2 | thread.c | `src/win/thread.c` | **110-171行目**: `uv_thread_create_ex()`。_beginthreadex()でSUSPENDED状態で作成し、selfハンドルを設定後にResumeThread() |

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

```
uv_thread_create() [src/unix/thread.c:126]
    │
    └── uv_thread_create_ex() [src/unix/thread.c:138]
            │
            +── uv__thread_stack_size() [src/unix/thread.c:101]
            │       +── getrlimit(RLIMIT_STACK)
            │       └── uv__default_stack_size()
            │
            +── uv__min_stack_size() [src/unix/thread.c:72]
            │
            +── pthread_attr_init() / pthread_attr_setstacksize()
            │
            +── pthread_create()
            │
            └── pthread_attr_destroy()
```

### データフロー図

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

entry (関数ptr) ──┐
arg (void*) ──────┤
params.flags ─────┤──▶ uv_thread_create_ex()
params.stack_size ┘       │
                     [スタックサイズ決定]
                          │
                     [ページアラインメント]
                          │
                     [pthread_create / _beginthreadex]
                          │
                     *tid ──▶ uv_thread_t（スレッドID）
                          │
                     新スレッド ──▶ entry(arg) 実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API定義（関数宣言、uv_thread_options_t構造体） |
| thread.c | `src/unix/thread.c` | ソース | Unix系プラットフォームの実装 |
| thread.c | `src/win/thread.c` | ソース | Windowsプラットフォームの実装 |
| threadpool.c | `src/threadpool.c` | ソース | 本APIの内部利用箇所（ワーカースレッド作成） |
