/* * Copyright (C) 2005 Philippe Gerum . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include "internal.h" /** * @addtogroup cobalt_api_time * @{ */ /** * @fn int timer_create(clockid_t clockid, const struct sigevent *__restrict__ evp, timer_t * __restrict__ timerid) * @brief Create a timer * * This service creates a timer based on the clock @a clockid. * * If @a evp is not @a NULL, it describes the notification mechanism * used on timer expiration. Only thread-directed notification is * supported (evp->sigev_notify set to @a SIGEV_THREAD_ID). * * If @a evp is NULL, the current Cobalt thread will receive the * notifications with signal SIGALRM. * * The recipient thread is delivered notifications when it calls any * of the sigwait(), sigtimedwait() or sigwaitinfo() services. * * If this service succeeds, an identifier for the created timer is * returned at the address @a timerid. The timer is unarmed until * started with the timer_settime() service. * * @param clockid clock used as a timing base; * * @param evp description of the asynchronous notification to occur * when the timer expires; * * @param timerid address where the identifier of the created timer * will be stored on success. * * @retval 0 on success; * @retval -1 with @a errno set if: * - EINVAL, the clock @a clockid is invalid; * - EINVAL, the member @a sigev_notify of the @b sigevent structure at the * address @a evp is not SIGEV_THREAD_ID; * - EINVAL, the member @a sigev_signo of the @b sigevent structure is an * invalid signal number; * - EAGAIN, the maximum number of timers was exceeded, recompile with a larger * value. * * @see * * Specification. * * @apitags{thread-unrestricted} */ COBALT_IMPL(int, timer_create, (clockid_t clockid, const struct sigevent *__restrict__ evp, timer_t * __restrict__ timerid)) { int ret; ret = -XENOMAI_SYSCALL3(sc_cobalt_timer_create, clockid, evp, timerid); if (ret == 0) return 0; errno = ret; return -1; } /** * Delete a timer object. * * This service deletes the timer @a timerid. * * @param timerid identifier of the timer to be removed; * * @retval 0 on success; * @retval -1 with @a errno set if: * - EINVAL, @a timerid is invalid; * - EPERM, the timer @a timerid does not belong to the current process. * * @see * * Specification. * * @apitags{thread-unrestricted} */ COBALT_IMPL(int, timer_delete, (timer_t timerid)) { int ret; ret = -XENOMAI_SYSCALL1(sc_cobalt_timer_delete, timerid); if (ret == 0) return 0; errno = ret; return -1; } /** * @fn timer_settime(timer_t timerid, int flags, const struct itimerspec *__restrict__ value, struct itimerspec *__restrict__ ovalue) * @brief Start or stop a timer * * This service sets a timer expiration date and reload value of the * timer @a timerid. If @a ovalue is not @a NULL, the current * expiration date and reload value are stored at the address @a * ovalue as with timer_gettime(). * * If the member @a it_value of the @b itimerspec structure at @a * value is zero, the timer is stopped, otherwise the timer is * started. If the member @a it_interval is not zero, the timer is * periodic. The current thread must be a Cobalt thread (created with * pthread_create()) and will be notified via signal of timer * expirations. * * When starting the timer, if @a flags is TIMER_ABSTIME, the expiration value * is interpreted as an absolute date of the clock passed to the timer_create() * service. Otherwise, the expiration value is interpreted as a time interval. * * Expiration date and reload value are rounded to an integer count of * nanoseconds. * * @param timerid identifier of the timer to be started or stopped; * * @param flags one of 0 or TIMER_ABSTIME; * * @param value address where the specified timer expiration date and reload * value are read; * * @param ovalue address where the specified timer previous expiration date and * reload value are stored if not @a NULL. * * @retval 0 on success; * @retval -1 with @a errno set if: * - EINVAL, the specified timer identifier, expiration date or reload value is * invalid. For @a timerid to be valid, it must belong to the current process. * * @see * * Specification. * * @apitags{xcontext, switch-primary} */ COBALT_IMPL(int, timer_settime, (timer_t timerid, int flags, const struct itimerspec *__restrict__ value, struct itimerspec *__restrict__ ovalue)) { int ret; ret = -XENOMAI_SYSCALL4(sc_cobalt_timer_settime, timerid, flags, value, ovalue); if (ret == 0) return 0; errno = ret; return -1; } /** * @fn int timer_gettime(timer_t timerid, struct itimerspec *value) * @brief Get timer next expiration date and reload value. * * This service stores, at the address @a value, the expiration date * (member @a it_value) and reload value (member @a it_interval) of * the timer @a timerid. The values are returned as time intervals, * and as multiples of the system clock tick duration (see note in * section @ref cobalt_api_time "Clocks and timers services" for details * on the duration of the system clock tick). If the timer was not * started, the returned members @a it_value and @a it_interval of @a * value are zero. * * @param timerid timer identifier; * * @param value address where the timer expiration date and reload value are * stored on success. * * @retval 0 on success; * @retval -1 with @a errno set if: * - EINVAL, @a timerid is invalid. For @a timerid to be valid, it * must belong to the current process. * * @see * * Specification. * * @apitags{unrestricted} */ COBALT_IMPL(int, timer_gettime, (timer_t timerid, struct itimerspec *value)) { int ret; ret = -XENOMAI_SYSCALL2(sc_cobalt_timer_gettime, timerid, value); if (ret == 0) return 0; errno = ret; return -1; } /** * Get expiration overruns count since the most recent timer expiration * signal delivery. * * This service returns @a timerid expiration overruns count since the most * recent timer expiration signal delivery. If this count is more than @a * DELAYTIMER_MAX expirations, @a DELAYTIMER_MAX is returned. * * @param timerid Timer identifier. * * @return the overruns count on success; * @return -1 with @a errno set if: * - EINVAL, @a timerid is invalid; * - EPERM, the timer @a timerid does not belong to the current process. * * @see * * Specification. * * @apitags{unrestricted} */ COBALT_IMPL(int, timer_getoverrun, (timer_t timerid)) { int overrun; overrun = XENOMAI_SYSCALL1(sc_cobalt_timer_getoverrun, timerid); if (overrun >= 0) return overrun; errno = -overrun; return -1; } /** @} */