Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:22

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup POSIXAPI
0007  *
0008  * @brief Function Arms or Disarms the Timer Identified by timerid 
0009  */
0010 
0011 /*
0012  *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
0013  *
0014  *  COPYRIGHT (c) 1989-2008.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <time.h>
0044 #include <errno.h>
0045 
0046 #include <rtems/posix/timerimpl.h>
0047 #include <rtems/score/todimpl.h>
0048 #include <rtems/score/watchdogimpl.h>
0049 #include <rtems/seterr.h>
0050 
0051 static void _POSIX_Timer_Insert(
0052   POSIX_Timer_Control *ptimer,
0053   Per_CPU_Control     *cpu,
0054   Watchdog_Interval    ticks
0055 )
0056 {
0057   /* The state really did not change but just to be safe */
0058   ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
0059 
0060   /* Store the time when the timer was started again */
0061   _TOD_Get( &ptimer->time );
0062 
0063   _Watchdog_Insert(
0064     &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
0065     &ptimer->Timer,
0066     cpu->Watchdog.ticks + ticks
0067   );
0068 }
0069 
0070 /*
0071  *  This is the operation that is run when a timer expires
0072  */
0073 void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog )
0074 {
0075   POSIX_Timer_Control *ptimer;
0076   ISR_lock_Context     lock_context;
0077   Per_CPU_Control     *cpu;
0078 
0079   ptimer = RTEMS_CONTAINER_OF( the_watchdog, POSIX_Timer_Control, Timer );
0080   _ISR_lock_ISR_disable( &lock_context );
0081   cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
0082 
0083   /* Increment the number of expirations. */
0084   ptimer->overrun = ptimer->overrun + 1;
0085 
0086   /* The timer must be reprogrammed */
0087   if ( ( ptimer->timer_data.it_interval.tv_sec  != 0 ) ||
0088        ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
0089     _POSIX_Timer_Insert( ptimer, cpu, ptimer->ticks );
0090   } else {
0091    /* Indicates that the timer is stopped */
0092    ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
0093   }
0094 
0095   _POSIX_Timer_Release( cpu, &lock_context );
0096 
0097   /*
0098    * The sending of the signal to the process running the handling function
0099    * specified for that signal is simulated
0100    */
0101 
0102   if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
0103     _Assert( FALSE );
0104     /*
0105      * TODO: What if an error happens at run-time? This should never
0106      *       occur because the timer should be canceled if the thread
0107      *       is deleted. This method is being invoked from the Clock
0108      *       Tick ISR so even if we decide to take action on an error,
0109      *       we don't have many options. We shouldn't shut the system down.
0110      */
0111   }
0112 
0113   /* After the signal handler returns, the count of expirations of the
0114    * timer must be set to 0.
0115    */
0116   ptimer->overrun = 0;
0117 }
0118 
0119 int timer_settime(
0120   timer_t                  timerid,
0121   int                      flags,
0122   const struct itimerspec *__restrict value,
0123   struct itimerspec       *__restrict ovalue
0124 )
0125 {
0126   POSIX_Timer_Control *ptimer;
0127   ISR_lock_Context     lock_context;
0128   uint32_t             initial_period;
0129   struct itimerspec    normalize;
0130 
0131   if ( !value )
0132     rtems_set_errno_and_return_minus_one( EINVAL );
0133 
0134   /* 
0135    * First, it verifies if the structure "value" is correct   
0136    * if the number of nanoseconds is not correct return EINVAL
0137    */
0138   if ( !_Timespec_Is_valid( &(value->it_value) ) ) {
0139     rtems_set_errno_and_return_minus_one( EINVAL );
0140   }
0141   if ( !_Timespec_Is_valid( &(value->it_interval) ) ) {
0142     rtems_set_errno_and_return_minus_one( EINVAL );
0143   }
0144 
0145   if ( flags != TIMER_ABSTIME && flags != POSIX_TIMER_RELATIVE ) {
0146     rtems_set_errno_and_return_minus_one( EINVAL );
0147   }
0148 
0149   normalize = *value;
0150 
0151   /* Convert absolute to relative time */
0152   if (flags == TIMER_ABSTIME) {
0153     struct timespec now;
0154     _TOD_Get( &now );
0155     /* Check for seconds in the past */
0156     if ( _Timespec_Greater_than( &now, &normalize.it_value ) )
0157       rtems_set_errno_and_return_minus_one( EINVAL );
0158     _Timespec_Subtract( &now, &normalize.it_value, &normalize.it_value );
0159   }
0160 
0161   /* If the function reaches this point, then it will be necessary to do
0162    * something with the structure of times of the timer: to stop, start
0163    * or start it again
0164    */
0165 
0166   ptimer = _POSIX_Timer_Get( timerid, &lock_context );
0167   if ( ptimer != NULL ) {
0168     Per_CPU_Control *cpu;
0169 
0170     cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
0171 
0172     /* Stop the timer */
0173     _Watchdog_Remove(
0174       &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
0175       &ptimer->Timer
0176     );
0177 
0178     /* First, it verifies if the timer must be stopped */
0179     if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) {
0180       /* The old data of the timer are returned */
0181       if ( ovalue )
0182         *ovalue = ptimer->timer_data;
0183       /* The new data are set */
0184       ptimer->timer_data = normalize;
0185       /* Indicates that the timer is created and stopped */
0186       ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
0187       /* Returns with success */
0188       _POSIX_Timer_Release( cpu, &lock_context );
0189       return 0;
0190     }
0191 
0192     /* Convert from seconds and nanoseconds to ticks */
0193     ptimer->ticks  = _Timespec_To_ticks( &value->it_interval );
0194     initial_period = _Timespec_To_ticks( &normalize.it_value );
0195 
0196     _POSIX_Timer_Insert( ptimer, cpu, initial_period );
0197 
0198     /*
0199      * The timer has been started and is running.  So we return the
0200      * old ones in "ovalue"
0201      */
0202     if ( ovalue )
0203       *ovalue = ptimer->timer_data;
0204     ptimer->timer_data = normalize;
0205     _POSIX_Timer_Release( cpu, &lock_context );
0206     return 0;
0207   }
0208 
0209   rtems_set_errno_and_return_minus_one( EINVAL );
0210 }