1 #ifndef CYGONCE_KERNEL_MLQUEUE_HXX
2 #define CYGONCE_KERNEL_MLQUEUE_HXX
4 //==========================================================================
8 // Multi-Level Queue scheduler class declarations
10 //==========================================================================
11 //####ECOSGPLCOPYRIGHTBEGIN####
12 // -------------------------------------------
13 // This file is part of eCos, the Embedded Configurable Operating System.
14 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
39 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40 // at http://sources.redhat.com/ecos/ecos-license/
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //==========================================================================
44 //#####DESCRIPTIONBEGIN####
47 // Contributors: jlarmour
49 // Purpose: Define multilevel queue scheduler implementation
50 // Description: The classes defined here are used as base classes
51 // by the common classes that define schedulers and thread
52 // things. The MLQ scheduler in various configurations
53 // provides standard FIFO, round-robin and single priority
55 // Usage: Included according to configuration by
56 // <cyg/kernel/sched.hxx>
58 //####DESCRIPTIONEND####
60 //==========================================================================
62 #include <cyg/kernel/ktypes.h>
64 #include <cyg/infra/clist.hxx> // List implementation
66 // -------------------------------------------------------------------------
67 // The macro CYGNUM_KERNEL_SCHED_PRIORITIES contains the number of priorities
68 // supported by the scheduler.
70 #ifndef CYGNUM_KERNEL_SCHED_PRIORITIES
71 #define CYGNUM_KERNEL_SCHED_PRIORITIES 32 // define a default
75 #define CYGNUM_KERNEL_SCHED_BITMAP_SIZE CYGNUM_KERNEL_SCHED_PRIORITIES
77 // -------------------------------------------------------------------------
78 // The macro CYGNUM_KERNEL_SCHED_BITMAP_SIZE contains the number of bits that the
79 // scheduler bitmap should contain. It is derived from the number of prioirity
80 // levels defined by the configuration.
82 #if CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 8
83 typedef cyg_ucount8 cyg_sched_bitmap;
84 #elif CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 16
85 typedef cyg_ucount16 cyg_sched_bitmap;
86 #elif CYGNUM_KERNEL_SCHED_BITMAP_SIZE <= 32
87 typedef cyg_ucount32 cyg_sched_bitmap;
89 #error Bitmaps greater than 32 bits not currently allowed
92 // -------------------------------------------------------------------------
93 // Customize the scheduler
95 #define CYGIMP_THREAD_PRIORITY 1 // Threads have changable priorities
97 #define CYG_THREAD_MIN_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES-1)
98 #define CYG_THREAD_MAX_PRIORITY 0
100 // set default scheduling info value for thread constructors.
101 #define CYG_SCHED_DEFAULT_INFO CYG_THREAD_MAX_PRIORITY
103 // -------------------------------------------------------------------------
104 // scheduler Run queue object
106 typedef Cyg_CList_T<Cyg_Thread> Cyg_RunQueue;
108 // -------------------------------------------------------------------------
109 // Thread queue implementation.
110 // This class provides the (scheduler specific) implementation of the
111 // thread queue class.
113 class Cyg_ThreadQueue_Implementation
114 : public Cyg_CList_T<Cyg_Thread>
116 friend class Cyg_Scheduler_Implementation;
117 friend class Cyg_SchedThread_Implementation;
119 void set_thread_queue(Cyg_Thread *thread,
120 Cyg_ThreadQueue *tq );
124 // API used by Cyg_ThreadQueue
126 Cyg_ThreadQueue_Implementation() {}; // Constructor
128 // Add thread to queue
129 void enqueue(Cyg_Thread *thread);
131 // return first thread on queue
132 Cyg_Thread *highpri();
134 // remove first thread on queue
135 Cyg_Thread *dequeue();
137 // Remove thread from queue
138 void remove(Cyg_Thread *thread);
142 // -------------------------------------------------------------------------
143 // This class contains the implementation details of the scheduler, and
144 // provides a standard API for accessing it.
146 class Cyg_Scheduler_Implementation
147 : public Cyg_Scheduler_Base
149 friend class Cyg_ThreadQueue_Implementation;
150 friend class Cyg_SchedThread_Implementation;
151 friend class Cyg_HardwareThread;
152 friend void cyg_scheduler_set_need_reschedule();
154 // Mask of which run queues have ready threads
155 cyg_sched_bitmap queue_map;
157 // Each run queue is a double linked circular list of threads.
158 // These pointers point to the head element of each list.
159 Cyg_RunQueue run_queue[CYGNUM_KERNEL_SCHED_PRIORITIES];
161 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
163 // In SMP systems we additionally keep a counter for each priority
164 // of the number of pending but not running threads in each queue.
166 cyg_uint32 pending[CYGNUM_KERNEL_SCHED_PRIORITIES];
168 cyg_sched_bitmap pending_map;
174 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
176 // Timeslice counter. This is decremented on each
177 // clock tick, and a timeslice is performed each
180 static cyg_ucount32 timeslice_count[CYGNUM_KERNEL_CPU_MAX]
181 CYGBLD_ANNOTATE_VARIABLE_SCHED;
185 Cyg_Scheduler_Implementation(); // Constructor
187 // The following functions provide the scheduler implementation
188 // interface to the Cyg_Scheduler class. These are protected
189 // so that only the scheduler can call them.
191 // choose a new thread
192 Cyg_Thread *schedule();
194 // make thread schedulable
195 void add_thread(Cyg_Thread *thread);
197 // make thread un-schedulable
198 void rem_thread(Cyg_Thread *thread);
200 // register thread with scheduler
201 void register_thread(Cyg_Thread *thread);
204 void deregister_thread(Cyg_Thread *thread);
206 // Test the given priority for uniqueness
207 cyg_bool unique( cyg_priority priority);
209 // Set need_reschedule if the supplied thread is of lower
210 // priority than any that are currently running.
211 static void set_need_reschedule( Cyg_Thread *thread );
212 static void set_need_reschedule();
215 void set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu );
217 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
219 // If timeslicing is enbled, define a scheduler
220 // entry points to do timeslicing. This will be
221 // called from the RTC DSR.
224 void timeslice_cpu();
230 // -------------------------------------------------------------------------
231 // Cyg_Scheduler_Implementation inlines
233 inline void Cyg_Scheduler_Implementation::set_need_reschedule()
235 need_reschedule[CYG_KERNEL_CPU_THIS()] = true;
239 // -------------------------------------------------------------------------
240 // Scheduler thread implementation.
241 // This class provides the implementation of the scheduler specific parts
244 class Cyg_SchedThread_Implementation
245 : public Cyg_DNode_T<Cyg_Thread>
247 friend class Cyg_Scheduler_Implementation;
248 friend class Cyg_ThreadQueue_Implementation;
252 cyg_priority priority; // current thread priority
254 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
255 HAL_SMP_CPU_TYPE cpu; // CPU id of cpu currently running
256 // this thread, or CYG_KERNEL_CPU_NONE
260 Cyg_SchedThread_Implementation(CYG_ADDRWORD sched_info);
262 void yield(); // Yield CPU to next thread
264 static void rotate_queue( cyg_priority pri );
265 // Rotate that run queue
267 void to_queue_head( void ); // Move this thread to the head
268 // of its queue (not necessarily
269 // a scheduler queue)
271 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
273 cyg_ucount32 timeslice_count;
275 void timeslice_save();
277 void timeslice_restore();
279 void timeslice_reset();
281 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
283 // This defines whether this thread is subject to timeslicing.
284 // If false, timeslice expiry has no effect on the thread.
286 cyg_bool timeslice_enabled;
290 void timeslice_enable();
292 void timeslice_disable();
298 inline void timeslice_save() {};
299 inline void timeslice_restore() {};
300 inline void timeslice_reset() {};
306 // -------------------------------------------------------------------------
307 // Cyg_SchedThread_Implementation inlines.
309 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
311 inline void Cyg_SchedThread_Implementation::timeslice_save()
313 timeslice_count = Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()];
316 inline void Cyg_SchedThread_Implementation::timeslice_restore()
318 Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()] = timeslice_count;
321 inline void Cyg_SchedThread_Implementation::timeslice_reset()
323 timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
326 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
328 inline void Cyg_SchedThread_Implementation::timeslice_enable()
330 timeslice_enabled = true;
333 inline void Cyg_SchedThread_Implementation::timeslice_disable()
335 timeslice_enabled = false;
343 // -------------------------------------------------------------------------
344 #endif // ifndef CYGONCE_KERNEL_MLQUEUE_HXX