rtems_status_code rtems_rate_monotonic_cancel( rtems_id id ) { Rate_monotonic_Control *the_period; Objects_Locations location; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( !_Thread_Is_executing( the_period->owner ) ) { _Thread_Enable_dispatch(); return RTEMS_NOT_OWNER_OF_RESOURCE; } (void) _Watchdog_Remove( &the_period->Timer ); the_period->state = RATE_MONOTONIC_INACTIVE; _Scheduler_Release_job(the_period->owner, 0); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_rate_monotonic_delete( rtems_id id ) { Rate_monotonic_Control *the_period; Objects_Locations location; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Objects_Close( &_Rate_monotonic_Information, &the_period->Object ); (void) _Watchdog_Remove( &the_period->Timer ); the_period->state = RATE_MONOTONIC_INACTIVE; _Rate_monotonic_Free( the_period ); _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_rate_monotonic_reset_statistics( rtems_id id ) { Rate_monotonic_Control *the_period; ISR_lock_Context lock_context; Thread_Control *owner; the_period = _Rate_monotonic_Get( id, &lock_context ); if ( the_period == NULL ) { return RTEMS_INVALID_ID; } owner = the_period->owner; _Rate_monotonic_Acquire_critical( owner, &lock_context ); _Rate_monotonic_Reset_statistics( the_period ); _Rate_monotonic_Release( owner, &lock_context ); return RTEMS_SUCCESSFUL; }
rtems_status_code rtems_rate_monotonic_cancel( rtems_id id ) { Rate_monotonic_Control *the_period; ISR_lock_Context lock_context; Thread_Control *executing; the_period = _Rate_monotonic_Get( id, &lock_context ); if ( the_period == NULL ) { return RTEMS_INVALID_ID; } executing = _Thread_Executing; if ( executing != the_period->owner ) { _ISR_lock_ISR_enable( &lock_context ); return RTEMS_NOT_OWNER_OF_RESOURCE; } _Rate_monotonic_Cancel( the_period, executing, &lock_context ); return RTEMS_SUCCESSFUL; }
rtems_status_code rtems_rate_monotonic_reset_statistics( rtems_id id ) { Objects_Locations location; Rate_monotonic_Control *the_period; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Rate_monotonic_Reset_statistics( the_period ); _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_rate_monotonic_get_status( rtems_id id, rtems_rate_monotonic_period_status *status ) { Timestamp_Control executed; Objects_Locations location; Rate_monotonic_Period_time_t since_last_period; Rate_monotonic_Control *the_period; bool valid_status; if ( !status ) return RTEMS_INVALID_ADDRESS; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: status->owner = the_period->owner->Object.id; status->state = the_period->state; /* * If the period is inactive, there is no information. */ if ( status->state == RATE_MONOTONIC_INACTIVE ) { _Timespec_Set_to_zero( &status->since_last_period ); _Timespec_Set_to_zero( &status->executed_since_last_period ); } else { /* * Grab the current status. */ valid_status = _Rate_monotonic_Get_status( the_period, &since_last_period, &executed ); if (!valid_status) { _Objects_Put( &the_period->Object ); return RTEMS_NOT_DEFINED; } _Timestamp_To_timespec( &since_last_period, &status->since_last_period ); _Timestamp_To_timespec( &executed, &status->executed_since_last_period ); } _Objects_Put( &the_period->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_rate_monotonic_period( rtems_id id, rtems_interval length ) { Rate_monotonic_Control *the_period; ISR_lock_Context lock_context; Thread_Control *executing; rtems_status_code status; rtems_rate_monotonic_period_states state; the_period = _Rate_monotonic_Get( id, &lock_context ); if ( the_period == NULL ) { return RTEMS_INVALID_ID; } executing = _Thread_Executing; if ( executing != the_period->owner ) { _ISR_lock_ISR_enable( &lock_context ); return RTEMS_NOT_OWNER_OF_RESOURCE; } _Rate_monotonic_Acquire_critical( the_period, &lock_context ); state = the_period->state; if ( length == RTEMS_PERIOD_STATUS ) { status = _Rate_monotonic_Get_status_for_state( state ); _Rate_monotonic_Release( the_period, &lock_context ); } else { switch ( state ) { case RATE_MONOTONIC_ACTIVE: if( the_period->postponed_jobs > 0 ){ /* * If the number of postponed jobs is not 0, it means the * previous postponed instance is finished without exceeding * the current period deadline. * * Do nothing on the watchdog deadline assignment but release the * next remaining postponed job. */ status = _Rate_monotonic_Block_while_expired( the_period, length, executing, &lock_context ); }else{ /* * Normal case that no postponed jobs and no expiration, so wait for * the period and update the deadline of watchdog accordingly. */ status = _Rate_monotonic_Block_while_active( the_period, length, executing, &lock_context ); } break; case RATE_MONOTONIC_INACTIVE: status = _Rate_monotonic_Activate( the_period, length, executing, &lock_context ); break; default: /* * As now this period was already TIMEOUT, there must be at least one * postponed job recorded by the watchdog. The one which exceeded * the previous deadlines was just finished. * * Maybe there is more than one job postponed due to the preemption or * the previous finished job. */ _Assert( state == RATE_MONOTONIC_EXPIRED ); status = _Rate_monotonic_Block_while_expired( the_period, length, executing, &lock_context ); break; } } return status; }
rtems_status_code rtems_rate_monotonic_period( rtems_id id, rtems_interval length ) { Rate_monotonic_Control *the_period; ISR_lock_Context lock_context; Thread_Control *executing; rtems_status_code status; rtems_rate_monotonic_period_states state; the_period = _Rate_monotonic_Get( id, &lock_context ); if ( the_period == NULL ) { return RTEMS_INVALID_ID; } executing = _Thread_Executing; if ( executing != the_period->owner ) { _ISR_lock_ISR_enable( &lock_context ); return RTEMS_NOT_OWNER_OF_RESOURCE; } _Rate_monotonic_Acquire_critical( the_period, &lock_context ); state = the_period->state; if ( length == RTEMS_PERIOD_STATUS ) { status = _Rate_monotonic_Get_status_for_state( state ); _Rate_monotonic_Release( the_period, &lock_context ); } else { switch ( state ) { case RATE_MONOTONIC_ACTIVE: status = _Rate_monotonic_Block_while_active( the_period, length, executing, &lock_context ); break; case RATE_MONOTONIC_INACTIVE: status = _Rate_monotonic_Activate( the_period, length, executing, &lock_context ); break; default: _Assert( state == RATE_MONOTONIC_EXPIRED ); status = _Rate_monotonic_Block_while_expired( the_period, length, executing, &lock_context ); break; } } return status; }
rtems_status_code rtems_rate_monotonic_period( rtems_id id, rtems_interval length ) { Rate_monotonic_Control *the_period; Objects_Locations location; rtems_status_code return_value; rtems_rate_monotonic_period_states local_state; ISR_Level level; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( !_Thread_Is_executing( the_period->owner ) ) { _Thread_Enable_dispatch(); return RTEMS_NOT_OWNER_OF_RESOURCE; } if ( length == RTEMS_PERIOD_STATUS ) { switch ( the_period->state ) { case RATE_MONOTONIC_INACTIVE: return_value = RTEMS_NOT_DEFINED; break; case RATE_MONOTONIC_EXPIRED: case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: return_value = RTEMS_TIMEOUT; break; case RATE_MONOTONIC_ACTIVE: default: /* unreached -- only to remove warnings */ return_value = RTEMS_SUCCESSFUL; break; } _Thread_Enable_dispatch(); return( return_value ); } _ISR_Disable( level ); if ( the_period->state == RATE_MONOTONIC_INACTIVE ) { _ISR_Enable( level ); the_period->next_length = length; /* * Baseline statistics information for the beginning of a period. */ _Rate_monotonic_Initiate_statistics( the_period ); the_period->state = RATE_MONOTONIC_ACTIVE; _Watchdog_Initialize( &the_period->Timer, _Rate_monotonic_Timeout, id, NULL ); _Watchdog_Insert_ticks( &the_period->Timer, length ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; } if ( the_period->state == RATE_MONOTONIC_ACTIVE ) { /* * Update statistics from the concluding period. */ _Rate_monotonic_Update_statistics( the_period ); /* * This tells the _Rate_monotonic_Timeout that this task is * in the process of blocking on the period and that we * may be changing the length of the next period. */ the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING; the_period->next_length = length; _ISR_Enable( level ); _Thread_Executing->Wait.id = the_period->Object.id; _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); /* * Did the watchdog timer expire while we were actually blocking * on it? */ _ISR_Disable( level ); local_state = the_period->state; the_period->state = RATE_MONOTONIC_ACTIVE; _ISR_Enable( level ); /* * If it did, then we want to unblock ourself and continue as * if nothing happen. The period was reset in the timeout routine. */ if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; } if ( the_period->state == RATE_MONOTONIC_EXPIRED ) { /* * Update statistics from the concluding period */ _Rate_monotonic_Update_statistics( the_period ); _ISR_Enable( level ); the_period->state = RATE_MONOTONIC_ACTIVE; the_period->next_length = length; _Watchdog_Insert_ticks( &the_period->Timer, length ); _Scheduler_Release_job(the_period->owner, the_period->next_length); _Thread_Enable_dispatch(); return RTEMS_TIMEOUT; } /* * These should never happen so just return invalid Id. * - RATE_MONOTONIC_OWNER_IS_BLOCKING: * - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: */ #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }