static void _Scheduler_simple_smp_Enqueue_ordered( Thread_Control *thread, Chain_Node_order order ) { Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance(); /* * The scheduled chain has exactly processor count nodes after * initialization, thus the lowest priority scheduled thread exists. */ Thread_Control *lowest_scheduled = (Thread_Control *) _Chain_Last( &self->scheduled ); if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) { _Scheduler_simple_smp_Allocate_processor( thread, lowest_scheduled ); _Scheduler_simple_smp_Insert( &self->scheduled, thread, order ); _Scheduler_simple_smp_Move_from_scheduled_to_ready( &self->ready, lowest_scheduled ); } else { _Scheduler_simple_smp_Insert( &self->ready, thread, order ); } }
static void _Thread_queue_Path_release( Thread_queue_Path *path ) { #if defined(RTEMS_SMP) Chain_Node *head; Chain_Node *node; head = _Chain_Head( &path->Links ); node = _Chain_Last( &path->Links ); if ( head != node ) { Thread_queue_Link *link; /* * The terminal link may have an owner which does not wait on a thread * queue. */ link = THREAD_QUEUE_LINK_OF_PATH_NODE( node ); if ( link->Queue_context.Wait.queue == NULL ) { _Thread_Wait_release_default_critical( link->owner, &link->Queue_context.Lock_context ); node = _Chain_Previous( node ); #if defined(RTEMS_DEBUG) _Chain_Set_off_chain( &link->Path_node ); #endif } while ( head != node ) { /* The other links have an owner which waits on a thread queue */ link = THREAD_QUEUE_LINK_OF_PATH_NODE( node ); _Assert( link->Queue_context.Wait.queue != NULL ); _Thread_queue_Link_remove( link ); _Thread_Wait_release_queue_critical( link->Queue_context.Wait.queue, &link->Queue_context ); _Thread_Wait_remove_request( link->owner, &link->Queue_context ); node = _Chain_Previous( node ); #if defined(RTEMS_DEBUG) _Chain_Set_off_chain( &link->Path_node ); #endif } } #else (void) path; #endif }
void _User_extensions_Thread_exitted ( Thread_Control *executing ) { Chain_Node *the_node; User_extensions_Control *the_extension; for ( the_node = _Chain_Last( &_User_extensions_List ); !_Chain_Is_head( &_User_extensions_List, the_node ) ; the_node = the_node->previous ) { the_extension = (User_extensions_Control *) the_node; if ( the_extension->Callouts.thread_exitted != NULL ) (*the_extension->Callouts.thread_exitted)( executing ); } }
/* * This method is unique to this scheduler because it must take into * account affinity as it searches for the lowest priority scheduled * thread. It ignores those which cannot be replaced by the filter * thread because the potential victim thread does not have affinity * for that processor. */ static Scheduler_Node * _Scheduler_priority_affinity_SMP_Get_lowest_scheduled( Scheduler_Context *context, Scheduler_Node *filter_base, Chain_Node_order order ) { Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context ); Scheduler_Node *lowest_scheduled = NULL; Chain_Control *scheduled = &self->Scheduled; Chain_Node *chain_node; Scheduler_priority_affinity_SMP_Node *filter = _Scheduler_priority_affinity_SMP_Node_downcast( filter_base ); for ( chain_node = _Chain_Last( scheduled ); chain_node != _Chain_Immutable_head( scheduled ) ; chain_node = _Chain_Previous( chain_node ) ) { Scheduler_priority_affinity_SMP_Node *node; Thread_Control *thread; uint32_t cpu_index; node = (Scheduler_priority_affinity_SMP_Node *) chain_node; /* * If we didn't find a thread which is of equal or lower importance * than filter thread is, then we can't schedule the filter thread * to execute. */ if ( (*order)( &node->Base.Base.Base.Node, &filter->Base.Base.Base.Node ) ) break; /* cpu_index is the processor number thread is executing on */ thread = _Scheduler_Node_get_owner( &node->Base.Base.Base ); cpu_index = _Per_CPU_Get_index( _Thread_Get_CPU( thread ) ); if ( CPU_ISSET( (int) cpu_index, filter->Affinity.set ) ) { lowest_scheduled = &node->Base.Base.Base; break; } } return lowest_scheduled; }
void _User_extensions_Fatal ( Internal_errors_Source the_source, bool is_internal, Internal_errors_t the_error ) { Chain_Node *the_node; User_extensions_Control *the_extension; for ( the_node = _Chain_Last( &_User_extensions_List ); !_Chain_Is_head( &_User_extensions_List, the_node ) ; the_node = the_node->previous ) { the_extension = (User_extensions_Control *) the_node; if ( the_extension->Callouts.fatal != NULL ) (*the_extension->Callouts.fatal)( the_source, is_internal, the_error ); } }
static #endif void _Thread_queue_Path_release_critical( Thread_queue_Context *queue_context ) { #if defined(RTEMS_SMP) Chain_Node *head; Chain_Node *node; head = _Chain_Head( &queue_context->Path.Links ); node = _Chain_Last( &queue_context->Path.Links ); while ( head != node ) { Thread_queue_Link *link; link = THREAD_QUEUE_LINK_OF_PATH_NODE( node ); if ( link->Lock_context.Wait.queue != NULL ) { _Thread_queue_Link_remove( link ); _Thread_Wait_release_queue_critical( link->Lock_context.Wait.queue, &link->Lock_context ); _Thread_Wait_remove_request( link->owner, &link->Lock_context ); } else { _Thread_Wait_release_default_critical( link->owner, &link->Lock_context.Lock_context ); } node = _Chain_Previous( node ); #if defined(RTEMS_DEBUG) _Chain_Set_off_chain( &link->Path_node ); #endif } #else (void) queue_context; #endif }
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 ); }
Thread_blocking_operation_States _Thread_queue_Enqueue_priority ( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread, ISR_Level *level_p ) { Priority_Control search_priority; Thread_Control *search_thread; ISR_Level level; Chain_Control *header; uint32_t header_index; Chain_Node *the_node; Chain_Node *next_node; Chain_Node *previous_node; Chain_Node *search_node; Priority_Control priority; States_Control block_state; _Chain_Initialize_empty( &the_thread->Wait.Block2n ); priority = the_thread->current_priority; header_index = _Thread_queue_Header_number( priority ); header = &the_thread_queue->Queues.Priority[ header_index ]; block_state = the_thread_queue->state; if ( _Thread_queue_Is_reverse_search( priority ) ) goto restart_reverse_search; restart_forward_search: search_priority = PRIORITY_MINIMUM - 1; _ISR_Disable( level ); search_thread = (Thread_Control *) _Chain_First( header ); while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) { search_priority = search_thread->current_priority; if ( priority <= search_priority ) break; #if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE ) search_thread = (Thread_Control *) search_thread->Object.Node.next; if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) ) break; search_priority = search_thread->current_priority; if ( priority <= search_priority ) break; #endif _ISR_Flash( level ); if ( !_States_Are_set( search_thread->current_state, block_state) ) { _ISR_Enable( level ); goto restart_forward_search; } search_thread = (Thread_Control *)search_thread->Object.Node.next; } if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) goto synchronize; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( priority == search_priority ) goto equal_priority; search_node = (Chain_Node *) search_thread; previous_node = search_node->previous; the_node = (Chain_Node *) the_thread; the_node->next = search_node; the_node->previous = previous_node; previous_node->next = the_node; search_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; restart_reverse_search: search_priority = PRIORITY_MAXIMUM + 1; _ISR_Disable( level ); search_thread = (Thread_Control *) _Chain_Last( header ); while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) { search_priority = search_thread->current_priority; if ( priority >= search_priority ) break; #if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE ) search_thread = (Thread_Control *) search_thread->Object.Node.previous; if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) ) break; search_priority = search_thread->current_priority; if ( priority >= search_priority ) break; #endif _ISR_Flash( level ); if ( !_States_Are_set( search_thread->current_state, block_state) ) { _ISR_Enable( level ); goto restart_reverse_search; } search_thread = (Thread_Control *) search_thread->Object.Node.previous; } if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) goto synchronize; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( priority == search_priority ) goto equal_priority; search_node = (Chain_Node *) search_thread; next_node = search_node->next; the_node = (Chain_Node *) the_thread; the_node->next = next_node; the_node->previous = search_node; search_node->next = the_node; next_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; equal_priority: /* add at end of priority group */ search_node = _Chain_Tail( &search_thread->Wait.Block2n ); previous_node = search_node->previous; the_node = (Chain_Node *) the_thread; the_node->next = search_node; the_node->previous = previous_node; previous_node->next = the_node; search_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; synchronize: /* * 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 the_thread_queue->sync_state; }