Submit Search
Linuxのsemaphoreとmutexを見る
Download as PPTX, PDF
1 like
3,187 views
W
wata2ki
glibcのLinuxのsemaphoreとmutexの実装を調べた内容の発表
Engineering
Read more
1 of 21
Download now
Downloaded 14 times
1
2
3
4
5
6
Most read
7
8
9
10
11
12
Most read
13
14
15
16
17
18
19
20
Most read
21
More Related Content
PPTX
本当は恐ろしい分散システムの話
Kumazaki Hiroki
PPTX
Slurmのジョブスケジューリングと実装
Ryuichi Sakamoto
PDF
/etc/network/interfaces について
Kazuhiro Nishiyama
PDF
Linux女子部 iptables復習編
Etsuji Nakai
PDF
大規模サービスを支えるネットワークインフラの全貌
LINE Corporation
PDF
コンテナの作り方「Dockerは裏方で何をしているのか?」
Masahito Zembutsu
PDF
Ethernetの受信処理
Takuya ASADA
PPTX
分散システムについて語らせてくれ
Kumazaki Hiroki
本当は恐ろしい分散システムの話
Kumazaki Hiroki
Slurmのジョブスケジューリングと実装
Ryuichi Sakamoto
/etc/network/interfaces について
Kazuhiro Nishiyama
Linux女子部 iptables復習編
Etsuji Nakai
大規模サービスを支えるネットワークインフラの全貌
LINE Corporation
コンテナの作り方「Dockerは裏方で何をしているのか?」
Masahito Zembutsu
Ethernetの受信処理
Takuya ASADA
分散システムについて語らせてくれ
Kumazaki Hiroki
What's hot
(20)
PPT
Glibc malloc internal
Motohiro KOSAKI
PDF
条件分岐とcmovとmaxps
MITSUNARI Shigeo
PPTX
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
NTT DATA Technology & Innovation
PDF
PostgreSQLの運用・監視にまつわるエトセトラ
NTT DATA OSS Professional Services
PDF
PG-REXで学ぶPacemaker運用の実例
kazuhcurry
PDF
Java仮想マシンの実装技術
Kiyokuni Kawachiya
PDF
大規模DCのネットワークデザイン
Masayuki Kobayashi
PDF
Vacuum徹底解説
Masahiko Sawada
PDF
雑なMySQLパフォーマンスチューニング
yoku0825
PPTX
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
SEGADevTech
PPTX
コンテナネットワーキング(CNI)最前線
Motonori Shindo
PDF
Gitの便利ワザ
ktateish
PDF
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
PPTX
ConfD で Linux にNetconfを喋らせてみた
Akira Iwamoto
PDF
PHPからgoへの移行で分かったこと
gree_tech
PDF
ML2/OVN アーキテクチャ概観
Yamato Tanaka
PPT
Raft
Preferred Networks
PDF
Scapyで作る・解析するパケット
Takaaki Hoyo
PPTX
VSCodeで作るPostgreSQL開発環境(第25回 PostgreSQLアンカンファレンス@オンライン 発表資料)
NTT DATA Technology & Innovation
PPTX
AVX-512(フォーマット)詳解
MITSUNARI Shigeo
Glibc malloc internal
Motohiro KOSAKI
条件分岐とcmovとmaxps
MITSUNARI Shigeo
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
NTT DATA Technology & Innovation
PostgreSQLの運用・監視にまつわるエトセトラ
NTT DATA OSS Professional Services
PG-REXで学ぶPacemaker運用の実例
kazuhcurry
Java仮想マシンの実装技術
Kiyokuni Kawachiya
大規模DCのネットワークデザイン
Masayuki Kobayashi
Vacuum徹底解説
Masahiko Sawada
雑なMySQLパフォーマンスチューニング
yoku0825
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
SEGADevTech
コンテナネットワーキング(CNI)最前線
Motonori Shindo
Gitの便利ワザ
ktateish
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
ConfD で Linux にNetconfを喋らせてみた
Akira Iwamoto
PHPからgoへの移行で分かったこと
gree_tech
ML2/OVN アーキテクチャ概観
Yamato Tanaka
Raft
Preferred Networks
Scapyで作る・解析するパケット
Takaaki Hoyo
VSCodeで作るPostgreSQL開発環境(第25回 PostgreSQLアンカンファレンス@オンライン 発表資料)
NTT DATA Technology & Innovation
AVX-512(フォーマット)詳解
MITSUNARI Shigeo
Ad
More from wata2ki
(11)
PPTX
鹿児島らぐハイブリッド開催への道
wata2ki
PPTX
Linuxの2038年問題を調べてみた
wata2ki
PDF
YoctoでLTSディストリを作るには
wata2ki
PDF
YoctoLTSについて調べてみた
wata2ki
PPTX
しょしんしゃのためのhello world
wata2ki
PPTX
ARM LinuxのMMUはわかりにくい
wata2ki
PPTX
Fireduck
wata2ki
PPTX
パッチを投稿してみた話
wata2ki
PPTX
Linux kernelのbspとupstream
wata2ki
PPTX
Yocto bspを作ってみた
wata2ki
PPTX
YoctoをつかったDistroの作り方とハマり方
wata2ki
鹿児島らぐハイブリッド開催への道
wata2ki
Linuxの2038年問題を調べてみた
wata2ki
YoctoでLTSディストリを作るには
wata2ki
YoctoLTSについて調べてみた
wata2ki
しょしんしゃのためのhello world
wata2ki
ARM LinuxのMMUはわかりにくい
wata2ki
Fireduck
wata2ki
パッチを投稿してみた話
wata2ki
Linux kernelのbspとupstream
wata2ki
Yocto bspを作ってみた
wata2ki
YoctoをつかったDistroの作り方とハマり方
wata2ki
Ad
Linuxのsemaphoreとmutexを見る
1.
Linuxのsemaphoreとmutexを見る glibc版
2.
目次 • semaphoreとmutexとは? • 計算機科学におけるsemaphore •
計算機科学におけるmutex • semaphoreとmutexの実装方法 • semaphoreの実装例 • mutexの実装例 • Linuxの場合 • LinuxのPOSIX semaphoreとmutex • LinuxのPOSIX semaphoreの実装を見る • Linuxのsemaphoreとmutexのまとめ
3.
semaphoreとmutexとは? • semaphoreとmutexとは? • 資源の同期・排他を行うための仕組みで、主にsemaphoreは同期のために、 mutexは排他のために使用する •
計算機科学の分野では昔から存在する考え方で、一般的なOS(Operating System)であれば用意されている • 初期のFreeRTOSやuITRONなどsemaphoreのみでmutexが用意されていないも のもある
4.
0 計算機科学における semaphore 1semaphore Thread 2 run
run (got semaphore)Thread 1 0 run wait() wait() →block stop (wait semaphore) signal() run 1 unblock signal() run (got semaphore) 1 02semaphore Thread 2 Thread 3 run run (got semaphore)Thread 1 1 0 run run (got semaphore) run wait() wait() wait() →block stop (wait semaphore) signal() run 1 unblock signal() run (got semaphore) run 1 semaphoreの排他用途での使用(バイナリセマフォ) run Thread 1が、semaphore資源 を獲得 Thread 2が、semaphore資源を 獲得しようとするが、資源が ないためblock Thread 1が、semaphore資源を 開放したため、獲得待ちに なっていたThread2がunblock Thread 2が、semaphore資源を 開放したため、資源が1に戻る semaphoreの排他用途での使用(資源数2の場合) Thread 1が、semaphore 資源を獲得 Thread 3が、semaphore 資源を獲得しようとす るが、資源がないため block Thread 1が、semaphore 資源を開放したため、 獲得待ちになっていた Thread3がunblock Thread 2が、semaphore資源を 開放したため、資源が1に戻る Thread 1が、semaphore 資源を獲得
5.
0 計算機科学における semaphore semaphore Thread 2 runThread
1 0 enqueue() wait() →block stop (wait semaphore) signal() 1 unblock signal() 1 semaphoreの同期用途での使用 queue(データ構造)と組み合わせて、スレッド間通信を行う run queue 0 wait() 1 0 dequeue() enqueue() 1 stop (wait semaphore) 0 unblock dequeue() run 0 Thread 1が、queueに Thread 2に渡したい データを格納 Thread 1が、semaphore 資源を与えることで、 Thread 2がunblock Thread 2は、queueか らデータを一個取得 受け取ったデータの処理が完了したThread 2は、 semaphoreの資源待ちに入り再度Thread 1から データが送られるのを待つ
6.
locked (Thread 2) 計算機科学における
mutex unlockmutex Thread 2 run run (mutex locked)Thread 1 locked (Thread 1) run lock() lock() →block stop (wait unlock) unlock() run unblock unlock() run (mutex locked) unlock mutexの排他用途での使用 run Thread 1が、mutexをlockし 所有権を得る Thread 2が、mutexをlockしよ うとするが、Thread 1にlockさ れているためblock Thread 1が、mutexをunlockし たため、lock待ちしていた Thread2が所有権を得てunblock Thread 2が、mutexをunlockし たため、mutexがunlock状態に 戻る mutexの特徴 mutex Thread 2 run run (got semaphore)Thread 1 locked (Thread 1) run lock() unlock() →error unlock() run unlock Thread 1が、mutexをlockし 所有権を得る Thread 2が、mutexをunlockしようとす るが、mutexの所有権を持っているの はThread 1なので、エラーになる。 Thread 1はmutexを所有してい るためunlockに成功する →mutexはsemaphoreとは異なり、同期用途には使えない
7.
semaphoreとmutexとは? • お題のsemaphoreとmutexとは? • 資源の同期・排他を行うための仕組みで、主にsemaphoreは同期のために、 mutexは排他のために使用する •
計算機科学の分野では昔から存在する考え方で、一般的なOS(Operating System)であれば用意されている • 初期のFreeRTOSやuITRONではsemaphoreのみでmutexが用意されていないも のもある • semaphoreとmutexの違いは、所有権の概念の有無 • 所有権の概念のないsemaphoreは排他と同期の両方に使うことができる • 所有権の概念のあるmutexは排他用途にしか使えない • 所有権の概念があるため、優先度継承プロトコルや再帰ロックのようなmutex の特徴となる機能が提供される • 優先度継承の概念はRTOS(Real-Time OS)では重要な機能だが、後半の内容 が複雑化するため省略する。 • 所有権の概念が原則としてないが、Linuxなどで使われるPOSIX仕様のmutexは、 初期化時の設定で所有権の概念を持たないmutexを作ることができる。
8.
目次 • semaphoreとmutexとは? • 計算機科学におけるsemaphore •
計算機科学におけるmutex • semaphoreとmutexの実装方法 • semaphoreの実装例 • mutexの実装例 • Linuxの場合 • LinuxのPOSIX semaphoreとmutex • LinuxのPOSIX semaphoreの実装を見る • Linuxのsemaphoreとmutexのまとめ
9.
semaphoreの実装例 Th.2 Sem Q. Res. 1 semaphoreはカウンタとqueueで実装される 初期状態
Th.1がwait() Sem Q. Res. 0 Th.3がwait() Sem Q. Res. 0 Th.2がwait() Sem Q. Res. 0 Th.2 Th.3 semaphoreは資源数と、 blockしたスレッドを覚える ためのqueueを持つ。 semaphore1個につき、この データが1個作られる。 資源が1の状態でwait()され たので、資源数をディクリ メントする。 資源が0の状態でwait()され たので、Th.2を待ち状態に して、semaphoreの資源待 ちqueueにつなぐ。 資源が0の状態でさらに wait()されたので、Th.3を待 ち状態にして、semaphore の資源待ちqueueにつなぐ。 Th.1がsignal() ① Sem Q. Res. 1 Th.2 Th.3 Th.1がsignal()したことで、 資源が1になる。 Th.1がsignal() ② Sem Q. Res. 0 Th.3 資源が1になったため、 semaphoreの資源待ちqueue にいるスレッドをunblockし、 資源数をディクリメントす る。 RTOSでは、カーネルのシステムコール内で これらの操作が行われる。 LinuxではRTOSとは違った実装になっており、 その解説が後半の内容です。
10.
mutexの実装例 Th.2 Mutex Q. (None) mutexもsemaphoreと同様にqueueを持ち、カウンタの代わりに所有者を格納する形で実装される 初期状態 Th.1がlock() Mutex
Q. (Th. 1) Th.3がlock() Mutex Q. (Th. 1) Th.2がlock() Mutex Q. (Th. 1) Th.2 Th.3 mutexはblockしたスレッド を覚えるためのqueueと、 所有者情報を持つ。 mutex 1個につき、このデー タが1個作られる。 所有者がいない(None) 状態 でlock()されたので、Th. 1 を所有者にする。 資源が0の状態でwait()され たので、Th.2を待ち状態に して、semaphoreの資源待 ちqueueにつなぐ。 資源が0の状態でさらに wait()されたので、Th.3を待 ち状態にして、semaphore の資源待ちqueueにつなぐ。 Th.1がunlock() ① Mutex Q. (None) Th.2 Th.3 Th.1がsignal()したことで、 資源が1になる。 Th.1がunlock() ② Sem Q. (Th. 2) Th.3 資源が1になったため、 semaphoreの資源待ちqueue にいるスレッドをunblockし、 資源数をディクリメントす る。 資源がある/ないが所有者がいる/いないに変 わる点が、semaphoreとmutexの違い。 この違いが、優先度継承*1や再帰的ロック*2 を可能にしている。 *1. ロックまちをしているスレッドのうち最も高い優先度 に、mutexをロックしているスレッドを昇格させる *2. 同じmutexを複数回ロックでき、ロックした回数unlock するまで所有権を維持する
11.
目次 • semaphoreとmutexとは? • 計算機科学におけるsemaphore •
計算機科学におけるmutex • semaphoreとmutexの実装方法 • semaphoreの実装例 • mutexの実装例 • Linuxの場合 • LinuxのPOSIX semaphoreとmutex • LinuxのPOSIX semaphoreの実装を見る • Linuxのsemaphoreとmutexのまとめ
12.
Linuxのsemaphoreとmutex • LinuxのsemaphoreとmutexはNPTLによって提供されている • NPTL(Native
POSIX Thread Library)は、RedHatによって開発されたライブ ラリで、glibcでPOSIXスレッドの機能を提供している • POSIXスレッドのAPIは先頭にpthreadがついている • POSIX semaphoreはPOSIXスレッドには含まれないが、NPTLに含まれている • Linuxにはmutexは一種類しか存在しないが、semaphoreは2種類ある • System V semaphore • 古くからあるsemaphoreで、プロセス間での排他・同期向けの作りになって おり、スレッド間の排他・同期には向いていない • UNIXの世界では、スレッドの考え方は後から付け足された概念なので、他に も同じようなつくりの物が結構ある • POSIX semaphore • 機能をシンプルにしたsemaphoreで、プロセス間での利用向け(名前付き) と、プロセス内での利用向け(名前なし)の両方が存在する • 今日中身を解説するのはこちら
13.
Linuxのsemaphore実装を見る • POSIX semaphoreは、sem_initで作成する int __new_sem_init
(sem_t *sem, int pshared, unsigned int value) { /* Parameter sanity check. */ if (__glibc_unlikely (value > SEM_VALUE_MAX)) { __set_errno (EINVAL); return -1; } pshared = pshared != 0 ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE; int err = futex_supports_pshared (pshared); if (err != 0) { __set_errno (err); return -1; } /* Map to the internal type. */ struct new_sem *isem = (struct new_sem *) sem; /* Use the values the caller provided. */ #if __HAVE_64B_ATOMICS isem->data = value; #else isem->value = value << SEM_VALUE_SHIFT; /* pad is used as a mutex on pre-v9 sparc and ignored otherwise. */ isem->pad = 0; isem->nwaiters = 0; #endif isem->private = (pshared == PTHREAD_PROCESS_PRIVATE ? FUTEX_PRIVATE : FUTEX_SHARED); return 0; } Semaphoreの上限値を超えた値を初 期値にしていたらエラーにする Semaphoreをプロセス間共有する指 定がされていた場合に、futex(ここ大 事)がプロセス間共有をサポートして いるかどうかをチェックする Semaphore構造体のメンバを初期化
14.
Linuxのsemaphore実装を見る • POSIX semaphoreは、sem_initで作成する int __new_sem_init
(sem_t *sem, int pshared, unsigned int value) { /* Parameter sanity check. */ if (__glibc_unlikely (value > SEM_VALUE_MAX)) { __set_errno (EINVAL); return -1; } pshared = pshared != 0 ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE; int err = futex_supports_pshared (pshared); if (err != 0) { __set_errno (err); return -1; } /* Map to the internal type. */ struct new_sem *isem = (struct new_sem *) sem; /* Use the values the caller provided. */ #if __HAVE_64B_ATOMICS isem->data = value; #else isem->value = value << SEM_VALUE_SHIFT; /* pad is used as a mutex on pre-v9 sparc and ignored otherwise. */ isem->pad = 0; isem->nwaiters = 0; #endif isem->private = (pshared == PTHREAD_PROCESS_PRIVATE ? FUTEX_PRIVATE : FUTEX_SHARED); return 0; } Semaphoreの上限値を超えた値を初 期値にしていたらエラーにする Semaphoreをプロセス間共有する指 定がされていた場合に、futex(ここ大 事)がプロセス間共有をサポートして いるかどうかをチェックする Semaphore構造体のメンバを初期化 Semaphoreの作成時に、カーネルの資源 を作成していない
15.
static int __new_sem_wait_fast (struct
new_sem *sem, int definitive_result) { #if __HAVE_64B_ATOMICS uint64_t d = atomic_load_relaxed (&sem->data); do { if ((d & SEM_VALUE_MASK) == 0) break; if (atomic_compare_exchange_weak_acquire (&sem->data, &d, d - 1)) return 0; } while (definitive_result); return -1; #else 省略 #endif } Linuxのsemaphore実装を見る • Semaphore資源の獲得は、sem_waitで行う int __new_sem_wait (sem_t *sem) { __pthread_testcancel (); if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) return 0; else return __new_sem_wait_slow((struct new_sem *) sem, NULL); } とりあえず、fastパスでOKになったら、 確保成功を返す Semaphore構造体から、現在のセマ フォの資源数を取得(アトミック読み 込み) →メモリから値をコピーしているだけ 資源数0の場合は、エラーを返す →slowパスに流す アトミックダウンカウントを行い、資 源数を1減らせたら確保成功 →だめだったら(競合したら)slowパス に流す
16.
static int __new_sem_wait_fast (struct
new_sem *sem, int definitive_result) { #if __HAVE_64B_ATOMICS uint64_t d = atomic_load_relaxed (&sem->data); do { if ((d & SEM_VALUE_MASK) == 0) break; if (atomic_compare_exchange_weak_acquire (&sem->data, &d, d - 1)) return 0; } while (definitive_result); return -1; #else 省略 #endif } Linuxのsemaphore実装を見る • Semaphore資源の獲得は、sem_waitで行う int __new_sem_wait (sem_t *sem) { __pthread_testcancel (); if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) return 0; else return __new_sem_wait_slow((struct new_sem *) sem, NULL); } とりあえず、fastパスでOKになったら、 確保成功を返す Semaphore構造体から、現在のセマ フォの資源数を取得(アトミック読み 込み) →メモリから値をコピーしているだけ 資源数0の場合は、エラーを返す →slowパスに流す アトミックダウンカウントを行い、資 源数を1減らせたら確保成功 →だめだったら(競合したら)slowパス に流す Semaphoreの資源を確保するだけであれ ば、ユーザ空間で変数ディクリメントす るだけで処理が終わる
17.
static int __attribute__
((noinline)) __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime) { int err = 0; uint64_t d = atomic_fetch_add_relaxed (&sem->data, (uint64_t) 1 << SEM_NWAITERS_SHIFT); for (;;) { if ((d & SEM_VALUE_MASK) == 0) { err = do_futex_wait (sem, abstime); if (err == ETIMEDOUT || err == EINTR) { __set_errno (err); err = -1; atomic_fetch_add_relaxed (&sem->data, -((uint64_t) 1 << SEM_NWAITERS_SHIFT)); break; } d = atomic_load_relaxed (&sem->data); } else { 省略 } } return err; } Linuxのsemaphore実装を見る • Semaphore資源の獲得は、sem_waitで行う もう一回セマフォの資源をアトミック 読み込みで取得する 本当に資源が存在しないことを確認し て、futex待ちに入る。 もし資源があった場合は、fastパスと 同じアトミックディクリメントを行う シグナルに割り込まれた場合やタイム アウトした場合は、一度sem_waitをエ ラーで返す futex待ちから出た後、アトミック読み 込みを行い、再度資源確保を試みる。 資源数を1減らせたら確保成功 →だめだったら、またfutex待ちに入る 注. スペースの都合上、32bit向け実装やsemaphoreの動きと直接関係ない行は省略しています
18.
int __new_sem_post (sem_t *sem) { struct
new_sem *isem = (struct new_sem *) sem; int private = isem->private; uint64_t d = atomic_load_relaxed (&isem->data); do { if ((d & SEM_VALUE_MASK) == SEM_VALUE_MAX) { __set_errno (EOVERFLOW); return -1; } } while (!atomic_compare_exchange_weak_release (&isem->data, &d, d + 1)); if ((d >> SEM_NWAITERS_SHIFT) > 0) futex_wake (((unsigned int *) &isem->data) + SEM_VALUE_OFFSET, 1, private); return 0; } Linuxのsemaphore実装を見る • Semaphore資源の開放は、sem_postで行う セマフォの資源をアトミック読み込み で取得する 資源数が限界値だったらエラーにする 資源数をアトミックインクリメント 資源数を0から1にした場合は、誰かが 待っているので、futexに希少要求をか ける 注. スペースの都合上、32bit向け実装やsemaphoreの動きと直接関係ない行は省略しています
19.
Linuxのsemaphore実装を見る • 途中で出てきたfutexとは? • NPTLの開発と同時に作られたシステムコールで、アトミックな休眠と起 床を実現するための仕組み •
パラメタuadderの部分に、資源数を格納しているメモリのアドレス渡し ている • 実は、カーネル内部ではuadderをキーにしてwaitキューを作るようになっ ており、誰かが起床待ちになった時に作成、全員が起床されると破棄さ れる • つまり、競合状態にあるときのみ、カーネル内部の資源が作られる int futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3);
20.
Linuxのsemaphoreとmutexのまとめ • Linuxのsemaphoreの実装とは? • アトミックインクリメント・ディクリメントによってほとんどの操作が 終わってしまう •
競合が発生しない限り、カウントアップorカウントダウンしかしないので、 速い • 競合が発生したときのみ、futexを使った待ち制御を行う • 競合が発生すると、システムコールを使うので遅くなる • RTOSの場合は? • RTOSのsemaphoreはカーネルリソースで、資源数の管理も休眠・起床制 御もすべてカーネルが行う • 広域ロックをとって、カーネル内のキューを探索・変更するため、数が 少ないと性能がよくなる LinuxとRTOSでは、semaphoreに対する考え方が全く異なる
21.
Linuxのsemaphoreとmutexのまとめ • これまでの流れで代替予想できると思いますが • Linuxのsemaphoreとmutexの実装は、ほとんど同じ •
semaphoreはアトミックカウンタによる制御 • mutexは、アトミックカウンタの代わりにpid(tid)を格納 • 結局のところ、開放状態か否かがわかればやること(futexで寝る・起き る)は同じ • futexを作ると、カーネルリソースを使うが、競合しないと作らない RTOSの常識 semaphoreやmutexは極力減らして、リソース削減や動作効率をよくする Linuxの常識 ユーザ空間のsemaphoreやmutexは作りまくって競合をなくし、 リソース削減や動作効率をよくする
Download