#ifndef CYGONCE_KERNEL_MLQUEUE_HXX #define CYGONCE_KERNEL_MLQUEUE_HXX //========================================================================== // // mlqueue.hxx // // Multi-Level Queue scheduler class declarations // //========================================================================== // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later // version. // // eCos is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with eCos; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // As a special exception, if other files instantiate templates or use // macros or inline functions from this file, or you compile this file // and link it with other works to produce a work based on this file, // this file does not by itself cause the resulting work to be covered by // the GNU General Public License. However the source code for this file // must still be made available in accordance with section (3) of the GNU // General Public License v2. // // This exception does not invalidate any other reasons why a work based // on this file might be covered by the GNU General Public License. // ------------------------------------------- // ####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: jlarmour // Date: 1997-09-10 // Purpose: Define multilevel queue scheduler implementation // Description: The classes defined here are used as base classes // by the common classes that define schedulers and thread // things. The MLQ scheduler in various configurations // provides standard FIFO, round-robin and single priority // schedulers. // Usage: Included according to configuration by // // //####DESCRIPTIONEND#### // //========================================================================== #include #include // List implementation // ------------------------------------------------------------------------- // The macro CYGNUM_KERNEL_SCHED_PRIORITIES contains the number of priorities // supported by the scheduler. #ifndef CYGNUM_KERNEL_SCHED_PRIORITIES #define CYGNUM_KERNEL_SCHED_PRIORITIES 32 // define a default #endif // set bitmap size #define CYGNUM_KERNEL_SCHED_BITMAP_SIZE CYGNUM_KERNEL_SCHED_PRIORITIES // ------------------------------------------------------------------------- // The macro CYGNUM_KERNEL_SCHED_BITMAP_SIZE contains the number of bits that the // scheduler bitmap should contain. It is derived from the number of prioirity // levels defined by the configuration. #if CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 8 typedef cyg_ucount8 cyg_sched_bitmap; #elif CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 16 typedef cyg_ucount16 cyg_sched_bitmap; #elif CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 32 typedef cyg_ucount32 cyg_sched_bitmap; #else #error Bitmaps greater than 32 bits not currently allowed #endif // ------------------------------------------------------------------------- // Customize the scheduler #define CYGIMP_THREAD_PRIORITY 1 // Threads have changable priorities #define CYG_THREAD_MIN_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES-1) #define CYG_THREAD_MAX_PRIORITY 0 // set default scheduling info value for thread constructors. #define CYG_SCHED_DEFAULT_INFO CYG_THREAD_MAX_PRIORITY // ------------------------------------------------------------------------- // scheduler Run queue object typedef Cyg_CList_T Cyg_RunQueue; // ------------------------------------------------------------------------- // Thread queue implementation. // This class provides the (scheduler specific) implementation of the // thread queue class. class Cyg_ThreadQueue_Implementation : public Cyg_CList_T { friend class Cyg_Scheduler_Implementation; friend class Cyg_SchedThread_Implementation; void set_thread_queue(Cyg_Thread *thread, Cyg_ThreadQueue *tq ); protected: // API used by Cyg_ThreadQueue Cyg_ThreadQueue_Implementation() {}; // Constructor // Add thread to queue void enqueue(Cyg_Thread *thread); // return first thread on queue Cyg_Thread *highpri(); // remove first thread on queue Cyg_Thread *dequeue(); // Remove thread from queue void remove(Cyg_Thread *thread); }; // ------------------------------------------------------------------------- // This class contains the implementation details of the scheduler, and // provides a standard API for accessing it. class Cyg_Scheduler_Implementation : public Cyg_Scheduler_Base { friend class Cyg_ThreadQueue_Implementation; friend class Cyg_SchedThread_Implementation; friend class Cyg_HardwareThread; friend void cyg_scheduler_set_need_reschedule(); // Mask of which run queues have ready threads cyg_sched_bitmap queue_map; // Each run queue is a double linked circular list of threads. // These pointers point to the head element of each list. Cyg_RunQueue run_queue[CYGNUM_KERNEL_SCHED_PRIORITIES]; #ifdef CYGPKG_KERNEL_SMP_SUPPORT // In SMP systems we additionally keep a counter for each priority // of the number of pending but not running threads in each queue. cyg_uint32 pending[CYGNUM_KERNEL_SCHED_PRIORITIES]; cyg_sched_bitmap pending_map; #endif protected: #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE // Timeslice counter. This is decremented on each // clock tick, and a timeslice is performed each // time it zeroes. static cyg_ucount32 timeslice_count[CYGNUM_KERNEL_CPU_MAX] CYGBLD_ANNOTATE_VARIABLE_SCHED; #endif Cyg_Scheduler_Implementation(); // Constructor // The following functions provide the scheduler implementation // interface to the Cyg_Scheduler class. These are protected // so that only the scheduler can call them. // choose a new thread Cyg_Thread *schedule(); // make thread schedulable void add_thread(Cyg_Thread *thread); // make thread un-schedulable void rem_thread(Cyg_Thread *thread); // register thread with scheduler void register_thread(Cyg_Thread *thread); // deregister thread void deregister_thread(Cyg_Thread *thread); // Test the given priority for uniqueness cyg_bool unique( cyg_priority priority); // Set need_reschedule if the supplied thread is of lower // priority than any that are currently running. static void set_need_reschedule( Cyg_Thread *thread ); static void set_need_reschedule(); public: void set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu ); #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE // If timeslicing is enbled, define a scheduler // entry points to do timeslicing. This will be // called from the RTC DSR. public: void timeslice(); void timeslice_cpu(); #endif }; // ------------------------------------------------------------------------- // Cyg_Scheduler_Implementation inlines inline void Cyg_Scheduler_Implementation::set_need_reschedule() { need_reschedule[CYG_KERNEL_CPU_THIS()] = true; } // ------------------------------------------------------------------------- // Scheduler thread implementation. // This class provides the implementation of the scheduler specific parts // of each thread. class Cyg_SchedThread_Implementation : public Cyg_DNode_T { friend class Cyg_Scheduler_Implementation; friend class Cyg_ThreadQueue_Implementation; protected: cyg_priority priority; // current thread priority #ifdef CYGPKG_KERNEL_SMP_SUPPORT HAL_SMP_CPU_TYPE cpu; // CPU id of cpu currently running // this thread, or CYG_KERNEL_CPU_NONE // if not running. #endif Cyg_SchedThread_Implementation(CYG_ADDRWORD sched_info); void yield(); // Yield CPU to next thread static void rotate_queue( cyg_priority pri ); // Rotate that run queue void to_queue_head( void ); // Move this thread to the head // of its queue (not necessarily // a scheduler queue) #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE cyg_ucount32 timeslice_count; void timeslice_save(); void timeslice_restore(); void timeslice_reset(); #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE // This defines whether this thread is subject to timeslicing. // If false, timeslice expiry has no effect on the thread. cyg_bool timeslice_enabled; public: void timeslice_enable(); void timeslice_disable(); #endif #else inline void timeslice_save() {}; inline void timeslice_restore() {}; inline void timeslice_reset() {}; #endif }; // ------------------------------------------------------------------------- // Cyg_SchedThread_Implementation inlines. #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE inline void Cyg_SchedThread_Implementation::timeslice_save() { timeslice_count = Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()]; } inline void Cyg_SchedThread_Implementation::timeslice_restore() { Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()] = timeslice_count; } inline void Cyg_SchedThread_Implementation::timeslice_reset() { timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS; } #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE inline void Cyg_SchedThread_Implementation::timeslice_enable() { timeslice_enabled = true; } inline void Cyg_SchedThread_Implementation::timeslice_disable() { timeslice_enabled = false; } #endif #endif // ------------------------------------------------------------------------- #endif // ifndef CYGONCE_KERNEL_MLQUEUE_HXX // EOF mlqueue.hxx