int _sigsuspend(const sigset_t *set) { struct pthread *curthread = _get_curthread(); sigset_t oldmask, newmask, tempset; int ret = -1; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_sigsuspend(set)); /* Check if a new signal set was provided by the caller: */ if (set != NULL) { newmask = *set; SIG_CANTMASK(newmask); THR_LOCK_SWITCH(curthread); /* Save current sigmask: */ oldmask = curthread->sigmask; curthread->oldsigmask = &oldmask; /* Change the caller's mask: */ curthread->sigmask = newmask; tempset = curthread->sigpend; SIGSETNAND(tempset, newmask); if (SIGISEMPTY(tempset)) { THR_SET_STATE(curthread, PS_SIGSUSPEND); /* Wait for a signal: */ _thr_sched_switch_unlocked(curthread); } else { curthread->check_pending = 1; THR_UNLOCK_SWITCH(curthread); /* check pending signal I can handle: */ _thr_sig_check_pending(curthread); } if ((curthread->cancelflags & THR_CANCELLING) != 0) curthread->oldsigmask = NULL; else { THR_ASSERT(curthread->oldsigmask == NULL, "oldsigmask is not cleared"); } /* Always return an interrupted error: */ errno = EINTR; } else { /* Return an invalid argument error: */ errno = EINVAL; } /* Return the completion status: */ return (ret); }
int _nanosleep(const struct timespec *time_to_sleep, struct timespec *time_remaining) { struct pthread *curthread = _get_curthread(); int ret = 0; struct timespec ts, ts1; struct timespec remaining_time; struct timespec wakeup_time; /* Check if the time to sleep is legal: */ if ((time_to_sleep == NULL) || (time_to_sleep->tv_sec < 0) || (time_to_sleep->tv_nsec < 0) || (time_to_sleep->tv_nsec >= 1000000000)) { /* Return an EINVAL error : */ errno = EINVAL; ret = -1; } else { if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_nanosleep(time_to_sleep, time_remaining)); KSE_GET_TOD(curthread->kse, &ts); /* Calculate the time for the current thread to wake up: */ TIMESPEC_ADD(&wakeup_time, &ts, time_to_sleep); THR_LOCK_SWITCH(curthread); curthread->interrupted = 0; curthread->wakeup_time = wakeup_time; THR_SET_STATE(curthread, PS_SLEEP_WAIT); /* Reschedule the current thread to sleep: */ _thr_sched_switch_unlocked(curthread); /* Calculate the remaining time to sleep: */ KSE_GET_TOD(curthread->kse, &ts1); remaining_time.tv_sec = time_to_sleep->tv_sec + ts.tv_sec - ts1.tv_sec; remaining_time.tv_nsec = time_to_sleep->tv_nsec + ts.tv_nsec - ts1.tv_nsec; /* Check if the nanosecond field has underflowed: */ if (remaining_time.tv_nsec < 0) { /* Handle the underflow: */ remaining_time.tv_sec -= 1; remaining_time.tv_nsec += 1000000000; } /* Check if the nanosecond field has overflowed: */ else if (remaining_time.tv_nsec >= 1000000000) { /* Handle the overflow: */ remaining_time.tv_sec += 1; remaining_time.tv_nsec -= 1000000000; } /* Check if the sleep was longer than the required time: */ if (remaining_time.tv_sec < 0) { /* Reset the time left: */ remaining_time.tv_sec = 0; remaining_time.tv_nsec = 0; } /* Check if the time remaining is to be returned: */ if (time_remaining != NULL) { /* Return the actual time slept: */ time_remaining->tv_sec = remaining_time.tv_sec; time_remaining->tv_nsec = remaining_time.tv_nsec; } /* Check if the sleep was interrupted: */ if (curthread->interrupted) { /* Return an EINTR error : */ errno = EINTR; ret = -1; } } return (ret); }