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

📄 lottery.cxx

📁 ecos为实时嵌入式操作系统
💻 CXX
字号:
//==========================================================================////      sched/lottery.cxx////      Lottery scheduler class implementation////==========================================================================//####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-16// Purpose:     Lottery scheduler class implementation// Description: This file contains the implementations of//              Cyg_Scheduler_Implementation and//              Cyg_SchedThread_Implementation.//              ////####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/sched.hxx>        // our header#include <cyg/kernel/intr.hxx>         // interrupt defines, for Cyg_HAL_Clock#include <cyg/hal/hal_arch.h>          // Architecture specific definitions#include <cyg/kernel/thread.inl>       // thread inlines#include <cyg/kernel/sched.inl>        // scheduler inlines#ifdef CYGSEM_KERNEL_SCHED_LOTTERY#define CYG_ENABLE_TRACE 1//==========================================================================// Cyg_Scheduler_Implementation class static members#ifdef CYGSEM_KERNEL_SCHED_TIMESLICEcyg_count32 Cyg_Scheduler_Implementation::timeslice_count =                                        CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;#endif//==========================================================================// Cyg_Scheduler_Implementation class members// -------------------------------------------------------------------------// Constructor.Cyg_Scheduler_Implementation::Cyg_Scheduler_Implementation(){    CYG_REPORT_FUNCTION();    total_tickets = 0;    rand_seed = 1;}// -------------------------------------------------------------------------// Choose the best thread to run nextCyg_Thread *Cyg_Scheduler_Implementation::schedule(){    CYG_REPORT_FUNCTION();#ifdef CYG_HAL_POWERPC    // PowerPc specific version of random number generator.    register cyg_int32 r1 asm("r4");    r1 = rand_seed;    asm(        "li     7,0;"        "ori    7,7,33614;"        "mulhwu 5,7,%0;"        "mullw  6,7,%0;"        "srawi  6,6,1;"        "add    %0,5,6;"        "cmpwi  %0,0;"        "bge    1f;"        "slwi   %0,%0,1;"        "srwi   %0,%0,1;"        "addi   %0,%0,1;"        "1:;"        : "=r"(r1)        : "0"(r1)        : "r5", "r6", "r7"        );    rand_seed = r1;    #else#if 1    rand_seed = (rand_seed * 1103515245) + 1234;    cyg_int32 r1 = rand_seed & 0x7FFFFFFF;#else        // Generic implementation of RNG.#if( CYG_BYTEORDER == CYG_MSBFIRST )#define _LO 1    #define _HI 0#else#define _LO 0    #define _HI 1#endif        union { cyg_int64 r64; cyg_int32 r32[2]; } u;    u.r64 = (cyg_int64)rand_seed * 33614LL;    cyg_int32 r1 = u.r32[_HI] + (u.r32[_LO]>>1);    if( r1 < 0 )        r1 = (r1 & 0x7FFFFFFF) + 1;    rand_seed = r1;#undef _LO#undef _HI#endif    #endif        cyg_int32 ticket = r1 % total_tickets;    cyg_int32 tick = ticket;    Cyg_Thread *thread = run_queue.highpri();    // Search the run queue for the thread with the    // given ticket.    while( ticket > 0 )    {        ticket -= thread->priority;        if( ticket <= 0 ) break;        thread = thread->next;                CYG_ASSERT( thread != run_queue.highpri(), "Looping in scheduler");    }    CYG_TRACE3( CYG_ENABLE_TRACE,        "seed %08x ticket %d thread %08x",        rand_seed, tick, thread);    // If the thread has any compensation tickets, take them away since    // it has just won.    if( thread->compensation_tickets > 0 )    {        thread->priority -= thread->compensation_tickets;        total_tickets -= thread->compensation_tickets;        thread->compensation_tickets = 0;    }     // Re-insert thread at head of list. This reduces runtime by    // putting the large ticket holders at the front of the list.    //    run_queue.remove(thread);//    run_queue.enqueue(thread);    CYG_CHECK_DATA_PTR( thread, "Invalid next thread pointer");                CYG_ASSERTCLASS( thread, "Bad next thread" );        return thread;}// -------------------------------------------------------------------------void Cyg_Scheduler_Implementation::add_thread(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();    // If the thread is on some other queue, remove it    // here.    if( thread->queue != NULL )    {        thread->queue->remove(thread);        thread->queue = NULL;    }        total_tickets += thread->priority;    run_queue.enqueue(thread);}// -------------------------------------------------------------------------void Cyg_Scheduler_Implementation::rem_thread(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();    run_queue.remove(thread);    total_tickets -= thread->priority;    // Compensate the thread for the segment of the quantum that    // it used. This makes it more likely to win the lottery next time    // it is scheduled. We only do this for threads that have voluntarily    // given up the CPU.//    if( thread->get_state() != Cyg_Thread::RUNNING )    {#if 0                cyg_uint32 hal_ticks;        HAL_CLOCK_READ( &hal_ticks );        thread->compensation_tickets = thread->priority *            CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / hal_ticks;#else        thread->compensation_tickets = (thread->priority *            CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS) / timeslice_count;        #endif                thread->priority += thread->compensation_tickets;    }}// -------------------------------------------------------------------------// register thread with schedulervoid Cyg_Scheduler_Implementation::register_thread(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();            // No registration necessary in this scheduler}// -------------------------------------------------------------------------// deregister threadvoid Cyg_Scheduler_Implementation::deregister_thread(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();            // No registration necessary in this scheduler    }    // -------------------------------------------------------------------------// Test the given priority for uniquenesscyg_bool Cyg_Scheduler_Implementation::unique( cyg_priority priority){    CYG_REPORT_FUNCTION();            // Priorities are not unique    return true;}//==========================================================================// Support for timeslicing option#ifdef CYGSEM_KERNEL_SCHED_TIMESLICEvoid Cyg_Scheduler_Implementation::timeslice(){    CYG_REPORT_FUNCTION();    if( --timeslice_count <= 0 )    {        CYG_INSTRUMENT_SCHED(TIMESLICE,0,0);                // Force a reschedule on each timeslice        need_reschedule = true;        timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;    }}#endif//==========================================================================// Cyg_Cyg_SchedThread_Implementation class membersCyg_SchedThread_Implementation::Cyg_SchedThread_Implementation(    CYG_ADDRWORD sched_info){    CYG_REPORT_FUNCTION();    priority = cyg_priority(sched_info);        // point the next and prev field at this thread.        next = prev = CYG_CLASSFROMBASE(Cyg_Thread,                                    Cyg_SchedThread_Implementation,                                    this);}// -------------------------------------------------------------------------// Insert thread in front of thisvoid Cyg_SchedThread_Implementation::insert( Cyg_Thread *thread){    CYG_REPORT_FUNCTION();            thread->next        = CYG_CLASSFROMBASE(Cyg_Thread,                                            Cyg_SchedThread_Implementation,                                            this);    thread->prev        = prev;    prev->next          = thread;    prev                = thread;    }// -------------------------------------------------------------------------// remove this from queuevoid Cyg_SchedThread_Implementation::remove(){    CYG_REPORT_FUNCTION();            next->prev          = prev;    prev->next          = next;    next = prev         = CYG_CLASSFROMBASE(Cyg_Thread,                                            Cyg_SchedThread_Implementation,                                            this);}// -------------------------------------------------------------------------// Yield the processor to another threadvoid Cyg_SchedThread_Implementation::yield(){    CYG_REPORT_FUNCTION();        }//==========================================================================// Cyg_ThreadQueue_Implementation class membersvoid Cyg_ThreadQueue_Implementation::enqueue(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();    // Always put thread at head of queue    if( queue == NULL ) queue = thread;    else    {        queue->insert(thread);//        queue->next->insert(thread);//        queue = thread;    }        thread->queue = CYG_CLASSFROMBASE(Cyg_ThreadQueue,                                      Cyg_ThreadQueue_Implementation,                                      this);    }// -------------------------------------------------------------------------Cyg_Thread *Cyg_ThreadQueue_Implementation::dequeue(){    CYG_REPORT_FUNCTION();            if( queue == NULL ) return NULL;        Cyg_Thread *thread = queue;        if( thread->next == thread )    {        // sole thread on list, NULL out ptr        queue = NULL;    }    else    {        // advance to next and remove thread        queue = thread->next;        thread->remove();    }    thread->queue = NULL;    return thread;}// -------------------------------------------------------------------------Cyg_Thread *Cyg_ThreadQueue_Implementation::highpri(){    CYG_REPORT_FUNCTION();            return queue;}// -------------------------------------------------------------------------void Cyg_ThreadQueue_Implementation::remove(Cyg_Thread *thread){    CYG_REPORT_FUNCTION();            // If the thread we want is the at the head    // of the list, and is on its own, clear the    // list and return. Otherwise advance to the    // next thread and remove ours. If the thread    // is not at the head of the list, just dequeue    // it.    thread->queue = NULL;        if( queue == thread )    {        if( thread->next == thread )        {            queue = NULL;            return;        }        else queue = thread->next;    }    thread->Cyg_SchedThread_Implementation::remove();}// -------------------------------------------------------------------------// Rotate the front thread on the queue to the back.void Cyg_ThreadQueue_Implementation::rotate(){    CYG_REPORT_FUNCTION();            queue = queue->next;}// -------------------------------------------------------------------------#endif// -------------------------------------------------------------------------// EOF sched/lottery.cxx

⌨️ 快捷键说明

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