---
# System prepended metadata

title: GTID
tags: [ghOSt]

---

# GTID
ghOSt ではスレッドの識別子として tid を拡張した gtid を使用する。GTIDは Ghost Thread IDentifier の略。

Linux では tid の上限値は基本的に 22 bit 程度となっており（[参考](https://www.yunabe.jp/docs/maximum_number_of_threads.html)）、すでに終了したスレッドの tid は再利用されたりする。つまり、**同じtidをもつ異なるスレッドが存在しないことは、同時刻においては保証されているが、異なる時刻においては保証されていない**。
:::info
💡 tid の上限値は以下のコマンドで確認できる。
```
$ sudo cat /proc/sys/kernel/pid_max_max
4194304
```
:::
ghOSt ではこのような状況を好ましくないとして、同じ tid でも異なるスレッドかどうかを見分けることができるようにするために gtid を導入したのである。

gtid は 64 bit 整数値であり、以下のようなフィールドで構成されている。tid はスレッドの tid と同じ値になる。また seqnum はスレッドが生成されるたびにインクリメントされていく値である（後で詳しく見る）。

![image](https://hackmd.io/_uploads/HycTY-j4p.png)





最上位ビットを0としたのは、**gtidが負の場合に特別な意味をもたせるため**である。
ghost_run に渡されたときに特別な意味を持つ gtid が以下で定義されている（TODO: 詳しくは ghost_run の方で）。
```c
#define GHOST_NULL_GTID		(0)
#define GHOST_AGENT_GTID		(-1)
#define GHOST_IDLE_GTID		(-2)
```

# GTID の割り当て
gtid がスレッドに割り当てられる部分の処理を見ていく。

[ghost_alloc_gtid](https://github.com/google/ghost-kernel/blob/edd5f9490d82df24c16f90a62f7be05c6c389867/kernel/sched/ghost_core.c#L718C1-L735C2) 関数は task_struct を受け取り gtid を返す関数で copy_process から呼び出される。**gtid は ghOSt スレッドかどうかに関係なく全てのスレッドに割り当てられる識別子**なので、スレッドの sched_class に関係なく全てのケースで実行される。

```mermaid
flowchart LR
copy_process -->|always call| ghost_alloc_gtid
```

```c
int64_t ghost_alloc_gtid(struct task_struct *p)
{
	gtid_t gtid;
	uint64_t seqnum;
	
	// ① 初期値が0の静的ローカル変数（この値がインクリメントされていきseqnumとなる）
	static atomic64_t gtid_seqnum = ATOMIC64_INIT(0);

	do {
		// ② gtid_seqnumをインクリメントし、その値をseqnumとする
		// 　 seqnumが0になることは決してない
		seqnum = atomic64_add_return(1, &gtid_seqnum) &
				((1UL << GHOST_TID_SEQNUM_BITS) - 1);
	} while (!seqnum);
	
	// ③ p->pidとseqnumからgtidを作成する
	gtid = ((gtid_t)p->pid << GHOST_TID_SEQNUM_BITS) | seqnum;
	return gtid;
}
```
