Thread_Control *_Thread_queue_Dequeue_fifo( Thread_queue_Control *the_thread_queue ) { ISR_Level level; Thread_Control *the_thread; _ISR_Disable( level ); if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) { the_thread = (Thread_Control *) _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo ); the_thread->Wait.queue = NULL; if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { _ISR_Enable( level ); _Thread_Unblock( the_thread ); } else { _Watchdog_Deactivate( &the_thread->Timer ); _ISR_Enable( level ); (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) _Thread_MP_Free_proxy( the_thread ); #endif return the_thread; } _ISR_Enable( level ); return NULL; }
/** * @brief Finalize a blocking operation. * * This method is used to finalize a blocking operation that was * satisfied. It may be used with thread queues or any other synchronization * object that uses the blocking states and watchdog times for timeout. * * This method will restore the previous ISR disable level during the cancel * operation. Thus it is an implicit _ISR_Enable(). * * @param[in] the_thread is the thread whose blocking is canceled * @param[in] lock_context is the previous ISR disable level */ static void _Thread_blocking_operation_Finalize( Thread_Control *the_thread, ISR_lock_Context *lock_context ) { /* * The thread is not waiting on anything after this completes. */ the_thread->Wait.queue = NULL; /* * If the sync state is timed out, this is very likely not needed. * But better safe than sorry when it comes to critical sections. */ if ( _Watchdog_Is_active( &the_thread->Timer ) ) { _Watchdog_Deactivate( &the_thread->Timer ); _Thread_queue_Release( lock_context ); (void) _Watchdog_Remove( &the_thread->Timer ); } else _Thread_queue_Release( lock_context ); /* * Global objects with thread queue's should not be operated on from an * ISR. But the sync code still must allow short timeouts to be processed * correctly. */ _Thread_Unblock( the_thread ); #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) _Thread_MP_Free_proxy( the_thread ); #endif }
static void thread_unblock( Thread_Control *thread ) { #if defined( PREVENT_SMP_ASSERT_FAILURES ) _Thread_Disable_dispatch(); #endif _Thread_Unblock( thread ); #if defined( PREVENT_SMP_ASSERT_FAILURES ) _Thread_Unnest_dispatch(); #endif }
void _Event_Timeout( Objects_Id id, void *ignored ) { Thread_Control *the_thread; Objects_Locations location; ISR_Level level; the_thread = _Thread_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: /* * If the event manager is not synchronized, then it is either * "nothing happened", "timeout", or "satisfied". If the_thread * is the executing thread, then it is in the process of blocking * and it is the thread which is responsible for the synchronization * process. * * If it is not satisfied, then it is "nothing happened" and * this is the "timeout" transition. After a request is satisfied, * a timeout is not allowed to occur. */ _ISR_Disable( level ); #if defined(RTEMS_DEBUG) if ( !the_thread->Wait.count ) { /* verify thread is waiting */ _Thread_Unnest_dispatch(); _ISR_Enable( level ); return; } #endif the_thread->Wait.count = 0; if ( _Thread_Is_executing( the_thread ) ) { if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) _Event_Sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT; } the_thread->Wait.return_code = RTEMS_TIMEOUT; _ISR_Enable( level ); _Thread_Unblock( the_thread ); _Thread_Unnest_dispatch(); break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* impossible */ #endif case OBJECTS_ERROR: break; } }
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 ); } }
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; }
void complete_test( void ) { uint32_t index; rtems_id task_id; ISR_lock_Context lock_context; Thread_queue_Context queue_context; benchmark_timer_initialize(); thread_resume( Middle_tcb ); thread_resume_time = benchmark_timer_read(); _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE ); benchmark_timer_initialize(); _Thread_Unblock( Middle_tcb ); thread_unblock_time = benchmark_timer_read(); _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE ); benchmark_timer_initialize(); _Thread_Clear_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE ); thread_ready_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) (void) benchmark_timer_empty_function(); overhead = benchmark_timer_read(); task_id = Middle_tcb->Object.id; benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) { (void) _Thread_Get( task_id, &lock_context ); _ISR_lock_ISR_enable( &lock_context ); } thread_get_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) { (void) _Semaphore_Get( Semaphore_id, &queue_context ); _ISR_lock_ISR_enable( &queue_context.Lock_context ); } semaphore_get_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) { (void) _Thread_Get( 0x3, &lock_context ); _ISR_lock_ISR_enable( &lock_context ); } thread_get_invalid_time = benchmark_timer_read(); /* * This is the running task and we have tricked RTEMS out enough where * we need to set some internal tracking information to match this. */ set_thread_heir( _Thread_Get_executing() ); set_thread_dispatch_necessary( false ); /* * Now dump all the times */ put_time( "rtems interrupt: _ISR_Local_disable", isr_disable_time, 1, 0, 0 ); put_time( "rtems interrupt: _ISR_Local_flash", isr_flash_time, 1, 0, 0 ); put_time( "rtems interrupt: _ISR_Local_enable", isr_enable_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Dispatch_disable", thread_disable_dispatch_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Dispatch_enable", thread_enable_dispatch_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Set_state", thread_set_state_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Dispatch NO FP", thread_dispatch_no_fp_time, 1, 0, 0 ); put_time( "rtems internal: context switch: no floating point contexts", context_switch_no_fp_time, 1, 0, 0 ); put_time( "rtems internal: context switch: self", context_switch_self_time, 1, 0, 0 ); put_time( "rtems internal: context switch to another task", context_switch_another_task_time, 1, 0, 0 ); #if (CPU_HARDWARE_FP == 1) || (CPU_SOFTWARE_FP == 1) put_time( "rtems internal: fp context switch restore 1st FP task", context_switch_restore_1st_fp_time, 1, 0, 0 ); put_time( "rtems internal: fp context switch save idle and restore initialized", context_switch_save_idle_restore_initted_time, 1, 0, 0 ); put_time( "rtems internal: fp context switch save idle, restore idle", context_switch_save_restore_idle_time, 1, 0, 0 ); put_time( "rtems internal: fp context switch save initialized, restore initialized", context_switch_save_restore_initted_time, 1, 0, 0 ); #else puts( "rtems internal: fp context switch restore 1st FP task - NA\n" "rtems internal: fp context switch save idle restore initialized - NA\n" "rtems internal: fp context switch save idle restore idle - NA\n" "rtems internal: fp context switch save initialized\n" " restore initialized - NA" ); #endif put_time( "rtems internal: _Thread_Resume", thread_resume_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Unblock", thread_unblock_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Ready", thread_ready_time, 1, 0, 0 ); put_time( "rtems internal: _Thread_Get", thread_get_time, OPERATION_COUNT, 0, 0 ); put_time( "rtems internal: _Semaphore_Get", semaphore_get_time, OPERATION_COUNT, 0, 0 ); put_time( "rtems internal: _Thread_Get: invalid id", thread_get_invalid_time, OPERATION_COUNT, 0, 0 ); TEST_END(); rtems_test_exit( 0 ); }
void _Event_Surrender( Thread_Control *the_thread ) { ISR_Level level; rtems_event_set pending_events; rtems_event_set event_condition; rtems_event_set seized_events; rtems_option option_set; RTEMS_API_Control *api; api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; option_set = (rtems_option) the_thread->Wait.option; _ISR_Disable( level ); pending_events = api->pending_events; event_condition = (rtems_event_set) the_thread->Wait.count; seized_events = _Event_sets_Get( pending_events, event_condition ); /* * No events were seized in this operation */ if ( _Event_sets_Is_empty( seized_events ) ) { _ISR_Enable( level ); return; } /* * If we are in an ISR and sending to the current thread, then * we have a critical section issue to deal with. */ if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) && ((_Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) || (_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED)) ) { if ( seized_events == event_condition || _Options_Is_any(option_set) ) { api->pending_events = _Event_sets_Clear( pending_events,seized_events ); the_thread->Wait.count = 0; *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; _Event_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED; } _ISR_Enable( level ); return; } /* * Otherwise, this is a normal send to another thread */ if ( _States_Is_waiting_for_event( the_thread->current_state ) ) { if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { api->pending_events = _Event_sets_Clear( pending_events, seized_events ); the_thread->Wait.count = 0; *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; _ISR_Flash( level ); if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { _ISR_Enable( level ); _Thread_Unblock( the_thread ); } else { _Watchdog_Deactivate( &the_thread->Timer ); _ISR_Enable( level ); (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } return; } } _ISR_Enable( level ); }
void _Event_Timeout( Objects_Id id, void *arg ) { Thread_Control *the_thread; Objects_Locations location; ISR_Level level; Thread_blocking_operation_States *sync_state; sync_state = arg; the_thread = _Thread_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: /* * If the event manager is not synchronized, then it is either * "nothing happened", "timeout", or "satisfied". If the_thread * is the executing thread, then it is in the process of blocking * and it is the thread which is responsible for the synchronization * process. * * If it is not satisfied, then it is "nothing happened" and * this is the "timeout" transition. After a request is satisfied, * a timeout is not allowed to occur. */ _ISR_Disable( level ); /* * Verify that the thread is still waiting for the event condition. * This test is necessary to avoid state corruption if the timeout * happens after the event condition is satisfied in * _Event_Surrender(). A satisfied event condition is indicated with * count set to zero. */ if ( !the_thread->Wait.count ) { _ISR_Enable( level ); _Objects_Put_without_thread_dispatch( &the_thread->Object ); return; } the_thread->Wait.count = 0; if ( _Thread_Is_executing( the_thread ) ) { if ( *sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) *sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT; } the_thread->Wait.return_code = RTEMS_TIMEOUT; _ISR_Enable( level ); _Thread_Unblock( the_thread ); _Objects_Put_without_thread_dispatch( &the_thread->Object ); break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* impossible */ #endif case OBJECTS_ERROR: break; } }
/* XXX this routine could probably be cleaned up */ bool _POSIX_signals_Unblock_thread( Thread_Control *the_thread, int signo, siginfo_t *info ) { POSIX_API_Control *api; sigset_t mask; siginfo_t *the_info = NULL; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; mask = signo_to_mask( signo ); /* * Is the thread is specifically waiting for a signal? */ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) { the_thread->Wait.return_code = EINTR; the_info = (siginfo_t *) the_thread->Wait.return_argument; if ( !info ) { the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; } else { *the_info = *info; } _Thread_queue_Extract_with_proxy( the_thread ); return true; } /* * This should only be reached via pthread_kill(). */ return false; } /* * Thread is not waiting due to a sigwait. */ if ( ~api->signals_blocked & mask ) { /* * The thread is interested in this signal. We are going * to post it. We have a few broad cases: * + If it is blocked on an interruptible signal, THEN * we unblock the thread. * + If it is in the ready state AND * we are sending from an ISR AND * it is the interrupted thread AND * it is not blocked, THEN * we need to dispatch at the end of this ISR. * + Any other combination, do nothing. */ the_thread->do_post_task_switch_extension = true; if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) { the_thread->Wait.return_code = EINTR; /* * In pthread_cond_wait, a thread will be blocking on a thread * queue, but is also interruptible by a POSIX signal. */ if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) ) _Thread_queue_Extract_with_proxy( the_thread ); else if ( _States_Is_delaying(the_thread->current_state) ){ (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } } else if ( the_thread->current_state == STATES_READY ) { if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) _ISR_Signals_to_thread_executing = true; } } return false; }
Thread_Control *_Thread_queue_Dequeue_priority( Thread_queue_Control *the_thread_queue ) { uint32_t index; ISR_Level level; Thread_Control *the_thread = NULL; /* just to remove warnings */ Thread_Control *new_first_thread; Chain_Node *head; Chain_Node *tail; Chain_Node *new_first_node; Chain_Node *new_second_node; Chain_Node *last_node; Chain_Node *next_node; Chain_Node *previous_node; _ISR_Disable( level ); for( index=0 ; index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; index++ ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) { the_thread = (Thread_Control *) _Chain_First( &the_thread_queue->Queues.Priority[ index ] ); goto dequeue; } } /* * We did not find a thread to unblock. */ _ISR_Enable( level ); return NULL; dequeue: the_thread->Wait.queue = NULL; new_first_node = _Chain_First( &the_thread->Wait.Block2n ); new_first_thread = (Thread_Control *) new_first_node; next_node = the_thread->Object.Node.next; previous_node = the_thread->Object.Node.previous; if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) { last_node = _Chain_Last( &the_thread->Wait.Block2n ); new_second_node = new_first_node->next; previous_node->next = new_first_node; next_node->previous = new_first_node; new_first_node->next = next_node; new_first_node->previous = previous_node; if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) { /* > two threads on 2-n */ head = _Chain_Head( &new_first_thread->Wait.Block2n ); tail = _Chain_Tail( &new_first_thread->Wait.Block2n ); new_second_node->previous = head; head->next = new_second_node; tail->previous = last_node; last_node->next = tail; } } else { previous_node->next = next_node; next_node->previous = previous_node; } if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { _ISR_Enable( level ); _Thread_Unblock( the_thread ); } else { _Watchdog_Deactivate( &the_thread->Timer ); _ISR_Enable( level ); (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) _Thread_MP_Free_proxy( the_thread ); #endif return( the_thread ); }
void complete_test( void ) { uint32_t index; rtems_id task_id; benchmark_timer_initialize(); _Thread_Resume( Middle_tcb, true ); thread_resume_time = benchmark_timer_read(); _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE ); benchmark_timer_initialize(); _Thread_Unblock( Middle_tcb ); thread_unblock_time = benchmark_timer_read(); _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE ); benchmark_timer_initialize(); _Thread_Ready( Middle_tcb ); thread_ready_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) (void) benchmark_timer_empty_function(); overhead = benchmark_timer_read(); task_id = Middle_tcb->Object.id; benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) (void) _Thread_Get( task_id, &location ); thread_get_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) (void) _Semaphore_Get( Semaphore_id, &location ); semaphore_get_time = benchmark_timer_read(); benchmark_timer_initialize(); for ( index=1 ; index <= OPERATION_COUNT ; index++ ) (void) _Thread_Get( 0x3, &location ); thread_get_invalid_time = benchmark_timer_read(); /* * This is the running task and we have tricked RTEMS out enough where * we need to set some internal tracking information to match this. */ _Thread_Heir = _Thread_Executing; _Context_Switch_necessary = false; _Thread_Dispatch_disable_level = 0; /* * Now dump all the times */ put_time( "_ISR_Disable", isr_disable_time, 1, 0, 0 ); put_time( "_ISR_Flash", isr_flash_time, 1, 0, 0 ); put_time( "_ISR_Enable", isr_enable_time, 1, 0, 0 ); put_time( "_Thread_Disable_dispatch", thread_disable_dispatch_time, 1, 0, 0 ); put_time( "_Thread_Enable_dispatch", thread_enable_dispatch_time, 1, 0, 0 ); put_time( "_Thread_Set_state", thread_set_state_time, 1, 0, 0 ); put_time( "_Thread_Dispatch (NO FP)", thread_dispatch_no_fp_time, 1, 0, 0 ); put_time( "context switch: no floating point contexts", context_switch_no_fp_time, 1, 0, 0 ); put_time( "context switch: self", context_switch_self_time, 1, 0, 0 ); put_time( "context switch: to another task", context_switch_another_task_time, 1, 0, 0 ); #if (CPU_HARDWARE_FP == 1) || (CPU_SOFTWARE_FP == 1) put_time( "fp context switch: restore 1st FP task", context_switch_restore_1st_fp_time, 1, 0, 0 ); put_time( "fp context switch: save idle, restore initialized", context_switch_save_idle_restore_initted_time, 1, 0, 0 ); put_time( "fp context switch: save idle, restore idle", context_switch_save_restore_idle_time, 1, 0, 0 ); put_time( "fp context switch: save initialized, restore initialized", context_switch_save_restore_initted_time, 1, 0, 0 ); #else puts( "fp context switch: restore 1st FP task - NA" ); puts( "fp context switch: save idle, restore initialized - NA" ); puts( "fp context switch: save idle, restore idle - NA" ); puts( "fp context switch: save initialized, restore initialized - NA" ); #endif put_time( "_Thread_Resume", thread_resume_time, 1, 0, 0 ); put_time( "_Thread_Unblock", thread_unblock_time, 1, 0, 0 ); put_time( "_Thread_Ready", thread_ready_time, 1, 0, 0 ); put_time( "_Thread_Get", thread_get_time, OPERATION_COUNT, 0, 0 ); put_time( "_Semaphore_Get", semaphore_get_time, OPERATION_COUNT, 0, 0 ); put_time( "_Thread_Get: invalid id", thread_get_invalid_time, OPERATION_COUNT, 0, 0 ); puts( "*** END OF TEST 26 ***" ); rtems_test_exit( 0 ); }
static int _Condition_Wake( struct _Condition_Control *_condition, int count ) { Condition_Control *condition; ISR_lock_Context lock_context; Thread_queue_Heads *heads; Chain_Control unblock; Chain_Node *node; Chain_Node *tail; int woken; condition = _Condition_Get( _condition ); _ISR_lock_ISR_disable( &lock_context ); _Condition_Queue_acquire_critical( condition, &lock_context ); /* * In common uses cases of condition variables there are normally no threads * on the queue, so check this condition early. */ heads = condition->Queue.Queue.heads; if ( __predict_true( heads == NULL ) ) { _Condition_Queue_release( condition, &lock_context ); return 0; } woken = 0; _Chain_Initialize_empty( &unblock ); while ( count > 0 && heads != NULL ) { const Thread_queue_Operations *operations; Thread_Control *first; bool do_unblock; operations = CONDITION_TQ_OPERATIONS; first = ( *operations->first )( heads ); do_unblock = _Thread_queue_Extract_locked( &condition->Queue.Queue, operations, first ); if (do_unblock) { _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain ); } ++woken; --count; heads = condition->Queue.Queue.heads; } node = _Chain_First( &unblock ); tail = _Chain_Tail( &unblock ); if ( node != tail ) { Per_CPU_Control *cpu_self; cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); _Condition_Queue_release( condition, &lock_context ); do { Thread_Control *thread; Chain_Node *next; next = _Chain_Next( node ); thread = THREAD_CHAIN_NODE_TO_THREAD( node ); _Watchdog_Remove_ticks( &thread->Timer ); _Thread_Unblock( thread ); node = next; } while ( node != tail ); _Thread_Dispatch_enable( cpu_self ); } else { _Condition_Queue_release( condition, &lock_context ); } return woken; }
/* XXX this routine could probably be cleaned up */ boolean _POSIX_signals_Unblock_thread( Thread_Control *the_thread, int signo, siginfo_t *info ) { POSIX_API_Control *api; sigset_t mask; siginfo_t *the_info = NULL; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; mask = signo_to_mask( signo ); /* * Is the thread is specifically waiting for a signal? */ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) { the_thread->Wait.return_code = EINTR; the_info = (siginfo_t *) the_thread->Wait.return_argument; if ( !info ) { the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; } else { *the_info = *info; } _Thread_queue_Extract_with_proxy( the_thread ); return TRUE; } /* * This should only be reached via pthread_kill(). */ return FALSE; } if ( ~api->signals_blocked & mask ) { the_thread->do_post_task_switch_extension = TRUE; if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { the_thread->Wait.return_code = EINTR; if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) ) _Thread_queue_Extract_with_proxy( the_thread ); else if ( _States_Is_delaying(the_thread->current_state)){ if ( _Watchdog_Is_active( &the_thread->Timer ) ) (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } } } return FALSE; }
void _Event_Seize( rtems_event_set event_in, rtems_option option_set, rtems_interval ticks, rtems_event_set *event_out ) { Thread_Control *executing; rtems_event_set seized_events; rtems_event_set pending_events; ISR_Level level; RTEMS_API_Control *api; Event_Sync_states sync_state; executing = _Thread_Executing; executing->Wait.return_code = RTEMS_SUCCESSFUL; api = executing->API_Extensions[ THREAD_API_RTEMS ]; _ISR_Disable( level ); pending_events = api->pending_events; seized_events = _Event_sets_Get( pending_events, event_in ); if ( !_Event_sets_Is_empty( seized_events ) && (seized_events == event_in || _Options_Is_any( option_set )) ) { api->pending_events = _Event_sets_Clear( pending_events, seized_events ); _ISR_Enable( level ); *event_out = seized_events; return; } if ( _Options_Is_no_wait( option_set ) ) { _ISR_Enable( level ); executing->Wait.return_code = RTEMS_UNSATISFIED; *event_out = seized_events; return; } _Event_Sync_state = EVENT_SYNC_NOTHING_HAPPENED; executing->Wait.option = (uint32_t ) option_set; executing->Wait.count = (uint32_t ) event_in; executing->Wait.return_argument = event_out; _ISR_Enable( level ); if ( ticks ) { _Watchdog_Initialize( &executing->Timer, _Event_Timeout, executing->Object.id, NULL ); _Watchdog_Insert_ticks( &executing->Timer, ticks ); } _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT ); _ISR_Disable( level ); sync_state = _Event_Sync_state; _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED; switch ( sync_state ) { case EVENT_SYNC_SYNCHRONIZED: /* * This cannot happen. It indicates that this routine did not * enter the synchronization states above. */ return; case EVENT_SYNC_NOTHING_HAPPENED: _ISR_Enable( level ); return; case EVENT_SYNC_TIMEOUT: executing->Wait.return_code = RTEMS_TIMEOUT; _ISR_Enable( level ); _Thread_Unblock( executing ); return; case EVENT_SYNC_SATISFIED: if ( _Watchdog_Is_active( &executing->Timer ) ) { _Watchdog_Deactivate( &executing->Timer ); _ISR_Enable( level ); (void) _Watchdog_Remove( &executing->Timer ); } else _ISR_Enable( level ); _Thread_Unblock( executing ); return; } }