source: rtems/cpukit/posix/src/timersettime.c @ 77e6eba7

Last change on this file since 77e6eba7 was 77e6eba7, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 7, 2016 at 3:01:57 PM

score: Add and use _Objects_Get_local()

This simplifies the handling with local-only objects.

Update #2555.

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