Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all 

名前
futex - 高速ユーザ空間ロック
書式
#include <linux/futex.h>
#include <sys/time.h>
int futex(int *uaddr, int op, int val, const struct timespec *timeout,
int *uaddr2, int val3);
説明
futex() システムコールは、 指定したアドレスの値が変更されるのをプログラムが待つ手段や 特定のアドレスに対
して待機中のプロセスを wake (起床) させる手段を提供する (プロセスが異なれば同じメモリに対するアドレスも同
じではないかもしれないが、 カーネルは異なる位置にマップされた同じメモリを futex() で使えるよう内部でマッ
プする)。 通常は、このシステムコールは futex(7) に書かれているように、 共有メモリ中のロックが競合する場
合の処理を実装するのに用いられる。
futex(7) の操作がユーザ空間で競合なく完了しなかった場合、 カーネルに仲裁させるためにシステムコールを呼ぶ
必要がある。 仲裁というのは、呼び出しプロセスを sleep (起床待ち) させたり、反対に 待ちプロセスを wake さ
せたりすることを意味する。
この関数を呼び出すプロセスは futex(7) に記述されているセマンティクスに忠実であることが要求される。 この
セマンティクスには移植不可能なアセンブリ命令を書くことが含まれる。 このことは言い換えると futex のユーザ
のほとんどは実際はライブラリの作者であり、 一般アプリケーションの開発者ではないということである。
uaddr 引き数は、カウンタを格納する、 アラインメントの揃った int 型変数を指している必要がある。 実行する操
作は op 引き数を介して、値 val とともに渡される。
現在のところ 5 つの操作が定義されている:
FUTEX_WAIT
この操作は futex アドレス uaddr に指定された値 val がまだ格納されているかどうかを不可分操作で検証
し、 sleep 状態で この futex アドレスに対して FUTEX_WAKE が実行されるのを待つ。 timeout 引き数が
NULL でない場合、その内容は待ち時間の最大値を表す (この停止時間はシステムクロックの粒度に切り上げ
られ、 カーネルのスケジューリング遅延により少しだけ長くなる可能性がある)。 NULL の場合、 呼び出し
は無限に停止する。 引き数 uaddr2 と val3 は無視される。
futex(7) に照らし合わせると、この呼び出しは カウントのデクリメントで負の値 (競合を表す) になった
場合に実行され、 別のプロセスがその futex を解放し FUTEX_WAKE の操作を実行するまで sleep する。
FUTEX_WAKE
この操作では指定した futex アドレスに対して待ち状態の (すなわち FUTEX_WAIT 中の) 最大 val 個のプロ
セスを wake させる。 引き数 timeout, uaddr2, val3 は無視される。
futex(4) に照らし合わせると、 この操作は カウントのインクリメントで待ちプロセスがあると判明し、
futex 値が 1 に設定された (利用可能であることを表す) 場合に実行される。
FUTEX_FD (Linux 2.6.25 以前)
非同期の wake に対応するため、この操作はファイルディスクリプタを futex に 関連づける。 別のプロセ
スが FUTEX_WAKE を実行すると、プロセスは val で渡されたシグナル番号のシグナルを受信する。 呼び出し
プロセスは使用後、返されたファイルディスクリプタを クローズしなければならない。 引き数 timeout,
uaddr2, val3 は無視される。
競合状態を防止するため、呼び出しプロセスは FUTEX_FD が返ったあと futex が up されたかどうかを確認
しなければならない。
FUTEX_FD はもともと競合が起きやすかったため、 Linux 2.6.26 以降で削除されている。
FUTEX_REQUEUE (Linux 2.5.70 以降)
この操作は、 FUTEX_WAKE が使われていて、かつ wake されている全てのプロセスが 他の futex を取得する
必要がある場合に、 「獣の群れの暴走 (thundering herd)」効果を避けるために導入された。 この呼び出し
は val 個のプロセスを wake し、アドレス uaddr2 で futex を待っている他の全てのプロセスを再度キュー
にいれる。 引き数 timeout と val3 は無視される。
FUTEX_CMP_REQUEUE (Linux 2.6.7 以降)
故意に FUTEX_REQUEUE を使う場合に競合が起こるため、 FUTEX_CMP_REQUEUE が導入された。これは
FUTEX_REQUEUE と似ているが、場所 uaddr に値 val3 がまだ保持されているかを最初にチェックする。 保持
されていない場合、操作はエラー EAGAIN で失敗する。引き数 timeout は無視される。
返り値
エラーの場合、全ての操作で -1 が返り、 errno がエラーの内容を示す値に設定される。成功時の返り値は操作に
よって異なり、以下のリストに書かれている通りである。
FUTEX_WAIT
そのプロセスが FUTEX_WAKE により wake された場合 0 を返す。発生する可能性があるエラーについては「
エラー」の節を参照。
FUTEX_WAKE
wake したプロセスの数を返す。
FUTEX_FD
futex に関連づけられた新たなファイルディスクリプタを返す。
FUTEX_REQUEUE
wake したプロセスの数を返す。
FUTEX_CMP_REQUEUE
wake したプロセスの数を返す。
エラー
EACCES futex メモリに読み込みアクセス権がなかった。
EAGAIN FUTEX_CMP_REQUEUE で、uaddr が指す値が期待値 val3 と異なる状況が検出された。 (これは競合を示してい
るかもしれない。この場合は安全な FUTEX_WAKE を使うこと。)
EFAULT ユーザ空間から timeout の情報を取得する際にエラーが発生した。
EINTR FUTEX_WAIT 操作がシグナル (signal(7) 参照) もしくは偽の wakeup により中断された。
EINVAL 無効な引き数。
ENFILE オープンされているファイルの総数がシステムの制限に達した。
ENOSYS op に無効な操作が指定された。
ETIMEDOUT
FUTEX_WAIT 操作でタイムアウトが発生した。
EWOULDBLOCK
op が FUTEX_WAIT で、その呼び出しにおいて uaddr が指す値が期待値 val と異なっていた。
バージョン
最初の futex 対応は Linux 2.5.7 で組み込まれたが、 上記のセマンティクスとは異なる。 4 つの引き数のここに
書かれているセマンティクスを持つ システムコールは、Linux 2.5.40 で導入された。 Linux 2.5.70 では 1 つの引
き数が追加された。 Linux 2.6.7 では 6 番目の引き数が追加された。 これは汚く、s390 アーキテクチャ上の特別
のものである。
準拠
このシステムコールは Linux 固有である。
注意
繰り返すが、裸の futex はエンドユーザが容易に使うことのできる概念として 意図されたものではない (glibc に
はこのシステムコールに対するラッパー関数はない)。 実装者は、アセンブリ言語に慣れており、以下に挙げる
futex ユーザ空間ライブラリの ソースを読み終えていることが要求される。
関連項目
restart_syscall(2), futex(7)
Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux (proceedings of the Ottawa Linux Symposium
2002), online at
http://kernel.org/doc/ols/2002/ols2002-pages-479-495.pdf
futex の使用例ライブラリ, futex-*.tar.bz2
ftp://ftp.nl.kernel.org/pub/linux/kernel/people/rusty/
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクトの説明とバグ報告
に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
Linux 2013-09-04 FUTEX(2)