/* * There are two possible cases: one is that the previous deadline is missed, * The other is that the number of postponed jobs is not 0, but the current * deadline is still not expired, i.e., state = RATE_MONOTONIC_ACTIVE. */ static rtems_status_code _Rate_monotonic_Block_while_expired( Rate_monotonic_Control *the_period, rtems_interval length, Thread_Control *executing, ISR_lock_Context *lock_context ) { /* * No matter the just finished jobs in time or not, * they are actually missing their deadlines already. */ the_period->state = RATE_MONOTONIC_EXPIRED; /* * Update statistics from the concluding period */ _Rate_monotonic_Update_statistics( the_period ); the_period->state = RATE_MONOTONIC_ACTIVE; the_period->next_length = length; _Rate_monotonic_Release_postponed_job( the_period, executing, length, lock_context ); return RTEMS_TIMEOUT; }
static rtems_status_code _Rate_monotonic_Block_while_expired( Rate_monotonic_Control *the_period, rtems_interval length, Thread_Control *executing, ISR_lock_Context *lock_context ) { /* * Update statistics from the concluding period */ _Rate_monotonic_Update_statistics( the_period ); the_period->state = RATE_MONOTONIC_ACTIVE; the_period->next_length = length; _Rate_monotonic_Release_job( the_period, executing, length, lock_context ); return RTEMS_TIMEOUT; }
static rtems_status_code _Rate_monotonic_Block_while_active( Rate_monotonic_Control *the_period, rtems_interval length, Thread_Control *executing, ISR_lock_Context *lock_context ) { Per_CPU_Control *cpu_self; bool success; /* * 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->next_length = length; executing->Wait.return_argument = the_period; _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK ); cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Rate_monotonic_Release( the_period, lock_context ); _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD ); success = _Thread_Wait_flags_try_change_acquire( executing, RATE_MONOTONIC_INTEND_TO_BLOCK, RATE_MONOTONIC_BLOCKED ); if ( !success ) { _Assert( _Thread_Wait_flags_get( executing ) == RATE_MONOTONIC_READY_AGAIN ); _Thread_Unblock( executing ); } _Thread_Dispatch_enable( cpu_self ); return RTEMS_SUCCESSFUL; }
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; }