rtems_status_code rtems_timer_delete( rtems_id id ) { Timer_Control *the_timer; Objects_Locations location; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Objects_Close( &_Timer_Information, &the_timer->Object ); (void) _Watchdog_Remove( &the_timer->Ticker ); _Timer_Free( the_timer ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_cancel( rtems_id id ) { Timer_Control *the_timer; Objects_Locations location; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( !_Timer_Is_dormant_class( the_timer->the_class ) ) (void) _Watchdog_Remove( &the_timer->Ticker ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_reset( rtems_id id ) { Timer_Control *the_timer; ISR_lock_Context lock_context; the_timer = _Timer_Get( id, &lock_context ); if ( the_timer != NULL ) { Per_CPU_Control *cpu; rtems_status_code status; cpu = _Timer_Acquire_critical( the_timer, &lock_context ); if ( _Timer_Is_interval_class( the_timer->the_class ) ) { _Timer_Cancel( cpu, the_timer ); _Watchdog_Insert( &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ], &the_timer->Ticker, cpu->Watchdog.ticks + the_timer->initial ); status = RTEMS_SUCCESSFUL; } else { status = RTEMS_NOT_DEFINED; } _Timer_Release( cpu, &lock_context ); return status; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_get_information( rtems_id id, rtems_timer_information *the_info ) { Timer_Control *the_timer; Objects_Locations location; ISR_lock_Context lock_context; Per_CPU_Control *cpu; if ( !the_info ) return RTEMS_INVALID_ADDRESS; the_timer = _Timer_Get( id, &location, &lock_context ); switch ( location ) { case OBJECTS_LOCAL: cpu = _Timer_Acquire_critical( the_timer, &lock_context ); the_info->the_class = the_timer->the_class; the_info->initial = the_timer->initial; the_info->start_time = the_timer->start_time; the_info->stop_time = the_timer->stop_time; _Timer_Release( cpu, &lock_context ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_fire_after( rtems_id id, rtems_interval ticks, rtems_timer_service_routine_entry routine, void *user_data ) { Timer_Control *the_timer; Objects_Locations location; ISR_Level level; if ( ticks == 0 ) return RTEMS_INVALID_NUMBER; if ( !routine ) return RTEMS_INVALID_ADDRESS; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Timer_Cancel( the_timer ); _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); _Objects_Put( &the_timer->Object ); return RTEMS_SUCCESSFUL; } /* * OK. Now we now the timer was not rescheduled by an interrupt * so we can atomically initialize it as in use. */ the_timer->the_class = TIMER_INTERVAL; _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); _ISR_Enable( level ); _Watchdog_Insert_ticks( &the_timer->Ticker, ticks ); _Objects_Put( &the_timer->Object ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_reset( rtems_id id ) { Timer_Control *the_timer; Objects_Locations location; rtems_status_code status = RTEMS_SUCCESSFUL; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( the_timer->the_class == TIMER_INTERVAL ) { _Watchdog_Remove( &the_timer->Ticker ); _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker ); } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) { Timer_server_Control *timer_server = _Timer_server; /* * There is no way for a timer to have this class unless * it was scheduled as a server fire. That requires that * the Timer Server be initiated. So this error cannot * occur unless something is internally wrong. */ #if defined(RTEMS_DEBUG) if ( !timer_server ) { _Thread_Enable_dispatch(); return RTEMS_INCORRECT_STATE; } #endif _Watchdog_Remove( &the_timer->Ticker ); (*timer_server->schedule_operation)( timer_server, the_timer ); } else { /* * Must be dormant or time of day timer (e.g. TIMER_DORMANT, * TIMER_TIME_OF_DAY, or TIMER_TIME_OF_DAY_ON_TASK). We * can only reset active interval timers. */ status = RTEMS_NOT_DEFINED; } _Thread_Enable_dispatch(); return status; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_server_fire_when( rtems_id id, rtems_time_of_day *wall_time, rtems_timer_service_routine_entry routine, void *user_data ) { Timer_Control *the_timer; Objects_Locations location; rtems_interval seconds; Timer_server_Control *timer_server = _Timer_server; if ( !timer_server ) return RTEMS_INCORRECT_STATE; if ( !_TOD.is_set ) return RTEMS_NOT_DEFINED; if ( !routine ) return RTEMS_INVALID_ADDRESS; if ( !_TOD_Validate( wall_time ) ) return RTEMS_INVALID_CLOCK; seconds = _TOD_To_seconds( wall_time ); if ( seconds <= _TOD_Seconds_since_epoch() ) return RTEMS_INVALID_CLOCK; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: (void) _Watchdog_Remove( &the_timer->Ticker ); the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK; _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch(); (*timer_server->schedule_operation)( timer_server, the_timer ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code _Timer_Fire( rtems_id id, rtems_interval interval, rtems_timer_service_routine_entry routine, void *user_data, Timer_Classes the_class, Watchdog_Service_routine_entry adaptor ) { Timer_Control *the_timer; ISR_lock_Context lock_context; the_timer = _Timer_Get( id, &lock_context ); if ( the_timer != NULL ) { Per_CPU_Control *cpu; cpu = _Timer_Acquire_critical( the_timer, &lock_context ); _Timer_Cancel( cpu, the_timer ); _Watchdog_Initialize( &the_timer->Ticker, adaptor ); the_timer->the_class = the_class; the_timer->routine = routine; the_timer->user_data = user_data; the_timer->initial = interval; the_timer->start_time = _Timer_Get_CPU_ticks( cpu ); if ( _Timer_Is_interval_class( the_class ) ) { _Watchdog_Insert( &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ], &the_timer->Ticker, cpu->Watchdog.ticks + interval ); } else { _Watchdog_Insert( &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ], &the_timer->Ticker, _Watchdog_Realtime_from_seconds( interval ) ); } _Timer_Release( cpu, &lock_context ); return RTEMS_SUCCESSFUL; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_timer_server_fire_after( Objects_Id id, rtems_interval ticks, rtems_timer_service_routine_entry routine, void *user_data ) { Timer_Control *the_timer; Objects_Locations location; ISR_Level level; if ( !_Timer_Server ) return RTEMS_INCORRECT_STATE; if ( !routine ) return RTEMS_INVALID_ADDRESS; if ( ticks == 0 ) return RTEMS_INVALID_NUMBER; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_REMOTE: /* should never return this */ return RTEMS_INTERNAL_ERROR; case OBJECTS_ERROR: return RTEMS_INVALID_ID; case OBJECTS_LOCAL: (void) _Watchdog_Remove( &the_timer->Ticker ); _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; } /* * OK. Now we now the timer was not rescheduled by an interrupt * so we can atomically initialize it as in use. */ the_timer->the_class = TIMER_INTERVAL_ON_TASK; _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); the_timer->Ticker.initial = ticks; _ISR_Enable( level ); _Timer_Server_stop_ticks_timer(); _Timer_Server_process_ticks_chain(); _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker ); _Timer_Server_reset_ticks_timer(); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; } return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */ }