File indexing completed on 2025-05-11 08:24:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042
0043 #include <rtems.h>
0044 #include <rtems/rtems/timerimpl.h>
0045 #include <rtems/rtems/tasksimpl.h>
0046 #include <rtems/score/todimpl.h>
0047
0048 static Timer_server_Control _Timer_server_Default;
0049
0050 static void _Timer_server_Acquire(
0051 Timer_server_Control *ts,
0052 ISR_lock_Context *lock_context
0053 )
0054 {
0055 _ISR_lock_ISR_disable_and_acquire( &ts->Lock, lock_context );
0056 }
0057
0058 static void _Timer_server_Release(
0059 Timer_server_Control *ts,
0060 ISR_lock_Context *lock_context
0061 )
0062 {
0063 _ISR_lock_Release_and_ISR_enable( &ts->Lock, lock_context );
0064 }
0065
0066 void _Timer_server_Routine_adaptor( Watchdog_Control *the_watchdog )
0067 {
0068 Timer_Control *the_timer;
0069 ISR_lock_Context lock_context;
0070 Per_CPU_Control *cpu;
0071 Timer_server_Control *ts;
0072 bool wakeup;
0073
0074 ts = _Timer_server;
0075 _Assert( ts != NULL );
0076 the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
0077
0078 _Timer_server_Acquire( ts, &lock_context );
0079
0080 _Assert( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_INACTIVE );
0081 _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_PENDING );
0082 cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
0083 the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
0084 wakeup = _Chain_Is_empty( &ts->Pending );
0085 _Chain_Append_unprotected( &ts->Pending, &the_timer->Ticker.Node.Chain );
0086
0087 _Timer_server_Release( ts, &lock_context );
0088
0089 if ( wakeup ) {
0090 (void) rtems_event_system_send( ts->server_id, RTEMS_EVENT_SYSTEM_SERVER );
0091 }
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 static rtems_task _Timer_server_Body(
0104 rtems_task_argument arg
0105 )
0106 {
0107 Timer_server_Control *ts = (Timer_server_Control *) arg;
0108 #if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
0109 Thread_Control *executing = _Thread_Get_executing();
0110 #endif
0111
0112 while ( true ) {
0113 ISR_lock_Context lock_context;
0114 rtems_event_set events;
0115
0116 _Timer_server_Acquire( ts, &lock_context );
0117
0118 while ( true ) {
0119 Watchdog_Control *the_watchdog;
0120 Timer_Control *the_timer;
0121 rtems_timer_service_routine_entry routine;
0122 Objects_Id id;
0123 void *user_data;
0124
0125 the_watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &ts->Pending );
0126 if ( the_watchdog == NULL ) {
0127 break;
0128 }
0129
0130 _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_PENDING );
0131 _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
0132 the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
0133 routine = the_timer->routine;
0134 id = the_timer->Object.id;
0135 user_data = the_timer->user_data;
0136
0137 _Timer_server_Release( ts, &lock_context );
0138
0139 ( *routine )( id, user_data );
0140 #if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
0141 _Assert( !_Thread_Owns_resources( executing ) );
0142 #endif
0143
0144 _Timer_server_Acquire( ts, &lock_context );
0145 }
0146
0147 _Timer_server_Release( ts, &lock_context );
0148
0149 (void) rtems_event_system_receive(
0150 RTEMS_EVENT_SYSTEM_SERVER,
0151 RTEMS_EVENT_ALL | RTEMS_WAIT,
0152 RTEMS_NO_TIMEOUT,
0153 &events
0154 );
0155 }
0156 }
0157
0158 static rtems_status_code _Timer_server_Initiate(
0159 rtems_task_priority priority,
0160 size_t stack_size,
0161 rtems_attribute attribute_set
0162 )
0163 {
0164 rtems_status_code status;
0165 rtems_id id;
0166 Timer_server_Control *ts;
0167
0168
0169
0170
0171 if ( _Timer_server != NULL ) {
0172 return RTEMS_INCORRECT_STATE;
0173 }
0174
0175 if ( priority == RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) {
0176 priority = PRIORITY_MINIMUM;
0177 }
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 status = rtems_task_create(
0194 rtems_build_name('T','I','M','E'),
0195 priority,
0196 stack_size,
0197 #ifdef RTEMS_SMP
0198 RTEMS_DEFAULT_MODES,
0199 #else
0200 RTEMS_NO_PREEMPT,
0201 #endif
0202
0203
0204 attribute_set | RTEMS_SYSTEM_TASK,
0205 &id
0206 );
0207 if (status != RTEMS_SUCCESSFUL) {
0208 return status;
0209 }
0210
0211
0212
0213
0214
0215
0216 ts = &_Timer_server_Default;
0217 _ISR_lock_Initialize( &ts->Lock, "Timer Server" );
0218 _Chain_Initialize_empty( &ts->Pending );
0219 ts->server_id = id;
0220
0221
0222
0223
0224 _Timer_server = ts;
0225
0226
0227
0228
0229 status = rtems_task_start(
0230 id,
0231 _Timer_server_Body,
0232 (rtems_task_argument) ts
0233 );
0234 _Assert( status == RTEMS_SUCCESSFUL );
0235
0236 return status;
0237 }
0238
0239 rtems_status_code rtems_timer_initiate_server(
0240 rtems_task_priority priority,
0241 size_t stack_size,
0242 rtems_attribute attribute_set
0243 )
0244 {
0245 rtems_status_code status;
0246
0247 _Objects_Allocator_lock();
0248 status = _Timer_server_Initiate( priority, stack_size, attribute_set );
0249 _Objects_Allocator_unlock();
0250
0251 return status;
0252 }