int main (void) { struct timespec ts; timer_t timer_sig, timer_thr1, timer_thr2; int retval; struct sigevent sigev1 = { .sigev_notify = SIGEV_SIGNAL, .sigev_signo = ZSIGALRM }; struct sigevent sigev2; struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; struct itimerspec old; retval = clock_gettime (CLOCK_REALTIME, &ts); sigev2.sigev_notify = SIGEV_THREAD; sigev2.sigev_notify_function = notify_func; sigev2.sigev_notify_attributes = NULL; setvbuf (stdout, 0, _IOLBF, 0); printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n", retval, ts.tv_sec, ts.tv_nsec); retval = clock_getres (CLOCK_REALTIME, &ts); printf ("clock_getres returned %d, timespec = { %ld, %ld }\n", retval, ts.tv_sec, ts.tv_nsec); timer_create (CLOCK_REALTIME, &sigev1, &timer_sig); timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1); timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2); timer_settime (timer_thr1, 0, &itimer2, &old); timer_settime (timer_thr2, 0, &itimer3, &old); signal (ZSIGALRM, signal_func); timer_settime (timer_sig, 0, &itimer1, &old); timer_delete (-1); intr_sleep (3); timer_delete (timer_sig); timer_delete (timer_thr1); intr_sleep (3); timer_delete (timer_thr2); return 0; }
static void fin_sleep(int secs) { struct timespec req = {.tv_sec = secs }; struct timespec rem = {.tv_sec = -1, .tv_nsec = -1 }; test_assert(0 == nanosleep(&req, &rem)); test_assert(-1 == rem.tv_sec && -1 == rem.tv_nsec); } static void sighandler(__attribute__((unused)) int sig) { test_assert(sys_gettid() == reader_tid); ++reader_caught_signal; atomic_puts("r: in sighandler level 1 ..."); intr_sleep(2); } static void sighandler2(__attribute__((unused)) int sig) { test_assert(sys_gettid() == reader_tid); ++reader_caught_signal; atomic_puts("r: in sighandler level 2 ..."); fin_sleep(1); } static void* reader_thread(__attribute__((unused)) void* dontcare) { struct sigaction act; int flags = 0; reader_tid = sys_gettid(); act.sa_handler = sighandler; sigemptyset(&act.sa_mask); act.sa_flags = flags; sigaction(SIGUSR1, &act, NULL); act.sa_handler = sighandler2; sigemptyset(&act.sa_mask); act.sa_flags = flags; sigaction(SIGUSR2, &act, NULL); pthread_barrier_wait(&barrier); atomic_puts("r: blocking on sleep, awaiting signal ..."); intr_sleep(3); return NULL; } int main(void) { struct timeval ts; /* (Kick on the syscallbuf if it's enabled.) */ gettimeofday(&ts, NULL); pthread_barrier_init(&barrier, NULL, 2); pthread_create(&reader, NULL, reader_thread, NULL); pthread_barrier_wait(&barrier); /* Force a blocked read() that's interrupted by a SIGUSR1, * which then itself blocks on read() and succeeds. */ atomic_puts("M: sleeping ..."); usleep(500000); atomic_puts("M: killing reader ..."); pthread_kill(reader, SIGUSR1); atomic_puts("M: (quick nap)"); usleep(100000); atomic_puts("M: killing reader again ..."); pthread_kill(reader, SIGUSR2); atomic_puts("M: ... done"); pthread_join(reader, NULL); atomic_puts("EXIT-SUCCESS"); return 0; }
int main (void) { struct timespec ts; timer_t timer_sig, timer_thr1, timer_thr2; int retval; struct sigevent sigev1 = { .sigev_notify = SIGEV_SIGNAL, .sigev_signo = ZSIGALRM }; struct sigevent sigev2; struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; struct itimerspec old; retval = clock_gettime (CLOCK_REALTIME, &ts); sigev2.sigev_notify = SIGEV_THREAD; sigev2.sigev_notify_function = notify_func1; sigev2.sigev_notify_attributes = NULL; /* It is unnecessary to do the following but to set a good example we do it anyhow. */ sigev2.sigev_value.sival_ptr = NULL; setvbuf (stdout, 0, _IOLBF, 0); printf ("clock_gettime returned %d, timespec = { %jd, %jd }\n", retval, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); retval = clock_getres (CLOCK_REALTIME, &ts); printf ("clock_getres returned %d, timespec = { %jd, %jd }\n", retval, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); if (timer_create (CLOCK_REALTIME, &sigev1, &timer_sig) != 0) { printf ("timer_create for timer_sig failed: %m\n"); exit (1); } if (timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1) != 0) { printf ("timer_create for timer_thr1 failed: %m\n"); exit (1); } sigev2.sigev_notify_function = notify_func2; if (timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2) != 0) { printf ("timer_create for timer_thr2 failed: %m\n"); exit (1); } if (timer_settime (timer_thr1, 0, &itimer2, &old) != 0) { printf ("timer_settime for timer_thr1 failed: %m\n"); exit (1); } if (timer_settime (timer_thr2, 0, &itimer3, &old) != 0) { printf ("timer_settime for timer_thr2 failed: %m\n"); exit (1); } signal (ZSIGALRM, signal_func); if (timer_settime (timer_sig, 0, &itimer1, &old) != 0) { printf ("timer_settime for timer_sig failed: %m\n"); exit (1); } intr_sleep (3); if (timer_delete (timer_sig) != 0) { printf ("timer_delete for timer_sig failed: %m\n"); exit (1); } if (timer_delete (timer_thr1) != 0) { printf ("timer_delete for timer_thr1 failed: %m\n"); exit (1); } intr_sleep (3); if (timer_delete (timer_thr2) != 0) { printf ("timer_delete for timer_thr2 failed: %m\n"); exit (1); } return 0; }