📄 sched.cxx
字号:
set_current_thread(next); // restore current thread pointer#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK // Reference the real time clock. This ensures that at least one // reference to the kernel_clock.o object exists, without which // the object will not be included while linking. CYG_REFERENCE_OBJECT( Cyg_Clock::real_time_clock );#endif // Load the first thread. This will also enable interrupts since // the initial state of all threads is to have interrupts enabled. HAL_THREAD_LOAD_CONTEXT( &next->stack_ptr ); }// -------------------------------------------------------------------------// SMP support functions#ifdef CYGPKG_KERNEL_SMP_SUPPORT// This is called on each secondary CPU on its interrupt stack after// the initial CPU has initialized the world.externC void cyg_kernel_smp_startup(){ CYG_INSTRUMENT_SMP( CPU_START, CYG_KERNEL_CPU_THIS(), 0 ); Cyg_Scheduler::lock(); Cyg_Scheduler::start_cpu();}// This is called from the DSR of the inter-CPU interrupt to cause a// reschedule when the scheduler lock is zeroed.__externC void cyg_scheduler_set_need_reschedule(){ CYG_INSTRUMENT_SMP( RESCHED_RECV, 0, 0 ); Cyg_Scheduler::need_reschedule[HAL_SMP_CPU_THIS()] = true;}#endif// -------------------------------------------------------------------------// Consistency checker#ifdef CYGDBG_USE_ASSERTScyg_bool Cyg_Scheduler::check_this( cyg_assert_class_zeal zeal) const{ CYG_REPORT_FUNCTION(); // check that we have a non-NULL pointer first if( this == NULL ) return false; switch( zeal ) { case cyg_system_test: case cyg_extreme: case cyg_thorough: if( !get_current_thread()->check_this(zeal) ) return false; case cyg_quick: case cyg_trivial: case cyg_none: default: break; }; return true;}#endif//==========================================================================// SchedThread members// -------------------------------------------------------------------------// Static data members#ifdef CYGSEM_KERNEL_SCHED_ASR_SUPPORT# ifdef CYGSEM_KERNEL_SCHED_ASR_GLOBALCyg_ASR *Cyg_SchedThread::asr = &Cyg_SchedThread::asr_default;# endif# ifdef CYGSEM_KERNEL_SCHED_ASR_DATA_GLOBALCYG_ADDRWORD Cyg_SchedThread::asr_data = 0;# endif#endif // CYGSEM_KERNEL_SCHED_ASR_SUPPORT// -------------------------------------------------------------------------// ConstructorCyg_SchedThread::Cyg_SchedThread(Cyg_Thread *thread, CYG_ADDRWORD sched_info): Cyg_SchedThread_Implementation(sched_info){ CYG_REPORT_FUNCTION(); queue = NULL;#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL mutex_count = 0; #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE priority_inherited = false; #endif#endif#ifdef CYGSEM_KERNEL_SCHED_ASR_SUPPORT asr_inhibit = 0; asr_pending = false;#ifndef CYGSEM_KERNEL_SCHED_ASR_GLOBAL asr = asr_default;#endif#ifdef CYGSEM_KERNEL_SCHED_ASR_DATA_GLOBAL asr_data = NULL#endif #endif }// -------------------------------------------------------------------------// ASR support functions#ifdef CYGSEM_KERNEL_SCHED_ASR_SUPPORT// -------------------------------------------------------------------------// Set ASR// Install a new ASR, returning the old one.void Cyg_SchedThread::set_asr( Cyg_ASR *new_asr, CYG_ADDRWORD new_data, Cyg_ASR **old_asr, CYG_ADDRWORD *old_data){ CYG_REPORT_FUNCTION(); // Do this with the scheduler locked... Cyg_Scheduler::lock(); if( old_asr != NULL ) *old_asr = asr; if( old_data != NULL ) *old_data = asr_data; // If new_asr is NULL, do not change the ASR, // but only change the data. if( new_asr != NULL ) asr = new_asr; asr_data = new_data; Cyg_Scheduler::unlock();}// -------------------------------------------------------------------------// Clear ASRvoid Cyg_SchedThread::clear_asr(){ CYG_REPORT_FUNCTION(); // Do this with the scheduler locked... Cyg_Scheduler::lock(); // Reset ASR to default. asr = asr_default; asr_data = 0; Cyg_Scheduler::unlock(); }// -------------------------------------------------------------------------// Default ASR function.// having this avoids our having to worry about ever seeing a NULL// pointer as the ASR function.void Cyg_SchedThread::asr_default(CYG_ADDRWORD data){ CYG_REPORT_FUNCTION(); data=data; return;}#endif// -------------------------------------------------------------------------// Generic priority protocol support#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOLvoid Cyg_SchedThread::set_inherited_priority( cyg_priority pri, Cyg_Thread *thread ){ CYG_REPORT_FUNCTION();#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE // This is the comon code for priority inheritance and ceiling // protocols. This implementation provides a simplified version of // the protocol. Cyg_Thread *self = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread, this); CYG_ASSERT( mutex_count > 0, "Non-positive mutex count"); // Compare with *current* priority in case thread has already // inherited - for relay case below. if( pri < priority ) { cyg_priority mypri = priority; cyg_bool already_inherited = priority_inherited; // If this is first inheritance, copy the old pri // and set inherited flag. We clear it before setting the // pri since set_priority() is inheritance aware. // This is called with the sched locked, so no race conditions. priority_inherited = false; // so that set_prio DTRT self->set_priority( pri ); if( !already_inherited ) original_priority = mypri; priority_inherited = true; // regardless, because it is now }#endif}void Cyg_SchedThread::relay_inherited_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue){ CYG_REPORT_FUNCTION();#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE // A simple implementation of priority inheritance. // At its simplest, this member does nothing. // If there is anyone else waiting, then the *new* owner inherits from // the current one, since that is a maxima of the others waiting. // (It's worth not doing if there's nobody waiting to prevent // unneccessary priority skew.) This could be viewed as a discovered // priority ceiling. if ( !pqueue->empty() ) set_inherited_priority( ex_owner->get_current_priority(), ex_owner );#endif}void Cyg_SchedThread::clear_inherited_priority(){ CYG_REPORT_FUNCTION();#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE // A simple implementation of priority inheritance/ceiling // protocols. The simplification in this algorithm is that we do // not reduce our priority until we have freed all mutexes // claimed. Hence we can continue to run at an artificially high // priority even when we should not. However, since nested // mutexes are rare, the thread we have inherited from is likely // to be locking the same mutexes we are, and mutex claim periods // should be very short, the performance difference between this // and a more complex algorithm should be negligible. The most // important advantage of this algorithm is that it is fast and // deterministic. Cyg_Thread *self = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread, this); CYG_ASSERT( mutex_count >= 0, "Non-positive mutex count"); if( mutex_count == 0 && priority_inherited ) { priority_inherited = false; // Only make an effort if the priority must change if( priority < original_priority ) self->set_priority( original_priority ); } #endif }#endif // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL// -------------------------------------------------------------------------// Priority inheritance support.#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT// -------------------------------------------------------------------------// Inherit the priority of the provided thread if it// has a higher priority than ours.void Cyg_SchedThread::inherit_priority( Cyg_Thread *thread){ CYG_REPORT_FUNCTION(); Cyg_Thread *self = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread, this); CYG_ASSERT( mutex_count > 0, "Non-positive mutex count"); CYG_ASSERT( self != thread, "Trying to inherit from self!"); self->set_inherited_priority( thread->get_current_priority(), thread ); }// -------------------------------------------------------------------------// Inherit the priority of the ex-owner thread or from the queue if it// has a higher priority than ours.void Cyg_SchedThread::relay_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue){ CYG_REPORT_FUNCTION(); relay_inherited_priority( ex_owner, pqueue );}// -------------------------------------------------------------------------// Lose a priority inheritancevoid Cyg_SchedThread::disinherit_priority(){ CYG_REPORT_FUNCTION(); CYG_ASSERT( mutex_count >= 0, "Non-positive mutex count"); clear_inherited_priority();}#endif // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT// -------------------------------------------------------------------------// Priority ceiling support#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILINGvoid Cyg_SchedThread::set_priority_ceiling( cyg_priority pri ){ CYG_REPORT_FUNCTION(); CYG_ASSERT( mutex_count > 0, "Non-positive mutex count"); set_inherited_priority( pri );}void Cyg_SchedThread::clear_priority_ceiling( ){ CYG_REPORT_FUNCTION(); CYG_ASSERT( mutex_count >= 0, "Non-positive mutex count"); clear_inherited_priority();}#endif // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING// -------------------------------------------------------------------------// EOF sched/sched.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -