]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/kernel/v2_0/include/mlqueue.hxx
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / kernel / v2_0 / include / mlqueue.hxx
1 #ifndef CYGONCE_KERNEL_MLQUEUE_HXX
2 #define CYGONCE_KERNEL_MLQUEUE_HXX
3
4 //==========================================================================
5 //
6 //      mlqueue.hxx
7 //
8 //      Multi-Level Queue scheduler class declarations
9 //
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.
15 //
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.
19 //
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
23 // for more details.
24 //
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.
28 //
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.
35 //
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.
38 //
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####
45 //
46 // Author(s):    nickg
47 // Contributors: jlarmour
48 // Date:         1997-09-10
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
54 //               schedulers.
55 // Usage:        Included according to configuration by
56 //               <cyg/kernel/sched.hxx>
57 //
58 //####DESCRIPTIONEND####
59 //
60 //==========================================================================
61
62 #include <cyg/kernel/ktypes.h>
63
64 #include <cyg/infra/clist.hxx>                  // List implementation
65
66 // -------------------------------------------------------------------------
67 // The macro CYGNUM_KERNEL_SCHED_PRIORITIES contains the number of priorities
68 // supported by the scheduler.
69
70 #ifndef CYGNUM_KERNEL_SCHED_PRIORITIES
71 #define CYGNUM_KERNEL_SCHED_PRIORITIES 32       // define a default
72 #endif
73
74 // set bitmap size
75 #define CYGNUM_KERNEL_SCHED_BITMAP_SIZE CYGNUM_KERNEL_SCHED_PRIORITIES
76
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.
81
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;
88 #else
89 #error Bitmaps greater than 32 bits not currently allowed
90 #endif
91
92 // -------------------------------------------------------------------------
93 // Customize the scheduler
94
95 #define CYGIMP_THREAD_PRIORITY  1       // Threads have changable priorities
96
97 #define CYG_THREAD_MIN_PRIORITY (CYGNUM_KERNEL_SCHED_PRIORITIES-1)
98 #define CYG_THREAD_MAX_PRIORITY 0
99
100 // set default scheduling info value for thread constructors.
101 #define CYG_SCHED_DEFAULT_INFO  CYG_THREAD_MAX_PRIORITY
102
103 // -------------------------------------------------------------------------
104 // scheduler Run queue object
105
106 typedef Cyg_CList_T<Cyg_Thread> Cyg_RunQueue;
107
108 // -------------------------------------------------------------------------
109 // Thread queue implementation.
110 // This class provides the (scheduler specific) implementation of the
111 // thread queue class.
112
113 class Cyg_ThreadQueue_Implementation
114     : public Cyg_CList_T<Cyg_Thread>
115 {
116     friend class Cyg_Scheduler_Implementation;
117     friend class Cyg_SchedThread_Implementation;
118
119     void                set_thread_queue(Cyg_Thread *thread,
120                                          Cyg_ThreadQueue *tq );
121
122 protected:
123
124     // API used by Cyg_ThreadQueue
125
126     Cyg_ThreadQueue_Implementation() {};   // Constructor
127     
128                                         // Add thread to queue
129     void                enqueue(Cyg_Thread *thread);
130
131                                         // return first thread on queue
132     Cyg_Thread          *highpri();
133
134                                         // remove first thread on queue    
135     Cyg_Thread          *dequeue();
136
137                                         // Remove thread from queue
138     void                remove(Cyg_Thread *thread);
139
140 };
141
142 // -------------------------------------------------------------------------
143 // This class contains the implementation details of the scheduler, and
144 // provides a standard API for accessing it.
145
146 class Cyg_Scheduler_Implementation
147     : public Cyg_Scheduler_Base
148 {
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();
153     
154     // Mask of which run queues have ready threads
155     cyg_sched_bitmap    queue_map;
156
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];
160
161 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
162
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.
165     
166     cyg_uint32 pending[CYGNUM_KERNEL_SCHED_PRIORITIES];
167
168     cyg_sched_bitmap pending_map;
169
170 #endif    
171
172 protected:
173     
174 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
175
176     // Timeslice counter. This is decremented on each
177     // clock tick, and a timeslice is performed each
178     // time it zeroes.
179     
180     static cyg_ucount32 timeslice_count[CYGNUM_KERNEL_CPU_MAX]
181                                         CYGBLD_ANNOTATE_VARIABLE_SCHED;
182
183 #endif
184
185     Cyg_Scheduler_Implementation();     // Constructor
186     
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.
190     
191     // choose a new thread
192     Cyg_Thread  *schedule();
193
194     // make thread schedulable
195     void        add_thread(Cyg_Thread *thread);
196
197     // make thread un-schedulable
198     void        rem_thread(Cyg_Thread *thread);
199
200     // register thread with scheduler
201     void        register_thread(Cyg_Thread *thread);
202
203     // deregister thread
204     void        deregister_thread(Cyg_Thread *thread);
205     
206     // Test the given priority for uniqueness
207     cyg_bool    unique( cyg_priority priority);
208
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();
213
214 public:
215     void set_idle_thread( Cyg_Thread *thread, HAL_SMP_CPU_TYPE cpu );
216     
217 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
218
219     // If timeslicing is enbled, define a scheduler
220     // entry points to do timeslicing. This will be
221     // called from the RTC DSR.
222 public:    
223     void timeslice();
224     void timeslice_cpu();
225
226 #endif
227
228 };
229
230 // -------------------------------------------------------------------------
231 // Cyg_Scheduler_Implementation inlines
232
233 inline void Cyg_Scheduler_Implementation::set_need_reschedule()
234 {
235     need_reschedule[CYG_KERNEL_CPU_THIS()] = true;
236 }
237
238
239 // -------------------------------------------------------------------------
240 // Scheduler thread implementation.
241 // This class provides the implementation of the scheduler specific parts
242 // of each thread.
243
244 class Cyg_SchedThread_Implementation
245     : public Cyg_DNode_T<Cyg_Thread>
246 {
247     friend class Cyg_Scheduler_Implementation;
248     friend class Cyg_ThreadQueue_Implementation;
249
250 protected:
251
252     cyg_priority        priority;       // current thread priority
253
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
257                                         // if not running.
258 #endif
259     
260     Cyg_SchedThread_Implementation(CYG_ADDRWORD sched_info);
261
262     void yield();                       // Yield CPU to next thread
263
264     static void rotate_queue( cyg_priority pri );
265                                         // Rotate that run queue
266
267     void to_queue_head( void );         // Move this thread to the head
268                                         // of its queue (not necessarily
269                                         // a scheduler queue)
270
271 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
272
273     cyg_ucount32 timeslice_count;
274         
275     void timeslice_save();
276
277     void timeslice_restore();
278     
279     void timeslice_reset();
280
281 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
282
283     // This defines whether this thread is subject to timeslicing.
284     // If false, timeslice expiry has no effect on the thread.
285     
286     cyg_bool            timeslice_enabled;
287
288 public:
289     
290     void timeslice_enable();
291
292     void timeslice_disable();
293     
294 #endif
295
296 #else
297
298     inline void timeslice_save() {};
299     inline void timeslice_restore() {};
300     inline void timeslice_reset() {};
301     
302 #endif    
303        
304 };
305
306 // -------------------------------------------------------------------------
307 // Cyg_SchedThread_Implementation inlines.
308
309 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
310
311 inline void Cyg_SchedThread_Implementation::timeslice_save()
312 {
313     timeslice_count = Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()];
314 }
315
316 inline void Cyg_SchedThread_Implementation::timeslice_restore()
317 {
318     Cyg_Scheduler_Implementation::timeslice_count[CYG_KERNEL_CPU_THIS()] = timeslice_count;
319 }
320
321 inline void Cyg_SchedThread_Implementation::timeslice_reset()
322 {
323     timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
324 }
325
326 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE_ENABLE
327
328 inline void Cyg_SchedThread_Implementation::timeslice_enable()
329 {
330     timeslice_enabled = true;
331 }
332
333 inline void Cyg_SchedThread_Implementation::timeslice_disable()
334 {
335     timeslice_enabled = false;
336 }
337
338 #endif
339
340 #endif
341
342
343 // -------------------------------------------------------------------------
344 #endif // ifndef CYGONCE_KERNEL_MLQUEUE_HXX
345 // EOF mlqueue.hxx