/** * Sleep some amount of time. * * This service suspends the calling thread until the wakeup time specified by * @a rqtp, or a signal is delivered to the caller. If the flag TIMER_ABSTIME is * set in the @a flags argument, the wakeup time is specified as an absolute * value of the clock @a clock_id. If the flag TIMER_ABSTIME is not set, the * wakeup time is specified as a time interval. * * If this service is interrupted by a signal, the flag TIMER_ABSTIME is not * set, and @a rmtp is not @a NULL, the time remaining until the specified * wakeup time is returned at the address @a rmtp. * * The resolution of this service is one system clock tick. * * @param clock_id clock identifier, either CLOCK_REALTIME, * CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW. * * @param flags one of: * - 0 meaning that the wakeup time @a rqtp is a time interval; * - TIMER_ABSTIME, meaning that the wakeup time is an absolute value of the * clock @a clock_id. * * @param rqtp address of the wakeup time. * * @param rmtp address where the remaining time before wakeup will be stored if * the service is interrupted by a signal. * * @return 0 on success; * @return an error number if: * - EPERM, the caller context is invalid; * - ENOTSUP, the specified clock is unsupported; * - EINVAL, the specified wakeup time is invalid; * - EINTR, this service was interrupted by a signal. * * @par Valid contexts: * - Xenomai kernel-space thread, * - Xenomai user-space thread (switches to primary mode). * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/clock_nanosleep.html"> * Specification.</a> * */ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp) { xnthread_t *cur; spl_t s; int err = 0; if (xnpod_unblockable_p()) return EPERM; if (clock_id != CLOCK_MONOTONIC && clock_id != CLOCK_MONOTONIC_RAW && clock_id != CLOCK_REALTIME) return ENOTSUP; if ((unsigned long)rqtp->tv_nsec >= ONE_BILLION) return EINVAL; if (flags & ~TIMER_ABSTIME) return EINVAL; cur = xnpod_current_thread(); xnlock_get_irqsave(&nklock, s); thread_cancellation_point(cur); xnpod_suspend_thread(cur, XNDELAY, ts2ticks_ceil(rqtp) + 1, clock_flag(flags, clock_id), NULL); thread_cancellation_point(cur); if (xnthread_test_info(cur, XNBREAK)) { if (flags == 0 && rmtp) { xnticks_t now, expiry; xnsticks_t rem; now = clock_get_ticks(clock_id); expiry = xntimer_get_date(&cur->rtimer); xnlock_put_irqrestore(&nklock, s); rem = expiry - now; ticks2ts(rmtp, rem > 0 ? rem : 0); } else xnlock_put_irqrestore(&nklock, s); return EINTR; } xnlock_put_irqrestore(&nklock, s); return err; }
static inline int sem_timedwait_internal(struct __shadow_sem *shadow, int timed, xnticks_t to) { pse51_sem_t *sem = shadow->sem; xnthread_t *cur; int err; if (xnpod_unblockable_p()) return EPERM; cur = xnpod_current_thread(); if ((err = sem_trywait_internal(shadow)) != EAGAIN) return err; thread_cancellation_point(cur); if (timed) xnsynch_sleep_on(&sem->synchbase, to, XN_REALTIME); else xnsynch_sleep_on(&sem->synchbase, XN_INFINITE, XN_RELATIVE); /* Handle cancellation requests. */ thread_cancellation_point(cur); if (xnthread_test_info(cur, XNRMID)) return EINVAL; if (xnthread_test_info(cur, XNBREAK)) return EINTR; if (xnthread_test_info(cur, XNTIMEO)) return ETIMEDOUT; return 0; }