/** * 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; }
/** * Attempt, during a bounded time, to lock a semaphore. * * This serivce is equivalent to sem_wait(), except that the caller is only * blocked until the timeout @a abs_timeout expires. * * @param sm the semaphore to be locked; * * @param abs_timeout the timeout, expressed as an absolute value of the * CLOCK_REALTIME clock. * * @retval 0 on success; * @retval -1 with @a errno set if: * - EPERM, the caller context is invalid; * - EINVAL, the semaphore is invalid or uninitialized; * - EINVAL, the specified timeout is invalid; * - EPERM, the semaphore @a sm is not process-shared and does not belong to the * current process; * - EINTR, the caller was interrupted by a signal while blocked in this * service; * - ETIMEDOUT, the semaphore could not be locked and the specified timeout * expired. * * @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/sem_timedwait.html"> * Specification.</a> * */ int sem_timedwait(sem_t * sm, const struct timespec *abs_timeout) { struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem; spl_t s; int err; if (abs_timeout->tv_nsec > ONE_BILLION) { err = EINVAL; goto error; } xnlock_get_irqsave(&nklock, s); err = sem_timedwait_internal(shadow, 1, ts2ticks_ceil(abs_timeout) + 1); xnlock_put_irqrestore(&nklock, s); error: if (err) { thread_set_errno(err); return -1; } return 0; }