source: rtems/cpukit/posix/src/timersettime.c @ dbb7ac6

5
Last change on this file since dbb7ac6 was dbb7ac6, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 14, 2020 at 10:23:12 AM

posix: Remove <rtems/posix/ptimer.h>

This file contained duplicate prototypes for standard POSIX functions
declared in <time.h>.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Function Arms or Disarms the Timer Identified by timerid
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
10 *
11 *  COPYRIGHT (c) 1989-2008.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <time.h>
24#include <errno.h>
25
26#include <rtems/posix/timerimpl.h>
27#include <rtems/score/todimpl.h>
28#include <rtems/score/watchdogimpl.h>
29#include <rtems/seterr.h>
30
31static void _POSIX_Timer_Insert(
32  POSIX_Timer_Control *ptimer,
33  Per_CPU_Control     *cpu,
34  Watchdog_Interval    ticks
35)
36{
37  /* The state really did not change but just to be safe */
38  ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
39
40  /* Store the time when the timer was started again */
41  _TOD_Get( &ptimer->time );
42
43  _Watchdog_Insert(
44    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
45    &ptimer->Timer,
46    cpu->Watchdog.ticks + ticks
47  );
48}
49
50/*
51 *  This is the operation that is run when a timer expires
52 */
53void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog )
54{
55  POSIX_Timer_Control *ptimer;
56  ISR_lock_Context     lock_context;
57  Per_CPU_Control     *cpu;
58
59  ptimer = RTEMS_CONTAINER_OF( the_watchdog, POSIX_Timer_Control, Timer );
60  _ISR_lock_ISR_disable( &lock_context );
61  cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
62
63  /* Increment the number of expirations. */
64  ptimer->overrun = ptimer->overrun + 1;
65
66  /* The timer must be reprogrammed */
67  if ( ( ptimer->timer_data.it_interval.tv_sec  != 0 ) ||
68       ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
69    _POSIX_Timer_Insert( ptimer, cpu, ptimer->ticks );
70  } else {
71   /* Indicates that the timer is stopped */
72   ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
73  }
74
75  _POSIX_Timer_Release( cpu, &lock_context );
76
77  /*
78   * The sending of the signal to the process running the handling function
79   * specified for that signal is simulated
80   */
81
82  if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
83    _Assert( FALSE );
84    /*
85     * TODO: What if an error happens at run-time? This should never
86     *       occur because the timer should be canceled if the thread
87     *       is deleted. This method is being invoked from the Clock
88     *       Tick ISR so even if we decide to take action on an error,
89     *       we don't have many options. We shouldn't shut the system down.
90     */
91  }
92
93  /* After the signal handler returns, the count of expirations of the
94   * timer must be set to 0.
95   */
96  ptimer->overrun = 0;
97}
98
99int timer_settime(
100  timer_t                  timerid,
101  int                      flags,
102  const struct itimerspec *__restrict value,
103  struct itimerspec       *__restrict ovalue
104)
105{
106  POSIX_Timer_Control *ptimer;
107  ISR_lock_Context     lock_context;
108  uint32_t             initial_period;
109  struct itimerspec    normalize;
110
111  if ( !value )
112    rtems_set_errno_and_return_minus_one( EINVAL );
113
114  /*
115   * First, it verifies if the structure "value" is correct   
116   * if the number of nanoseconds is not correct return EINVAL
117   */
118  if ( !_Timespec_Is_valid( &(value->it_value) ) ) {
119    rtems_set_errno_and_return_minus_one( EINVAL );
120  }
121  if ( !_Timespec_Is_valid( &(value->it_interval) ) ) {
122    rtems_set_errno_and_return_minus_one( EINVAL );
123  }
124
125  if ( flags != TIMER_ABSTIME && flags != POSIX_TIMER_RELATIVE ) {
126    rtems_set_errno_and_return_minus_one( EINVAL );
127  }
128
129  normalize = *value;
130
131  /* Convert absolute to relative time */
132  if (flags == TIMER_ABSTIME) {
133    struct timespec now;
134    _TOD_Get( &now );
135    /* Check for seconds in the past */
136    if ( _Timespec_Greater_than( &now, &normalize.it_value ) )
137      rtems_set_errno_and_return_minus_one( EINVAL );
138    _Timespec_Subtract( &now, &normalize.it_value, &normalize.it_value );
139  }
140
141  /* If the function reaches this point, then it will be necessary to do
142   * something with the structure of times of the timer: to stop, start
143   * or start it again
144   */
145
146  ptimer = _POSIX_Timer_Get( timerid, &lock_context );
147  if ( ptimer != NULL ) {
148    Per_CPU_Control *cpu;
149
150    cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
151
152    /* Stop the timer */
153    _Watchdog_Remove(
154      &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
155      &ptimer->Timer
156    );
157
158    /* First, it verifies if the timer must be stopped */
159    if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) {
160      /* The old data of the timer are returned */
161      if ( ovalue )
162        *ovalue = ptimer->timer_data;
163      /* The new data are set */
164      ptimer->timer_data = normalize;
165      /* Indicates that the timer is created and stopped */
166      ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
167      /* Returns with success */
168      _POSIX_Timer_Release( cpu, &lock_context );
169      return 0;
170    }
171
172    /* Convert from seconds and nanoseconds to ticks */
173    ptimer->ticks  = _Timespec_To_ticks( &value->it_interval );
174    initial_period = _Timespec_To_ticks( &normalize.it_value );
175
176    _POSIX_Timer_Insert( ptimer, cpu, initial_period );
177
178    /*
179     * The timer has been started and is running.  So we return the
180     * old ones in "ovalue"
181     */
182    if ( ovalue )
183      *ovalue = ptimer->timer_data;
184    ptimer->timer_data = normalize;
185    _POSIX_Timer_Release( cpu, &lock_context );
186    return 0;
187  }
188
189  rtems_set_errno_and_return_minus_one( EINVAL );
190}
Note: See TracBrowser for help on using the repository browser.