/** * Copyright (C) NAKAMURA Minoru * * gcc -g -Wall -O0 -lrt timer_max_limit.c */ #include #include #include #include #include #include #include #include #include volatile int acc_sigusr1; void handler(int signum, siginfo_t* info, void * p) { acc_sigusr1++; } int main(int argc, char** argv) { // タイマーに使うシグナル SIGUSR1 は通常ブロックするよ sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGUSR1); sigprocmask(SIG_BLOCK, &sigset, NULL); // SIGUSR1 ハンドラの設定 struct sigaction action; action.sa_flags = SA_SIGINFO; sigfillset(&action.sa_mask); action.sa_sigaction = handler; sigaction(SIGUSR1, &action, NULL); // イベント設定 struct sigevent event; // event.sigev_notify = SIGEV_NONE; event.sigev_notify = SIGEV_SIGNAL; event.sigev_signo = SIGUSR1; event.sigev_value.sival_int = 0xCAFEBABE; timer_t timer; if (timer_create(CLOCK_REALTIME, &event, &timer)) { perror("timer_create"); abort(); } struct itimerspec spec, old_spec; spec.it_value.tv_sec = LONG_MAX; spec.it_value.tv_nsec = 0; spec.it_interval.tv_sec = 0; spec.it_interval.tv_nsec = 0; while(spec.it_value.tv_sec != 0) { if (timer_settime(timer, 0, &spec, NULL)) { if (errno == EINVAL) { spec.it_value.tv_sec /= 2; continue; } perror("timer_settime"); abort(); } if (timer_gettime(timer, &old_spec)) { perror("timer_gettime"); abort(); } acc_sigusr1 = 0; // SIGUSR1 を解除する。 sigprocmask(SIG_UNBLOCK, &sigset, NULL); sched_yield(); // タイマーが来るかも知れないのを少し待つよ。 sigprocmask(SIG_BLOCK, &sigset, NULL); printf("settime: %ld.%09ld\ngettime: %ld.%09ld%s\n\n", spec.it_value.tv_sec, spec.it_value.tv_nsec, old_spec.it_value.tv_sec, old_spec.it_value.tv_nsec, acc_sigusr1 ? " TIMER EXPIRED" : ""); // タイマー解除 struct itimerspec spec_clear; spec_clear.it_value.tv_sec = 0; spec_clear.it_value.tv_nsec = 0; spec_clear.it_interval.tv_sec = 0; spec_clear.it_interval.tv_nsec = 0; timer_settime(timer, 0, &spec_clear, NULL); // 余分なシグナルを破棄 sigprocmask(SIG_UNBLOCK, &sigset, NULL); sigprocmask(SIG_BLOCK, &sigset, NULL); spec.it_value.tv_sec /= 2; } return 0; }