static void* __timer_thread_start(void* arg) { PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg); kernel_sigset_t sigset; sigaddset(sigset.get(), TIMER_SIGNAL); while (true) { // Wait for a signal... siginfo_t si; memset(&si, 0, sizeof(si)); int rc = __rt_sigtimedwait(sigset.get(), &si, NULL, sizeof(sigset)); if (rc == -1) { continue; } if (si.si_code == SI_TIMER) { // This signal was sent because a timer fired, so call the callback. timer->callback(timer->callback_argument); } else if (si.si_code == SI_TKILL) { // This signal was sent because someone wants us to exit. free(timer); return NULL; } } }
static void* __timer_thread_start(void* arg) { PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg); sigset64_t sigset = {}; sigaddset64(&sigset, TIMER_SIGNAL); while (true) { // Wait for a signal... siginfo_t si = {}; if (__rt_sigtimedwait(&sigset, &si, nullptr, sizeof(sigset)) == -1) continue; if (si.si_code == SI_TIMER) { // This signal was sent because a timer fired, so call the callback. // All events to the callback will be ignored when the timer is deleted. if (atomic_load(&timer->deleted) == true) { continue; } timer->callback(timer->callback_argument); } else if (si.si_code == SI_TKILL) { // This signal was sent because someone wants us to exit. free(timer); return nullptr; } } }
int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) { sigset64_t mutable_set; sigset64_t* mutable_set_ptr = nullptr; if (set) { mutable_set = filter_reserved_signals(*set, SIG_SETMASK); mutable_set_ptr = &mutable_set; } return __rt_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set)); }
int sigwait(const sigset_t* set, int* sig) { kernel_sigset_t sigset(set); while (true) { // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop // around them since sigwait is only allowed to return EINVAL. int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset)); if (result >= 0) { *sig = result; return 0; } if (errno != EAGAIN && errno != EINTR) { return errno; } } }
/* Helper function to support starting threads for SIGEV_THREAD. */ static void *timer_thread_main (void *arg) { /* Wait for the SIGTIMER signal */ sem_t *sem = (sem_t *)arg; #ifdef ANDROID unsigned long sigset[2]; memset(&sigset, 0, sizeof(sigset)); #else sigset_t sigset; sigemptyset(&sigset); #endif sigaddset((sigset_t*)&sigset, SIGTIMER); th_timer_tid = gettid(); sem_post(sem); /* Endless loop for waiting for signals. The loop is only ended when the thread is canceled. */ while (1) { siginfo_t si; int result; #ifdef ANDROID result = __rt_sigtimedwait((sigset_t*)&sigset, &si, NULL, sizeof(sigset)); #else result = sigwaitinfo(&sigset, &si); #endif if (result > 0) { if (si.si_code == SI_TIMER) { timer *t; t = static_cast<timer*>(si.si_value.sival_ptr); t->alarm.signal(); } } } return NULL; }
int sigwait(const sigset_t *set, int *sig) { int ret; #ifdef __mips__ /* use a union to get rid of aliasing warnings. On MIPS sigset_t is 128 bits */ union { sigset_t kernel_sigset; sigset_t dummy_sigset; } u; u.dummy_sigset = *set; #else /* use a union to get rid of aliasing warnings */ union { unsigned long kernel_sigset[2]; sigset_t dummy_sigset; } u; u.kernel_sigset[0] = *set; u.kernel_sigset[1] = 0; /* no real-time signals supported ? */ #endif for (;;) { /* __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop * around them since sigwait is only allowed to return EINVAL */ ret = __rt_sigtimedwait ( &u.dummy_sigset, NULL, NULL, sizeof(u.kernel_sigset)); if (ret >= 0) break; if (errno != EAGAIN && errno != EINTR) return errno; } *sig = ret; return 0; }
int attribute_hidden __sigtimedwait(const sigset_t * set, siginfo_t * info, const struct timespec *timeout) { return __rt_sigtimedwait(set, info, timeout, _NSIG / 8); }
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *ts) { return __rt_sigtimedwait(set,info,ts,_NSIG/8); }
int sigwaitinfo(const sigset_t * set, siginfo_t * info) { return __rt_sigtimedwait(set, info, NULL, _NSIG / 8); }