⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sched.cxx

📁 ecos为实时嵌入式操作系统
💻 CXX
字号:
//==========================================================================////      sched/sched.cxx////      Scheduler class implementations////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License.  You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus.  Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions.  All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   nickg// Contributors:        nickg// Date:        1997-09-15// Purpose:     Scheduler class implementation// Description: This file contains the definitions of the scheduler class//              member functions that are common to all scheduler//              implementations.////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/kernel.h>#include <cyg/kernel/ktypes.h>         // base kernel types#include <cyg/infra/cyg_trac.h>        // tracing macros#include <cyg/infra/cyg_ass.h>         // assertion macros#include <cyg/kernel/instrmnt.h>       // instrumentation#include <cyg/kernel/sched.hxx>        // our header#include <cyg/kernel/thread.hxx>       // thread classes#include <cyg/kernel/intr.hxx>         // Interrupt interface#include <cyg/hal/hal_arch.h>          // Architecture specific definitions#include <cyg/kernel/thread.inl>       // thread inlines//-------------------------------------------------------------------------// Some local tracing control - a default.#ifdef CYGDBG_USE_TRACING# if !defined( CYGDBG_INFRA_DEBUG_TRACE_ASSERT_SIMPLE ) && \     !defined( CYGDBG_INFRA_DEBUG_TRACE_ASSERT_FANCY  )   // ie. not a tracing implementation that takes a long time to output#  ifndef CYGDBG_KERNEL_TRACE_UNLOCK_INNER#   define CYGDBG_KERNEL_TRACE_UNLOCK_INNER#  endif // control not already defined# endif  // trace implementation not ..._SIMPLE && not ..._FANCY#endif   // CYGDBG_USE_TRACING// -------------------------------------------------------------------------// Static Cyg_Scheduler class members// We start with sched_lock at 1 so that any kernel code we// call during initialization will not try to reschedule.volatile cyg_ucount32 Cyg_Scheduler_Base::sched_lock = 1;Cyg_Thread            *Cyg_Scheduler_Base::current_thread = NULL;cyg_bool              Cyg_Scheduler_Base::need_reschedule = false;Cyg_Scheduler         Cyg_Scheduler::scheduler CYG_INIT_PRIORITY( SCHEDULER );cyg_ucount32          Cyg_Scheduler_Base::thread_switches = 0;// -------------------------------------------------------------------------// Scheduler unlock function.// This is only called when the lock is to be decremented to zero and there// is the potential for real work to be done. Other cases are handled in// Cyg_Scheduler::unlock() which is an inline.void Cyg_Scheduler::unlock_inner(){#ifdef CYGDBG_KERNEL_TRACE_UNLOCK_INNER    CYG_REPORT_FUNCTION();#endif        do {        CYG_PRECONDITION( sched_lock == 1 , "sched_lock not 1" );        #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS                // Call any pending DSRs. Do this here to ensure that any        // threads that get awakened are properly scheduled.        if( Cyg_Interrupt::DSRs_pending() )            Cyg_Interrupt::call_pending_DSRs();#endif                    Cyg_Thread *current = current_thread;        CYG_ASSERTCLASS( current, "Bad current thread" );        // If the current thread is going to sleep, or someone        // wants a reschedule, choose another thread to run        if( current->state != Cyg_Thread::RUNNING || need_reschedule ) {            CYG_INSTRUMENT_SCHED(RESCHEDULE,0,0);                        // Get the next thread to run from scheduler            Cyg_Thread *next = scheduler.schedule();            CYG_CHECK_DATA_PTR( next, "Invalid next thread pointer");            CYG_ASSERTCLASS( next, "Bad next thread" );            if( current != next )            {                CYG_INSTRUMENT_THREAD(SWITCH,current,next);                // Count this thread switch                thread_switches++;                                // Switch contexts                HAL_THREAD_SWITCH_CONTEXT( &current->stack_ptr,                                           &next->stack_ptr );                // Worry here about possible compiler                // optimizations across the above call that may try to                // propogate common subexpresions.  We would end up                // with the expression from one thread in its                // successor. This is only a worry if we do not save                // and restore the complete register set. We need a                // way of marking functions that return into a                // different context. A temporary fix would be to                // disable CSE (-fdisable-cse) in the compiler.                                // We return here only when the current thread is                // rescheduled.  There is a bit of housekeeping to do                // here before we are allowed to go on our way.                CYG_CHECK_DATA_PTR( current, "Invalid current thread pointer");                CYG_ASSERTCLASS( current, "Bad current thread" );                current_thread = current;   // restore current thread pointer            }#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE            // Reset the timeslice counter so that this thread gets a full            // quantum.             reset_timeslice_count();#endif            need_reschedule = false;        // finished rescheduling        }                  HAL_REORDER_BARRIER(); // Make sure everything above has happened                               // by this point        sched_lock = 0;       // Clear the lock        HAL_REORDER_BARRIER();                #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS        // Now check whether any DSRs got posted during the thread        // switch and if so, go around again. Making this test after        // the lock has been zeroed avoids a race condition in which        // a DSR could have been posted during a reschedule, but would        // not be run until the _next_ time we release the sched lock.        if( Cyg_Interrupt::DSRs_pending() ) {            sched_lock = 1;     // reclaim the lock            continue;           // go back to head of loop        }#endif        // Otherwise the lock is zero, we can return.        CYG_POSTCONDITION( sched_lock == 0, "sched_lock not zero" );        #ifdef CYGDBG_KERNEL_TRACE_UNLOCK_INNER        CYG_REPORT_RETURN();#endif        return;    } while( 1 );    CYG_FAIL( "Should not be executed" );}// -------------------------------------------------------------------------// Start the scheduler. This is called after the initial threads have been// created to start scheduling.void Cyg_Scheduler::start(){    CYG_REPORT_FUNCTION();            // Get the first thread to run from scheduler    register Cyg_Thread *next = scheduler.schedule();    CYG_ASSERTCLASS( next, "Bad initial thread" );    need_reschedule = false;    // finished rescheduling    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    // Let the interrupts go    Cyg_Interrupt::enable_interrupts();        HAL_THREAD_LOAD_CONTEXT( &next->stack_ptr );        }// -------------------------------------------------------------------------// Consistency checker#ifdef CYGDBG_USE_ASSERTSbool 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( !current_thread->check_this(zeal) ) return false;    case cyg_quick:    case cyg_trivial:    case cyg_none:    default:        break;    };    return true;}#endif//==========================================================================// SchedThread members// -------------------------------------------------------------------------// ConstructorCyg_SchedThread::Cyg_SchedThread(Cyg_Thread *thread, CYG_ADDRWORD sched_info): Cyg_SchedThread_Implementation(sched_info){    CYG_REPORT_FUNCTION();            queue = NULL;        if( Cyg_Scheduler::current_thread == NULL )        Cyg_Scheduler::current_thread = thread;#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE    mutex_count = 0;    priority_inherited = false;    #endif    }// -------------------------------------------------------------------------// Priority inheritance support.#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE// -------------------------------------------------------------------------// Inherit the priority of the provided thread if it// has a higher priority than ours.void Cyg_SchedThread::inherit_priority( Cyg_Thread *thread){#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE    // A simple implementation of priority inheritance.  If the other    // thread is of higher priority, reset our priority to his. The    // first time we do this, save our original priority.    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!");        if( thread->get_priority() < priority )    {        cyg_priority mypri = priority;        if( !priority_inherited )        {            // If this is first inheritance, copy the old pri            // and set inherited flag. We do this after setting the            // pri since set_priority() is inheritance aware.            self->set_priority( thread->get_priority() );            priority_inherited = true,            original_priority = mypri;        }        else        {            // Already in inherited state, and new pri is higher            // than old. Just change the pri.                        self->set_priority( thread->get_priority() );                    }    }#endif}// -------------------------------------------------------------------------// Lose a priority inheritancevoid Cyg_SchedThread::disinherit_priority(){#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE    // A simple implementation of priority inheritance.  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// -------------------------------------------------------------------------// EOF sched/sched.cxx

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -