コード例 #1
0
ファイル: clock.c プロジェクト: BhargavKola/xenomai-forge
/**
 * 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;
}
コード例 #2
0
ファイル: sem.c プロジェクト: JackieXie168/xenomai
/**
 * 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;
}