static void release_semaphore(rtems_id timer, void *arg) { /* The arg is NULL */ test_context *ctx = &ctx_instance; rtems_status_code sc; if ( _Thread_Wait_flags_get(ctx->main_task_control) == (THREAD_WAIT_CLASS_OBJECT | THREAD_WAIT_STATE_INTEND_TO_BLOCK) ) { CORE_semaphore_Control *sem; ctx->done = true; sc = rtems_semaphore_release(ctx->semaphore_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert( _Thread_Wait_flags_get(ctx->main_task_control) == (THREAD_WAIT_CLASS_OBJECT | THREAD_WAIT_STATE_READY_AGAIN) ); sem = &ctx->semaphore_control->Core_control.Semaphore; rtems_test_assert(sem->count == 0); } else { sc = rtems_semaphore_release(ctx->semaphore_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } }
static void any_satisfy_before_timeout(rtems_id timer, void *arg) { rtems_status_code sc; test_context *ctx = arg; Thread_Control *thread = ctx->thread; Thread_Wait_flags flags = _Thread_Wait_flags_get(thread); if (blocks_for_event(flags)) { ctx->hit = interrupts_blocking_op(flags); rtems_test_assert( *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF ); rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); sc = rtems_event_send(thread->Object.id, GREEN); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert( *(rtems_event_set *) thread->Wait.return_argument == GREEN ); rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); sc = rtems_event_send(thread->Object.id, RED); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert( *(rtems_event_set *) thread->Wait.return_argument == GREEN ); rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); _Thread_Timeout(&thread->Timer.Watchdog); rtems_test_assert( *(rtems_event_set *) thread->Wait.return_argument == GREEN ); rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); if (ctx->hit) { rtems_test_assert( _Thread_Wait_flags_get(thread) == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_READY_AGAIN) ); } rtems_test_assert(thread->Wait.count == EVENTS); } sc = rtems_timer_reset(timer); rtems_test_assert(sc == RTEMS_SUCCESSFUL); }
static bool interrupts_blocking_op(void) { Thread_Wait_flags flags = _Thread_Wait_flags_get( thread ); return flags == ( THREAD_WAIT_CLASS_OBJECT | THREAD_WAIT_STATE_INTEND_TO_BLOCK ); }
static bool _Thread_queue_Make_ready_again( Thread_Control *the_thread ) { bool success; bool unblock; /* * We must update the wait flags under protection of the current thread lock, * otherwise a _Thread_Timeout() running on another processor may interfere. */ success = _Thread_Wait_flags_try_change_release( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK, THREAD_QUEUE_READY_AGAIN ); if ( success ) { unblock = false; } else { _Assert( _Thread_Wait_flags_get( the_thread ) == THREAD_QUEUE_BLOCKED ); _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_READY_AGAIN ); unblock = true; } _Thread_Wait_restore_default( the_thread ); return unblock; }
void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog ) { Rate_monotonic_Control *the_period; Thread_Control *owner; ISR_lock_Context lock_context; Thread_Wait_flags wait_flags; the_period = RTEMS_CONTAINER_OF( the_watchdog, Rate_monotonic_Control, Timer ); owner = the_period->owner; _ISR_lock_ISR_disable( &lock_context ); _Rate_monotonic_Acquire_critical( the_period, &lock_context ); wait_flags = _Thread_Wait_flags_get( owner ); if ( ( wait_flags & THREAD_WAIT_CLASS_PERIOD ) != 0 && owner->Wait.return_argument == the_period ) { bool unblock; bool success; owner->Wait.return_argument = NULL; success = _Thread_Wait_flags_try_change_release( owner, RATE_MONOTONIC_INTEND_TO_BLOCK, RATE_MONOTONIC_READY_AGAIN ); if ( success ) { unblock = false; } else { _Assert( _Thread_Wait_flags_get( owner ) == RATE_MONOTONIC_BLOCKED ); _Thread_Wait_flags_set( owner, RATE_MONOTONIC_READY_AGAIN ); unblock = true; } _Rate_monotonic_Restart( the_period, owner, &lock_context ); if ( unblock ) { _Thread_Unblock( owner ); } } else { _Rate_monotonic_Renew_deadline( the_period, &lock_context ); } }
bool _Thread_queue_Do_extract_locked( Thread_queue_Queue *queue, const Thread_queue_Operations *operations, Thread_Control *the_thread #if defined(RTEMS_MULTIPROCESSING) , const Thread_queue_Context *queue_context #endif ) { bool success; bool unblock; #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) { Thread_Proxy_control *the_proxy; Thread_queue_MP_callout mp_callout; the_proxy = (Thread_Proxy_control *) the_thread; mp_callout = queue_context->mp_callout; _Assert( mp_callout != NULL ); the_proxy->thread_queue_callout = queue_context->mp_callout; } #endif ( *operations->extract )( queue, the_thread ); /* * We must update the wait flags under protection of the current thread lock, * otherwise a _Thread_Timeout() running on another processor may interfere. */ success = _Thread_Wait_flags_try_change_release( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK, THREAD_QUEUE_READY_AGAIN ); if ( success ) { unblock = false; } else { _Assert( _Thread_Wait_flags_get( the_thread ) == THREAD_QUEUE_BLOCKED ); _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_READY_AGAIN ); unblock = true; } _Thread_Wait_restore_default( the_thread ); return unblock; }
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; }
static bool is_case_hit( void ) { return _Thread_Wait_flags_get( main_thread) == ( THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK ); }
static bool is_interrupt_timeout(void) { Thread_Wait_flags flags = _Thread_Wait_flags_get( thread ); return flags == ( THREAD_WAIT_CLASS_OBJECT | THREAD_WAIT_STATE_READY_AGAIN ); }
static void _POSIX_signals_Action_handler( Thread_Control *executing, Thread_Action *action, ISR_lock_Context *lock_context ) { POSIX_API_Control *api; int signo; uint32_t hold_errno; (void) action; _Thread_State_release( executing, lock_context ); api = executing->API_Extensions[ THREAD_API_POSIX ]; /* * We need to ensure that if the signal handler executes a call * which overwrites the unblocking status, we restore it. */ hold_errno = executing->Wait.return_code; /* * api may be NULL in case of a thread close in progress */ if ( !api ) return; /* * In case the executing thread is blocked or about to block on something * that uses the thread wait information, then this is a kernel bug. */ _Assert( ( _Thread_Wait_flags_get( executing ) & ( THREAD_WAIT_STATE_BLOCKED | THREAD_WAIT_STATE_INTEND_TO_BLOCK ) ) == 0 ); /* * If we invoke any user code, there is the possibility that * a new signal has been posted that we should process so we * restart the loop if a signal handler was invoked. * * The first thing done is to check there are any signals to be * processed at all. No point in doing this loop otherwise. */ while (1) { Thread_queue_Context queue_context; _Thread_queue_Context_initialize( &queue_context ); _POSIX_signals_Acquire( &queue_context ); if ( !(api->signals_unblocked & (api->signals_pending | _POSIX_signals_Pending)) ) { _POSIX_signals_Release( &queue_context ); break; } _POSIX_signals_Release( &queue_context ); for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } } executing->Wait.return_code = hold_errno; }