Thread_blocking_operation_States _Thread_queue_Enqueue_fifo ( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread, ISR_Level *level_p ) { Thread_blocking_operation_States sync_state; ISR_Level level; _ISR_Disable( level ); sync_state = the_thread_queue->sync_state; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) { _Chain_Append_unprotected( &the_thread_queue->Queues.Fifo, &the_thread->Object.Node ); the_thread->Wait.queue = the_thread_queue; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; } /* * An interrupt completed the thread's blocking request. * For example, the blocking thread could have been given * the mutex by an ISR or timed out. * * WARNING! Returning with interrupts disabled! */ *level_p = level; return sync_state; }
static void _Thread_Make_zombie( Thread_Control *the_thread ) { ISR_lock_Context lock_context; Thread_Zombie_control *zombies = &_Thread_Zombies; if ( _Thread_Owns_resources( the_thread ) ) { _Terminate( INTERNAL_ERROR_CORE, false, INTERNAL_ERROR_RESOURCE_IN_USE ); } _Objects_Close( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); _Thread_Set_state( the_thread, STATES_ZOMBIE ); _Thread_queue_Extract_with_proxy( the_thread ); _Watchdog_Remove_ticks( &the_thread->Timer ); _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); _Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node ); _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context ); }
static void _Thread_queue_Priority_do_enqueue( Thread_queue_Heads *heads, Thread_Control *the_thread ) { Thread_queue_Priority_queue *priority_queue; Scheduler_Node *scheduler_node; Priority_Control current_priority; priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); #if defined(RTEMS_SMP) if ( _RBTree_Is_empty( &priority_queue->Queue ) ) { _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node ); } #endif scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); current_priority = _Thread_Get_priority( the_thread ); _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree ); _RBTree_Insert_inline( &priority_queue->Queue, &scheduler_node->Wait.Node.RBTree, ¤t_priority, _Thread_queue_Priority_less ); }
void _Scheduler_priority_Yield(void) { Scheduler_priority_Per_thread *sched_info; ISR_Level level; Thread_Control *executing; Chain_Control *ready; executing = _Thread_Executing; sched_info = (Scheduler_priority_Per_thread *) executing->scheduler_info; ready = sched_info->ready_chain; _ISR_Disable( level ); if ( !_Chain_Has_only_one_node( ready ) ) { _Chain_Extract_unprotected( &executing->Object.Node ); _Chain_Append_unprotected( ready, &executing->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( executing ) ) _Thread_Heir = (Thread_Control *) _Chain_First( ready ); _Thread_Dispatch_necessary = true; } else if ( !_Thread_Is_heir( executing ) ) _Thread_Dispatch_necessary = true; _ISR_Enable( level ); }
void _Thread_Reset_timeslice( void ) { ISR_Level level; Thread_Control *executing; Chain_Control *ready; executing = _Thread_Executing; ready = executing->ready; _ISR_Disable( level ); if ( _Chain_Has_only_one_node( ready ) ) { _ISR_Enable( level ); return; } _Chain_Extract_unprotected( &executing->Object.Node ); _Chain_Append_unprotected( ready, &executing->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( executing ) ) _Thread_Heir = (Thread_Control *) ready->first; _Context_Switch_necessary = true; _ISR_Enable( level ); }
void _Chain_Append( Chain_Control *the_chain, Chain_Node *node ) { _Chain_Append_unprotected( the_chain, node ); }
boolean _POSIX_signals_Clear_signals( POSIX_API_Control *api, int signo, siginfo_t *info, boolean is_global, boolean check_blocked ) { sigset_t mask; sigset_t signals_blocked; ISR_Level level; boolean do_callout; POSIX_signals_Siginfo_node *psiginfo; mask = signo_to_mask( signo ); do_callout = FALSE; /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK * insures that no signals are blocked and all are checked. */ if ( check_blocked ) signals_blocked = ~api->signals_blocked; else signals_blocked = SIGNAL_ALL_MASK; /* XXX this is not right for siginfo type signals yet */ /* XXX since they can't be cleared the same way */ _ISR_Disable( level ); if ( is_global ) { if ( mask & (_POSIX_signals_Pending & signals_blocked) ) { if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { psiginfo = (POSIX_signals_Siginfo_node *) _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] ); if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) ) _POSIX_signals_Clear_process_signals( mask ); if ( psiginfo ) { *info = psiginfo->Info; _Chain_Append_unprotected( &_POSIX_signals_Inactive_siginfo, &psiginfo->Node ); } else do_callout = FALSE; } else _POSIX_signals_Clear_process_signals( mask ); do_callout = TRUE; } } else { if ( mask & (api->signals_pending & signals_blocked) ) { api->signals_pending &= ~mask; do_callout = TRUE; } } _ISR_Enable( level ); return do_callout; }
void _Watchdog_Insert_locked( Watchdog_Header *header, Watchdog_Control *the_watchdog, ISR_lock_Context *lock_context ) { if ( the_watchdog->state == WATCHDOG_INACTIVE ) { Watchdog_Iterator iterator; Chain_Node *current; Chain_Node *next; Watchdog_Interval delta; the_watchdog->state = WATCHDOG_BEING_INSERTED; _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); delta = the_watchdog->initial; current = _Chain_Head( &header->Watchdogs ); while ( ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) ) { Watchdog_Control *next_watchdog; Watchdog_Interval delta_next; next_watchdog = (Watchdog_Control *) next; delta_next = next_watchdog->delta_interval; if ( delta < delta_next ) { _Watchdog_Insert_fixup( header, next_watchdog, delta ); break; } iterator.delta_interval = delta - delta_next; iterator.current = next; _Watchdog_Flash( header, lock_context ); if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { goto abort_insert; } delta = iterator.delta_interval; current = iterator.current; } the_watchdog->delta_interval = delta; the_watchdog->start_time = _Watchdog_Ticks_since_boot; _Watchdog_Activate( the_watchdog ); _Chain_Insert_unprotected( current, &the_watchdog->Node ); abort_insert: _Chain_Extract_unprotected( &iterator.Node ); } }
static void _Thread_Add_to_zombie_chain( Thread_Control *the_thread ) { ISR_lock_Context lock_context; Thread_Zombie_control *zombies; zombies = &_Thread_Zombies; _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); _Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node ); _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context ); }
static void _Thread_queue_FIFO_do_enqueue( Thread_queue_Heads *heads, Thread_Control *the_thread ) { _Chain_Append_unprotected( &heads->Heads.Fifo, &the_thread->Wait.Node.Chain ); }
void rtems_chain_append( rtems_chain_control *chain, rtems_chain_node *node ) { ISR_Level level; _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level ); _Chain_Append_unprotected( &chain->Chain, node ); _ISR_lock_Release_and_ISR_enable( &chain->Lock, level ); }
void rtems_chain_append( rtems_chain_control *chain, rtems_chain_node *node ) { rtems_interrupt_lock_context lock_context; chain_acquire( &lock_context ); _Chain_Append_unprotected( chain, node ); chain_release( &lock_context ); }
void _Chain_Append( Chain_Control *the_chain, Chain_Node *node ) { ISR_Level level; _ISR_Disable( level ); _Chain_Append_unprotected( the_chain, node ); _ISR_Enable( level ); }
void _Scheduler_simple_smp_Start_idle( Thread_Control *thread, Per_CPU_Control *cpu ) { Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance(); thread->is_scheduled = true; thread->cpu = cpu; _Chain_Append_unprotected( &self->scheduled, &thread->Object.Node ); }
static void _Thread_queue_FIFO_do_enqueue( Thread_queue_Heads *heads, Thread_Control *the_thread ) { Scheduler_Node *scheduler_node; scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain ); _Chain_Append_unprotected( &heads->Heads.Fifo, &scheduler_node->Wait.Node.Chain ); }
void _Scheduler_SMP_Start_idle( const Scheduler_Control *scheduler, Thread_Control *thread, Per_CPU_Control *cpu ) { Scheduler_Context *context = _Scheduler_Get_context( scheduler ); Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context ); Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); node->state = SCHEDULER_SMP_NODE_SCHEDULED; _Thread_Set_CPU( thread, cpu ); _Chain_Append_unprotected( &self->Scheduled, &thread->Object.Node ); }
void _Thread_Resume( Thread_Control *the_thread, bool force ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); #if defined(RTEMS_ITRON_API) if ( force == true ) the_thread->suspend_count = 0; else the_thread->suspend_count--; if ( the_thread->suspend_count > 0 ) { _ISR_Enable( level ); return; } #endif current_state = the_thread->current_state; if ( current_state & STATES_SUSPENDED ) { current_state = the_thread->current_state = _States_Clear(STATES_SUSPENDED, current_state); if ( _States_Is_ready( current_state ) ) { _Priority_Add_to_bit_map( &the_thread->Priority_map ); _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node); _ISR_Flash( level ); if ( the_thread->current_priority < _Thread_Heir->current_priority ) { _Thread_Heir = the_thread; if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 ) _Context_Switch_necessary = true; } } } _ISR_Enable( level ); }
void _Thread_MP_Free_proxy( Thread_Control *the_thread ) { Thread_Proxy_control *the_proxy; ISR_lock_Context lock_context; the_proxy = (Thread_Proxy_control *) the_thread; _Thread_MP_Proxies_acquire( &lock_context ); _RBTree_Extract( &_Thread_MP_Active_proxies, &the_proxy->Active ); _Chain_Append_unprotected( &_Thread_MP_Inactive_proxies, &the_proxy->Object.Node ); _Thread_MP_Proxies_release( &lock_context ); }
void _Thread_Clear_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); current_state = the_thread->current_state; if ( current_state & state ) { current_state = the_thread->current_state = _States_Clear( state, current_state ); if ( _States_Is_ready( current_state ) ) { _Priority_Add_to_bit_map( &the_thread->Priority_map ); _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node); _ISR_Flash( level ); /* * If the thread that was unblocked is more important than the heir, * then we have a new heir. This may or may not result in a * context switch. * * Normal case: * If the current thread is preemptible, then we need to do * a context switch. * Pseudo-ISR case: * Even if the thread isn't preemptible, if the new heir is * a pseudo-ISR system task, we need to do a context switch. */ if ( the_thread->current_priority < _Thread_Heir->current_priority ) { _Thread_Heir = the_thread; if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 ) _Context_Switch_necessary = true; } } } _ISR_Enable( level ); }
void _CORE_message_queue_Insert_message( CORE_message_queue_Control *the_message_queue, CORE_message_queue_Buffer_control *the_message, CORE_message_queue_Submit_types submit_type ) { Chain_Control *pending_messages; #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION) bool notify; #endif _CORE_message_queue_Set_message_priority( the_message, submit_type ); pending_messages = &the_message_queue->Pending_messages; #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION) notify = ( the_message_queue->number_of_pending_messages == 0 ); #endif ++the_message_queue->number_of_pending_messages; if ( submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST ) { _Chain_Append_unprotected( pending_messages, &the_message->Node ); #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY) } else if ( submit_type != CORE_MESSAGE_QUEUE_URGENT_REQUEST ) { _Chain_Insert_ordered_unprotected( pending_messages, &the_message->Node, _CORE_message_queue_Order ); #endif } else { _Chain_Prepend_unprotected( pending_messages, &the_message->Node ); } #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION) /* * According to POSIX, does this happen before or after the message * is actually enqueued. It is logical to think afterwards, because * the message is actually in the queue at this point. */ if ( notify && the_message_queue->notify_handler ) (*the_message_queue->notify_handler)(the_message_queue->notify_argument); #endif }
static void _Thread_queue_Priority_do_extract( Thread_queue_Heads *heads, Thread_Control *the_thread ) { Thread_queue_Priority_queue *priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); _RBTree_Extract( &priority_queue->Queue, &the_thread->Wait.Node.RBTree ); #if defined(RTEMS_SMP) _Chain_Extract_unprotected( &priority_queue->Node ); if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) { _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node ); } #endif }
static void _Thread_queue_Priority_do_enqueue( Thread_queue_Heads *heads, Thread_Control *the_thread ) { Thread_queue_Priority_queue *priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); #if defined(RTEMS_SMP) if ( _RBTree_Is_empty( &priority_queue->Queue ) ) { _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node ); } #endif _RBTree_Insert( &priority_queue->Queue, &the_thread->Wait.Node.RBTree, _Thread_queue_Compare_priority, false ); }
void _Thread_Ready( Thread_Control *the_thread ) { ISR_Level level; Thread_Control *heir; _ISR_Disable( level ); the_thread->current_state = STATES_READY; _Priority_Add_to_bit_map( &the_thread->Priority_map ); _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node ); _ISR_Flash( level ); _Thread_Calculate_heir(); /* Priority_Bit_map_control minor; Priority_Bit_map_control major; _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); Priority_Control My_Pri=(major<< 4) +minor ; // My_Pri=My_Pri+0x100; Chain_Control *xx; *xx=_Thread_Ready_chain[ My_Pri ]; _Thread_Heir=(Thread_Control *)(xx->first); // _Thread_Heir = (Thread_Control *)_Thread_Ready_chain[ My_Pri ].first; */ heir = _Thread_Heir; if ( !_Thread_Is_executing( heir ) && _Thread_Executing->is_preemptible ) _Context_Switch_necessary = true; _ISR_Enable( level ); }
static void _Thread_queue_Path_append_deadlock_thread( Thread_Control *the_thread, Thread_queue_Context *queue_context ) { Thread_Control *deadlock; /* * In case of a deadlock, we must obtain the thread wait default lock for the * first thread on the path that tries to enqueue on a thread queue. This * thread can be identified by the thread wait operations. This lock acquire * is necessary for the timeout and explicit thread priority changes, see * _Thread_Priority_perform_actions(). */ deadlock = NULL; while ( the_thread->Wait.operations != &_Thread_queue_Operations_default ) { the_thread = the_thread->Wait.queue->owner; deadlock = the_thread; } if ( deadlock != NULL ) { Thread_queue_Link *link; link = &queue_context->Path.Deadlock; _Chain_Initialize_node( &link->Path_node ); _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node ); link->owner = deadlock; link->Lock_context.Wait.queue = NULL; _Thread_Wait_acquire_default_critical( deadlock, &link->Lock_context.Lock_context ); } }
static void _Thread_queue_Priority_do_enqueue( Thread_queue_Heads *heads, Thread_Control *the_thread ) { Thread_queue_Priority_queue *priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); Priority_Control current_priority; #if defined(RTEMS_SMP) if ( _RBTree_Is_empty( &priority_queue->Queue ) ) { _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node ); } #endif current_priority = the_thread->current_priority; _RBTree_Insert_inline( &priority_queue->Queue, &the_thread->Wait.Node.RBTree, ¤t_priority, _Thread_queue_Priority_less ); }
void _Scheduler_Request_ask_for_help( Thread_Control *the_thread ) { ISR_lock_Context lock_context; _Thread_Scheduler_acquire_critical( the_thread, &lock_context ); if ( _Chain_Is_node_off_chain( &the_thread->Scheduler.Help_node ) ) { Per_CPU_Control *cpu; cpu = _Thread_Get_CPU( the_thread ); _Per_CPU_Acquire( cpu ); _Chain_Append_unprotected( &cpu->Threads_in_need_for_help, &the_thread->Scheduler.Help_node ); _Per_CPU_Release( cpu ); _Thread_Dispatch_request( _Per_CPU_Get(), cpu ); } _Thread_Scheduler_release_critical( the_thread, &lock_context ); }
static #endif bool _Thread_queue_Path_acquire_critical( Thread_queue_Queue *queue, Thread_Control *the_thread, Thread_queue_Context *queue_context ) { Thread_Control *owner; #if defined(RTEMS_SMP) Thread_queue_Link *link; Thread_queue_Queue *target; /* * For an overview please look at the non-SMP part below. We basically do * the same on SMP configurations. The fact that we may have more than one * executing thread and each thread queue has its own SMP lock makes the task * a bit more difficult. We have to avoid deadlocks at SMP lock level, since * this would result in an unrecoverable deadlock of the overall system. */ _Chain_Initialize_empty( &queue_context->Path.Links ); owner = queue->owner; if ( owner == NULL ) { return true; } if ( owner == the_thread ) { return false; } _Chain_Initialize_node( &queue_context->Path.Start.Lock_context.Wait.Gate.Node ); link = &queue_context->Path.Start; _RBTree_Initialize_node( &link->Registry_node ); _Chain_Initialize_node( &link->Path_node ); do { _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node ); link->owner = owner; _Thread_Wait_acquire_default_critical( owner, &link->Lock_context.Lock_context ); target = owner->Wait.queue; link->Lock_context.Wait.queue = target; if ( target != NULL ) { if ( _Thread_queue_Link_add( link, queue, target ) ) { _Thread_queue_Gate_add( &owner->Wait.Lock.Pending_requests, &link->Lock_context.Wait.Gate ); _Thread_Wait_release_default_critical( owner, &link->Lock_context.Lock_context ); _Thread_Wait_acquire_queue_critical( target, &link->Lock_context ); if ( link->Lock_context.Wait.queue == NULL ) { _Thread_queue_Link_remove( link ); _Thread_Wait_release_queue_critical( target, &link->Lock_context ); _Thread_Wait_acquire_default_critical( owner, &link->Lock_context.Lock_context ); _Thread_Wait_remove_request_locked( owner, &link->Lock_context ); _Assert( owner->Wait.queue == NULL ); return true; } } else { link->Lock_context.Wait.queue = NULL; _Thread_queue_Path_append_deadlock_thread( owner, queue_context ); return false; } } else { return true; } link = &owner->Wait.Link; queue = target; owner = queue->owner; } while ( owner != NULL ); #else do { owner = queue->owner; if ( owner == NULL ) { return true; } if ( owner == the_thread ) { return false; } queue = owner->Wait.queue; } while ( queue != NULL ); #endif return true; }
bool _POSIX_signals_Clear_signals( POSIX_API_Control *api, int signo, siginfo_t *info, bool is_global, bool check_blocked ) { sigset_t mask; sigset_t signals_blocked; ISR_Level level; bool do_callout; POSIX_signals_Siginfo_node *psiginfo; mask = signo_to_mask( signo ); do_callout = false; /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK * insures that no signals are blocked and all are checked. */ if ( check_blocked ) signals_blocked = ~api->signals_blocked; else signals_blocked = SIGNAL_ALL_MASK; /* XXX is this right for siginfo type signals? */ /* XXX are we sure they can be cleared the same way? */ _ISR_Disable( level ); if ( is_global ) { if ( mask & (_POSIX_signals_Pending & signals_blocked) ) { if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { psiginfo = (POSIX_signals_Siginfo_node *) _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] ); _POSIX_signals_Clear_process_signals( signo ); /* * It may be impossible to get here with an empty chain * BUT until that is proven we need to be defensive and * protect against it. */ if ( psiginfo ) { *info = psiginfo->Info; _Chain_Append_unprotected( &_POSIX_signals_Inactive_siginfo, &psiginfo->Node ); } else do_callout = false; } _POSIX_signals_Clear_process_signals( signo ); do_callout = true; } } else { if ( mask & (api->signals_pending & signals_blocked) ) { api->signals_pending &= ~mask; do_callout = true; } } _ISR_Enable( level ); return do_callout; }
void _Thread_queue_Enqueue( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread, States_Control state, Watchdog_Interval timeout ) { ISR_lock_Context lock_context; Thread_blocking_operation_States sync_state; #if defined(RTEMS_MULTIPROCESSING) if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) the_thread = _Thread_MP_Allocate_proxy( state ); else #endif /* * Set the blocking state for this thread queue in the thread. */ _Thread_Set_state( the_thread, state ); /* * If the thread wants to timeout, then schedule its timer. */ if ( timeout ) { _Watchdog_Initialize( &the_thread->Timer, _Thread_queue_Timeout, the_thread->Object.id, NULL ); _Watchdog_Insert_ticks( &the_thread->Timer, timeout ); } /* * Now initiate the enqueuing and checking if the blocking operation * should be completed or the thread has had its blocking condition * satisfied before we got here. */ _Thread_queue_Acquire( &lock_context ); sync_state = the_thread_queue->sync_state; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) { /* * Invoke the discipline specific enqueue method. */ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) { _Chain_Append_unprotected( &the_thread_queue->Queues.Fifo, &the_thread->Object.Node ); } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */ _Thread_Lock_set( the_thread, &_Thread_queue_Lock ); _Thread_Priority_set_change_handler( the_thread, _Thread_queue_Requeue_priority, the_thread_queue ); _RBTree_Insert( &the_thread_queue->Queues.Priority, &the_thread->RBNode, _Thread_queue_Compare_priority, false ); } the_thread->Wait.queue = the_thread_queue; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; _Thread_queue_Release( &lock_context ); } else { /* Cancel a blocking operation due to ISR */ _Assert( sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT || sync_state == THREAD_BLOCKING_OPERATION_SATISFIED ); _Thread_blocking_operation_Finalize( the_thread, &lock_context ); } }
void _Thread_Scheduler_process_requests( Thread_Control *the_thread ) { ISR_lock_Context lock_context; Scheduler_Node *scheduler_node; _Thread_Scheduler_acquire_critical( the_thread, &lock_context ); scheduler_node = the_thread->Scheduler.requests; if ( scheduler_node != NULL ) { Scheduler_Node *next; Scheduler_Node *remove; the_thread->Scheduler.requests = NULL; remove = NULL; do { Scheduler_Node_request request; request = scheduler_node->Thread.request; scheduler_node->Thread.request = SCHEDULER_NODE_REQUEST_NOT_PENDING; next = scheduler_node->Thread.next_request; #if defined(RTEMS_DEBUG) scheduler_node->Thread.next_request = NULL; #endif if ( request == SCHEDULER_NODE_REQUEST_ADD ) { ++the_thread->Scheduler.helping_nodes; _Chain_Append_unprotected( &the_thread->Scheduler.Scheduler_nodes, &scheduler_node->Thread.Scheduler_node.Chain ); } else if ( request == SCHEDULER_NODE_REQUEST_REMOVE ) { --the_thread->Scheduler.helping_nodes; _Chain_Extract_unprotected( &scheduler_node->Thread.Scheduler_node.Chain ); scheduler_node->Thread.Scheduler_node.next = remove; remove = scheduler_node; } else { _Assert( request == SCHEDULER_NODE_REQUEST_NOTHING ); } scheduler_node = next; } while ( scheduler_node != NULL ); _Thread_Scheduler_release_critical( the_thread, &lock_context ); scheduler_node = remove; while ( scheduler_node != NULL ) { const Scheduler_Control *scheduler; ISR_lock_Context lock_context; next = scheduler_node->Thread.Scheduler_node.next; #if defined(RTEMS_DEBUG) scheduler_node->Thread.Scheduler_node.next = NULL; #endif scheduler = _Scheduler_Node_get_scheduler( scheduler_node ); _Scheduler_Acquire_critical( scheduler, &lock_context ); ( *scheduler->Operations.withdraw_node )( scheduler, the_thread, scheduler_node, THREAD_SCHEDULER_READY ); _Scheduler_Release_critical( scheduler, &lock_context ); scheduler_node = next; } } else { _Thread_Scheduler_release_critical( the_thread, &lock_context ); } }