Manpages

名 前

sem_wait, sem_timedwait, sem_trywait − セ マ フ ォ を ロ ッ ク す る

書 式

#include <semaphore.h>

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

−pthread と リ ン ク す る 。

glibc 向 け の 機 能 検 査 マ ク ロ の 要 件 (feature_test_macros(7) 参 照 ):

sem_timedwait(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

説 明

sem_wait() は sem が 指 す セ マ フ ォ の 値 を 1 減 ら す (ロ ッ ク す る )。 セ マ フ ォ の 値 が 0 よ り 大 き い 場 合 、 減 算 が 実 行 さ れ 、 関 数 は 直 ち に 復 帰 す る 。 セ マ フ ォ の 現 在 値 が 0 の 場 合 に は 、 減 算 を 実 行 で き る よ う に な る (つ ま り 、 セ マ フ ォ の 値 が 0 よ り 大 き な 値 に な る ) ま で 、 も し く は シ グ ナ ル ハ ン ド ラ ー に よ っ て 呼 び 出 し が 中 断 さ れ る ま で 、 関 数 呼 び 出 し は 停 止 (block) す る 。

sem_trywait() は sem_wait() と 同 じ だ が 、 セ マ フ ォ 値 の 減 算 を す ぐ に 実 行 で き な か っ た 場 合 に 、 停 止 (block) す る の で は な く エ ラ ー で 復 帰 す る (errnoEAGAIN が セ ッ ト さ れ る ) 点 が 異 な る 。

sem_timedwait() は sem_wait() と 同 じ だ が 、 セ マ フ ォ 値 の 減 算 を す ぐ に 実 行 で き な か っ た 場 合 に 関 数 呼 び 出 し が 停 止 す る 時 間 の 上 限 を abs_timeout で 指 定 す る 点 が 異 な る 。 abs_timeout 引 き 数 は 、 タ イ ム ア ウ ト 時 刻 を 指 定 す る 構 造 体 へ の ポ イ ン タ ー で あ る 。 こ の 構 造 体 に は 、 タ イ ム ア ウ ト 時 刻 を 時 刻 紀 元 (Epoch; 1970−01−01 00:00:00 +0000 (UTC)) か ら の 経 過 時 間 (秒 + ナ ノ 秒 ) で 指 定 す る 。 構 造 体 は 以 下 の よ う に 定 義 さ れ て い る :

struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds [0 .. 999999999] */ }; 関 数 呼 び 出 し 時 点 で す で に タ イ ム ア ウ ト に 指 定 し た 時 刻 が 過 ぎ て お り 、 か つ セ マ フ ォ を す ぐ に ロ ッ ク で き な か っ た 場 合 は 、 sem_timedwait() は タ イ ム ア ウ ト エ ラ ー (errnoETIMEDOUT が セ ッ ト さ れ る ) で 失 敗 す る 。 セ マ フ ォ 操 作 が す ぐ に 実 行 で き る と き は 、 abs_timeout が ど ん な 値 で あ っ て も sem_timedwait() が 失 敗 す る こ と は 決 し て な い 。 さ ら に い う と 、 こ の 場 合 に は abs_timeout の 正 当 性 の 検 査 は 行 わ れ な い 。

返 り 値

成 功 す る と 、 こ れ ら の 関 数 は 0 を 返 す 。 エ ラ ー の 場 合 、 セ マ フ ォ の 値 を 変 更 せ ず に 、 −1 を 返 し 、 errno に エ ラ ー を 示 す 値 を セ ッ ト す る 。

エ ラ ー

EINTR 呼 び 出 し は シ グ ナ ル ハ ン ド ラ ー に よ り 中 断 さ れ た 。

signal(7) 参 照 。

EINVAL

sem は 有 効 な セ マ フ ォ で は な い 。

sem_trywait() の 場 合 に は 、 上 記 に 加 え て 以 下 の エ ラ ー も 起 こ る 。

EAGAIN 停 止

