📄 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_ASSERTS
cyg_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_GLOBAL
Cyg_ASR *Cyg_SchedThread::asr = &Cyg_SchedThread::asr_default;
# endif
# ifdef CYGSEM_KERNEL_SCHED_ASR_DATA_GLOBAL
CYG_ADDRWORD Cyg_SchedThread::asr_data = 0;
# endif
#endif // CYGSEM_KERNEL_SCHED_ASR_SUPPORT
// -------------------------------------------------------------------------
// Constructor
Cyg_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 ASR
void 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_PROTOCOL
void 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 inheritance
void 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_CEILING
void 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 + -