📄 mlqueue.cxx
字号:
Cyg_Scheduler_Implementation::unique( cyg_priority priority){ CYG_REPORT_FUNCTYPE("returning %d"); CYG_REPORT_FUNCARG1("priority=%d", priority); // Priorities are not unique CYG_REPORT_RETVAL(true); return true;}//==========================================================================// Support for timeslicing option#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE// -------------------------------------------------------------------------voidCyg_Scheduler_Implementation::timeslice(void){#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE CYG_REPORT_FUNCTION();#endif#ifdef CYGPKG_KERNEL_SMP_SUPPORT HAL_SMP_CPU_TYPE cpu; HAL_SMP_CPU_TYPE cpu_count = CYG_KERNEL_CPU_COUNT(); HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS(); for( cpu = 0; cpu < cpu_count; cpu++ ) { if( --timeslice_count[cpu] == 0 ) if( cpu == cpu_this ) timeslice_cpu(); else CYG_KERNEL_CPU_TIMESLICE_INTERRUPT( cpu, 0 ); }#else if( --timeslice_count[CYG_KERNEL_CPU_THIS()] == 0 ) timeslice_cpu(); #endif#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE CYG_REPORT_RETURN();#endif }// -------------------------------------------------------------------------voidCyg_Scheduler_Implementation::timeslice_cpu(void){#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE CYG_REPORT_FUNCTION();#endif Cyg_Thread *thread = get_current_thread(); HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS(); CYG_ASSERT( queue_map != 0, "Run queue empty"); CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!");#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE if( thread->timeslice_enabled && timeslice_count[cpu_this] == 0 )#else if( timeslice_count[cpu_this] == 0 )#endif { CYG_INSTRUMENT_SCHED(TIMESLICE,0,0);#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE CYG_TRACE0( true, "quantum consumed, time to reschedule" );#endif CYG_ASSERT( get_sched_lock() > 0 , "Timeslice called with zero sched_lock"); // Only try to rotate the run queue if the current thread is running. // Otherwise we are going to reschedule anyway. if( thread->get_state() == Cyg_Thread::RUNNING ) { Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; CYG_INSTRUMENT_MLQ( TIMESLICE, thread, 0); CYG_ASSERTCLASS( thread, "Bad current thread"); CYG_ASSERTCLASS( sched, "Bad scheduler"); cyg_priority pri = thread->priority; Cyg_RunQueue *queue = &sched->run_queue[pri];#ifdef CYGPKG_KERNEL_SMP_SUPPORT // In SMP systems we set the head of the queue to point to // the thread immediately after the current // thread. schedule() will then pick that thread, or one // after it to run next. queue->to_head( thread->get_next() );#else queue->rotate();#endif if( queue->get_head() != thread ) sched->set_need_reschedule(); timeslice_count[cpu_this] = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS; } } CYG_ASSERT( queue_map & (1<<CYG_THREAD_MIN_PRIORITY), "Idle thread vanished!!!"); CYG_ASSERT( !run_queue[CYG_THREAD_MIN_PRIORITY].empty(), "Idle thread vanished!!!");#ifdef CYGDBG_KERNEL_TRACE_TIMESLICE CYG_REPORT_RETURN();#endif}// -------------------------------------------------------------------------__externC void cyg_scheduler_timeslice_cpu(void){ Cyg_Scheduler::scheduler.timeslice_cpu();}#endif//==========================================================================// Cyg_SchedThread_Implementation class membersCyg_SchedThread_Implementation::Cyg_SchedThread_Implementation( CYG_ADDRWORD sched_info){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG1("sched_info=%08x", sched_info); // Set priority to the supplied value. priority = (cyg_priority)sched_info;#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE // If timeslice_enabled exists, set it true by default timeslice_enabled = true;#endif#ifdef CYGPKG_KERNEL_SMP_SUPPORT cpu = CYG_KERNEL_CPU_NONE;#endif CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Yield the processor to another threadvoidCyg_SchedThread_Implementation::yield(void){ CYG_REPORT_FUNCTION(); // Prevent preemption Cyg_Scheduler::lock(); Cyg_Thread *thread = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread_Implementation, this); // Only do this if this thread is running. If it is not, there // is no point. if( thread->get_state() == Cyg_Thread::RUNNING ) { // To yield we simply rotate the appropriate // run queue to the next thread and reschedule. CYG_INSTRUMENT_MLQ( YIELD, thread, 0); CYG_ASSERTCLASS( thread, "Bad current thread"); Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; CYG_ASSERTCLASS( sched, "Bad scheduler"); cyg_priority pri = thread->priority; Cyg_RunQueue *queue = &sched->run_queue[pri];#ifdef CYGPKG_KERNEL_SMP_SUPPORT // In SMP systems we set the head of the queue to point to // the thread immediately after the current // thread. schedule() will then pick that thread, or one // after it to run next. queue->to_head( thread->get_next() );#else queue->rotate();#endif if( queue->get_head() != thread ) sched->set_need_reschedule();#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE // Reset the timeslice counter so that this thread gets a full // quantum. else Cyg_Scheduler::reset_timeslice_count();#endif } // Unlock the scheduler and switch threads#ifdef CYGDBG_USE_ASSERTS // This test keeps the assertions in unlock_inner() happy if // need_reschedule was not set above. if( !Cyg_Scheduler::get_need_reschedule() ) Cyg_Scheduler::unlock(); else #endif Cyg_Scheduler::unlock_reschedule(); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Rotate the run queue at a specified priority.// (pri is the decider, not this, so the routine is static)voidCyg_SchedThread_Implementation::rotate_queue( cyg_priority pri ){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG1("priority=%d", pri); // Prevent preemption Cyg_Scheduler::lock(); Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; CYG_ASSERTCLASS( sched, "Bad scheduler"); Cyg_RunQueue *queue = &sched->run_queue[pri]; if ( !queue->empty() ) { queue->rotate(); sched->set_need_reschedule(); } // Unlock the scheduler and switch threads Cyg_Scheduler::unlock(); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Move this thread to the head of its queue// (not necessarily a scheduler queue)voidCyg_SchedThread_Implementation::to_queue_head( void ){ CYG_REPORT_FUNCTION(); // Prevent preemption Cyg_Scheduler::lock(); Cyg_Thread *thread = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread_Implementation, this); CYG_ASSERTCLASS( thread, "Bad current thread"); Cyg_ThreadQueue *q = thread->get_current_queue(); if( q != NULL ) q->to_head( thread ); else if( thread->in_list() ) { // If the queue pointer is NULL then it is on a run // queue. Move the thread to the head of it's priority list // and force a reschedule. Cyg_Scheduler *sched = &Cyg_Scheduler::scheduler; sched->run_queue[thread->priority].to_head( thread ); sched->set_need_reschedule( thread ); } // Unlock the scheduler and switch threads Cyg_Scheduler::unlock(); CYG_REPORT_RETURN();}//==========================================================================// Cyg_ThreadQueue_Implementation class members// ------------------------------------------------------------------------- voidCyg_ThreadQueue_Implementation::enqueue(Cyg_Thread *thread){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG1("thread=%08x", thread); CYG_INSTRUMENT_MLQ( ENQUEUE, this, thread ); #ifdef CYGIMP_KERNEL_SCHED_SORTED_QUEUES // Insert the thread into the queue in priority order. Cyg_Thread *qhead = get_head(); if( qhead == NULL ) add_tail( thread ); else if( qhead == qhead->get_next() ) { // There is currently only one thread in the queue, join it // and adjust the queue pointer to point to the highest // priority of the two. If they are the same priority, // leave the pointer pointing to the oldest. qhead->insert( thread ); if( thread->priority < qhead->priority ) to_head(thread); } else { // There is more than one thread in the queue. First check // whether we are of higher priority than the head and if // so just jump in at the front. Also check whether we are // lower priority than the tail and jump onto the end. // Otherwise we really have to search the queue to find // our place. if( thread->priority < qhead->priority ) { qhead->insert( thread ); to_head(thread); } else if( thread->priority > get_tail()->priority ) { // We are lower priority than any thread in the queue, // go in at the end. add_tail( thread ); } else { // Search the queue. We do this backwards so that we // always add new threads after any that have the same // priority. // Because of the previous tests we know that this // search will terminate before we hit the head of the // queue, hence we do not need to check for that // condition. Cyg_Thread *qtmp = get_tail(); // Scan the queue until we find a higher or equal // priority thread. while( thread->priority > qtmp->priority ) qtmp = qtmp->get_prev(); // Append ourself after the node pointed to by qtmp. qtmp->append( thread ); } }#else // Just add the thread to the tail of the list add_tail( thread );#endif thread->queue = CYG_CLASSFROMBASE(Cyg_ThreadQueue, Cyg_ThreadQueue_Implementation, this); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------Cyg_Thread *Cyg_ThreadQueue_Implementation::dequeue(void){ CYG_REPORT_FUNCTYPE("returning thread %08x"); Cyg_Thread *thread = rem_head(); CYG_INSTRUMENT_MLQ( DEQUEUE, this, thread ); if( thread != NULL ) thread->queue = NULL; CYG_REPORT_RETVAL(thread); return thread;}// -------------------------------------------------------------------------voidCyg_ThreadQueue_Implementation::remove( Cyg_Thread *thread ){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG1("thread=%08x", thread); CYG_INSTRUMENT_MLQ( REMOVE, this, thread ); thread->queue = NULL; Cyg_CList_T<Cyg_Thread>::remove( thread ); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------Cyg_Thread *Cyg_ThreadQueue_Implementation::highpri(void){ CYG_REPORT_FUNCTYPE("returning thread %08x"); CYG_REPORT_RETVAL(get_head()); return get_head();}// -------------------------------------------------------------------------inline voidCyg_ThreadQueue_Implementation::set_thread_queue(Cyg_Thread *thread, Cyg_ThreadQueue *tq ){ thread->queue = tq;}// -------------------------------------------------------------------------#endif// -------------------------------------------------------------------------// EOF sched/mlqueue.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -