source: rtems/cpukit/rtems/src/timercreate.c @ 21275b58

Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 22, 2018 at 6:14:51 PM

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS Create Timer
5 *  @ingroup ClassicTimer
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2002.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/rtems/timerimpl.h>
22#include <rtems/rtems/clock.h>
23#include <rtems/rtems/status.h>
24#include <rtems/rtems/support.h>
25#include <rtems/score/assert.h>
26#include <rtems/score/chainimpl.h>
27#include <rtems/score/thread.h>
28#include <rtems/score/todimpl.h>
29#include <rtems/score/watchdogimpl.h>
30#include <rtems/sysinit.h>
31
32RTEMS_STATIC_ASSERT(
33  PER_CPU_WATCHDOG_REALTIME == TIMER_CLASS_BIT_TIME_OF_DAY,
34  TIMER_CLASS_BIT_TIME_OF_DAY
35);
36
37Timer_server_Control *volatile _Timer_server;
38
39void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog )
40{
41  Timer_Control   *the_timer;
42  Per_CPU_Control *cpu;
43
44  the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
45  cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
46  the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
47
48  ( *the_timer->routine )( the_timer->Object.id, the_timer->user_data );
49}
50
51rtems_status_code _Timer_Fire(
52  rtems_id                           id,
53  rtems_interval                     interval,
54  rtems_timer_service_routine_entry  routine,
55  void                              *user_data,
56  Timer_Classes                      the_class,
57  Watchdog_Service_routine_entry     adaptor
58)
59{
60  Timer_Control    *the_timer;
61  ISR_lock_Context  lock_context;
62
63  the_timer = _Timer_Get( id, &lock_context );
64  if ( the_timer != NULL ) {
65    Per_CPU_Control *cpu;
66
67    cpu = _Timer_Acquire_critical( the_timer, &lock_context );
68    _Timer_Cancel( cpu, the_timer );
69    _Watchdog_Initialize( &the_timer->Ticker, adaptor );
70    the_timer->the_class = the_class;
71    the_timer->routine = routine;
72    the_timer->user_data = user_data;
73    the_timer->initial = interval;
74    the_timer->start_time = _Timer_Get_CPU_ticks( cpu );
75
76    if ( _Timer_Is_interval_class( the_class ) ) {
77      _Watchdog_Insert(
78        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ],
79        &the_timer->Ticker,
80        cpu->Watchdog.ticks + interval
81      );
82    } else {
83      _Watchdog_Insert(
84        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
85        &the_timer->Ticker,
86        _Watchdog_Ticks_from_seconds( interval )
87      );
88    }
89
90    _Timer_Release( cpu, &lock_context );
91    return RTEMS_SUCCESSFUL;
92  }
93
94  return RTEMS_INVALID_ID;
95}
96
97rtems_status_code _Timer_Fire_after(
98  rtems_id                           id,
99  rtems_interval                     ticks,
100  rtems_timer_service_routine_entry  routine,
101  void                              *user_data,
102  Timer_Classes                      the_class,
103  Watchdog_Service_routine_entry     adaptor
104)
105{
106  if ( ticks == 0 )
107    return RTEMS_INVALID_NUMBER;
108
109  if ( !routine )
110    return RTEMS_INVALID_ADDRESS;
111
112  return _Timer_Fire(
113    id,
114    ticks,
115    routine,
116    user_data,
117    the_class,
118    adaptor
119  );
120}
121
122rtems_status_code _Timer_Fire_when(
123  rtems_id                           id,
124  const rtems_time_of_day           *wall_time,
125  rtems_timer_service_routine_entry  routine,
126  void                              *user_data,
127  Timer_Classes                      the_class,
128  Watchdog_Service_routine_entry     adaptor
129)
130{
131  rtems_interval seconds;
132
133  if ( !_TOD_Is_set() )
134    return RTEMS_NOT_DEFINED;
135
136  if ( !routine )
137    return RTEMS_INVALID_ADDRESS;
138
139  if ( !_TOD_Validate( wall_time ) )
140    return RTEMS_INVALID_CLOCK;
141
142  seconds = _TOD_To_seconds( wall_time );
143  if ( seconds <= _TOD_Seconds_since_epoch() )
144    return RTEMS_INVALID_CLOCK;
145
146  return _Timer_Fire(
147    id,
148    seconds,
149    routine,
150    user_data,
151    the_class,
152    adaptor
153  );
154}
155
156void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer )
157{
158  Timer_Classes the_class;
159
160  the_class = the_timer->the_class;
161
162  if ( _Watchdog_Is_scheduled( &the_timer->Ticker ) ) {
163    the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
164    _Watchdog_Remove(
165      &cpu->Watchdog.Header[ _Timer_Watchdog_header_index( the_class ) ],
166      &the_timer->Ticker
167    );
168  } else if ( _Timer_Is_on_task_class( the_class ) ) {
169    Timer_server_Control *timer_server;
170    ISR_lock_Context      lock_context;
171
172    timer_server = _Timer_server;
173    _Assert( timer_server != NULL );
174    _Timer_server_Acquire_critical( timer_server, &lock_context );
175
176    if ( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_PENDING ) {
177      _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_INACTIVE );
178      _Chain_Extract_unprotected( &the_timer->Ticker.Node.Chain );
179    }
180
181    _Timer_server_Release_critical( timer_server, &lock_context );
182  }
183}
184
185rtems_status_code rtems_timer_create(
186  rtems_name  name,
187  rtems_id   *id
188)
189{
190  Timer_Control *the_timer;
191
192  if ( !rtems_is_name_valid( name ) )
193    return RTEMS_INVALID_NAME;
194
195  if ( !id )
196    return RTEMS_INVALID_ADDRESS;
197
198  the_timer = _Timer_Allocate();
199
200  if ( !the_timer ) {
201    _Objects_Allocator_unlock();
202    return RTEMS_TOO_MANY;
203  }
204
205  the_timer->the_class = TIMER_DORMANT;
206  _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() );
207
208  _Objects_Open(
209    &_Timer_Information,
210    &the_timer->Object,
211    (Objects_Name) name
212  );
213
214  *id = the_timer->Object.id;
215  _Objects_Allocator_unlock();
216  return RTEMS_SUCCESSFUL;
217}
218
219static void _Timer_Manager_initialization( void )
220{
221  _Objects_Initialize_information( &_Timer_Information );
222}
223
224RTEMS_SYSINIT_ITEM(
225  _Timer_Manager_initialization,
226  RTEMS_SYSINIT_CLASSIC_TIMER,
227  RTEMS_SYSINIT_ORDER_MIDDLE
228);
Note: See TracBrowser for help on using the repository browser.