(block) せ ず に ロ ッ ク 操 作 を 完 了 で き な か っ た (つ ま り 、 セ マ

フ ォ の 現 在 の 値 が 0 で あ っ た )。

sem_timedwait() の 場 合 、 以 下 の エ ラ ー も 起 こ る 。

EINVAL

abs_timeout.tv_nsecs の 値 が 0 未 満 、 も し く は 1,000,000,000 以 上 で あ る 。

ETIMEDOUT セ マ フ ォ の ロ ッ ク に 成 功 す る 前 に 時 間 切 れ と な っ た 。

属 性

マ ル チ ス レ ッ デ ィ ン グ (pthreads(7) 参 照 ) 関 数 sem_wait(), sem_trywait(), sem_timedwait() は ス レ ッ ド セ ー フ で あ る 。

準 拠

POSIX.1−2001.

注 意

シ グ ナ ル ハ ン ド ラ ー は 、 sigaction(2)SA_RESTART フ ラ グ を 使 用 し て い る か ど う か に 関 わ ら ず 、 こ れ ら の 関 数 の 呼 び 出 し が 停 止 し て い る 場 合 、 シ グ ナ ル ハ ン ド ラ ー に よ り 常 に 中 断 さ れ る 。

以 下 に 示 す (ち ょ っ と し た ) プ ロ グ ラ ム は 名 前 な し セ マ フ ォ の 操 作 を 行 う 。 プ ロ グ ラ ム は コ マ ン ド ラ イ ン 引 き 数 を 2 つ 取 る 。 最 初 の 引 き 数 に は 、 SIGALRM シ グ ナ ル を 生 成 す る た め の ア ラ ー ム タ イ マ ー の 設 定 に 使 わ れ る 値 を 秒 単 位 で 指 定 す る 。 こ の シ グ ナ ル ハ ン ド ラ ー は 、 main() 内 で sem_timedwait() を 使 っ て 待 っ て い る セ マ フ ォ を 、 sem_post(3) を 使 っ て 加 算 す る 。 2番 目 の 引 き 数 に は 、 sem_timedwait() に 渡 す タ イ ム ア ウ ト ま で の 時 間 を 秒 単 位 で 指 定 す る 。

$ ./a.out 2 3
About to call sem_timedwait()
sem_post() from handler
sem_timedwait() succeeded
$ ./a.out 2 1
About to call sem_timedwait()
sem_timedwait() timed out プ ロ グ ラ ム の ソ ー ス

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>

sem_t sem;

#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)

static void
handler(int sig)
{
write(STDOUT_FILENO, "sem_post() from handler\n", 24);
if (sem_post(&sem) == −1) {
write(STDERR_FILENO, "sem_post() failed\n", 18);
_exit(EXIT_FAILURE); } }

int
main(int argc, char *argv[])
{
struct sigaction sa;
struct timespec ts;
int s;

if (argc != 3) {
fprintf(stderr, "Usage: %s <alarm−secs> <wait−secs>\n",
argv[0]);
exit(EXIT_FAILURE); }

if (sem_init(&sem, 0, 0) == −1)
handle_error("sem_init");

/* Establish SIGALRM handler; set alarm timer using argv[1] */

sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGALRM, &sa, NULL) == −1)
handle_error("sigaction");

alarm(atoi(argv[1]));

/* Calculate relative interval as current time plus
number of seconds given argv[2] */

if (clock_gettime(CLOCK_REALTIME, &ts) == −1)
handle_error("clock_gettime");

ts.tv_sec += atoi(argv[2]);

printf("main() about to call sem_timedwait()\n");
while ((s = sem_timedwait(&sem, &ts)) == −1 && errno == EINTR)
continue; /* Restart if interrupted by handler */

/* Check what happened */

if (s == −1) {
if (errno == ETIMEDOUT)
printf("sem_timedwait() timed out\n");
else
perror("sem_timedwait"); }
else
printf("sem_timedwait() succeeded\n");

exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE); }

関 連 項 目

clock_gettime(2), sem_getvalue(3), sem_post(3), sem_overview(7), time(7)

こ の 文 書 に つ い て

こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。