OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [src/] [sched/] [lottery.cxx] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      sched/lottery.cxx
4
//
5
//      Lottery scheduler class implementation
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   nickg
43
// Contributors:        nickg
44
// Date:        1997-09-16
45
// Purpose:     Lottery scheduler class implementation
46
// Description: This file contains the implementations of
47
//              Cyg_Scheduler_Implementation and
48
//              Cyg_SchedThread_Implementation.
49
//              
50
//
51
//####DESCRIPTIONEND####
52
//
53
//==========================================================================
54
 
55
#include <pkgconf/kernel.h>
56
 
57
#include <cyg/kernel/ktypes.h>         // base kernel types
58
#include <cyg/infra/cyg_trac.h>        // tracing macros
59
#include <cyg/infra/cyg_ass.h>         // assertion macros
60
 
61
#include <cyg/kernel/sched.hxx>        // our header
62
#include <cyg/kernel/intr.hxx>         // interrupt defines, for Cyg_HAL_Clock
63
 
64
#include <cyg/hal/hal_arch.h>          // Architecture specific definitions
65
 
66
 
67
#include <cyg/kernel/thread.inl>       // thread inlines
68
#include <cyg/kernel/sched.inl>        // scheduler inlines
69
 
70
#ifdef CYGSEM_KERNEL_SCHED_LOTTERY
71
 
72
#define CYG_ENABLE_TRACE 1
73
 
74
//==========================================================================
75
// Cyg_Scheduler_Implementation class static members
76
 
77
#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
78
 
79
cyg_count32 Cyg_Scheduler_Implementation::timeslice_count =
80
                                        CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
81
 
82
#endif
83
 
84
//==========================================================================
85
// Cyg_Scheduler_Implementation class members
86
 
87
// -------------------------------------------------------------------------
88
// Constructor.
89
 
90
Cyg_Scheduler_Implementation::Cyg_Scheduler_Implementation()
91
{
92
    CYG_REPORT_FUNCTION();
93
 
94
    total_tickets = 0;
95
    rand_seed = 1;
96
}
97
 
98
// -------------------------------------------------------------------------
99
// Choose the best thread to run next
100
 
101
Cyg_Thread *Cyg_Scheduler_Implementation::schedule()
102
{
103
    CYG_REPORT_FUNCTION();
104
 
105
#ifdef CYGPKG_HAL_POWERPC
106
 
107
    // PowerPc specific version of random number generator.
108
    register cyg_int32 r1 asm("r4");
109
    r1 = rand_seed;
110
    asm(
111
        "li     7,0;"
112
        "ori    7,7,33614;"
113
        "mulhwu 5,7,%0;"
114
        "mullw  6,7,%0;"
115
        "srawi  6,6,1;"
116
        "add    %0,5,6;"
117
        "cmpwi  %0,0;"
118
        "bge    1f;"
119
        "slwi   %0,%0,1;"
120
        "srwi   %0,%0,1;"
121
        "addi   %0,%0,1;"
122
        "1:;"
123
        : "=r"(r1)
124
        : "0"(r1)
125
        : "r5", "r6", "r7"
126
        );
127
    rand_seed = r1;
128
 
129
#else
130
#if 1
131
    rand_seed = (rand_seed * 1103515245) + 1234;
132
    cyg_int32 r1 = rand_seed & 0x7FFFFFFF;
133
#else    
134
    // Generic implementation of RNG.
135
#if( CYG_BYTEORDER == CYG_MSBFIRST )
136
#define _LO 1    
137
#define _HI 0
138
#else
139
#define _LO 0    
140
#define _HI 1
141
#endif    
142
    union { cyg_int64 r64; cyg_int32 r32[2]; } u;
143
    u.r64 = (cyg_int64)rand_seed * 33614LL;
144
    cyg_int32 r1 = u.r32[_HI] + (u.r32[_LO]>>1);
145
    if( r1 < 0 )
146
        r1 = (r1 & 0x7FFFFFFF) + 1;
147
    rand_seed = r1;
148
#undef _LO
149
#undef _HI
150
#endif    
151
#endif    
152
 
153
    cyg_int32 ticket = r1 % total_tickets;
154
    cyg_int32 tick = ticket;
155
    Cyg_Thread *thread = run_queue.highpri();
156
 
157
    // Search the run queue for the thread with the
158
    // given ticket.
159
    while( ticket > 0 )
160
    {
161
        ticket -= thread->priority;
162
        if( ticket <= 0 ) break;
163
        thread = thread->next;
164
 
165
        CYG_ASSERT( thread != run_queue.highpri(), "Looping in scheduler");
166
    }
167
 
168
    CYG_TRACE3( CYG_ENABLE_TRACE,
169
        "seed %08x ticket %d thread %08x",
170
        rand_seed, tick, thread);
171
 
172
    // If the thread has any compensation tickets, take them away since
173
    // it has just won.
174
 
175
    if( thread->compensation_tickets > 0 )
176
    {
177
        thread->priority -= thread->compensation_tickets;
178
        total_tickets -= thread->compensation_tickets;
179
        thread->compensation_tickets = 0;
180
    }
181
 
182
    // Re-insert thread at head of list. This reduces runtime by
183
    // putting the large ticket holders at the front of the list.
184
 
185
//    run_queue.remove(thread);
186
//    run_queue.enqueue(thread);
187
 
188
    CYG_CHECK_DATA_PTR( thread, "Invalid next thread pointer");
189
    CYG_ASSERTCLASS( thread, "Bad next thread" );
190
 
191
    return thread;
192
}
193
 
194
// -------------------------------------------------------------------------
195
 
196
void Cyg_Scheduler_Implementation::add_thread(Cyg_Thread *thread)
197
{
198
    CYG_REPORT_FUNCTION();
199
 
200
    // If the thread is on some other queue, remove it
201
    // here.
202
    if( thread->queue != NULL )
203
    {
204
        thread->queue->remove(thread);
205
        thread->queue = NULL;
206
    }
207
 
208
    total_tickets += thread->priority;
209
 
210
    run_queue.enqueue(thread);
211
}
212
 
213
// -------------------------------------------------------------------------
214
 
215
void Cyg_Scheduler_Implementation::rem_thread(Cyg_Thread *thread)
216
{
217
    CYG_REPORT_FUNCTION();
218
 
219
    run_queue.remove(thread);
220
 
221
    total_tickets -= thread->priority;
222
 
223
    // Compensate the thread for the segment of the quantum that
224
    // it used. This makes it more likely to win the lottery next time
225
    // it is scheduled. We only do this for threads that have voluntarily
226
    // given up the CPU.
227
 
228
//    if( thread->get_state() != Cyg_Thread::RUNNING )
229
    {
230
#if 0        
231
        cyg_uint32 hal_ticks;
232
        HAL_CLOCK_READ( &hal_ticks );
233
        thread->compensation_tickets = thread->priority *
234
            CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / hal_ticks;
235
#else
236
        thread->compensation_tickets = (thread->priority *
237
            CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS) / timeslice_count;
238
 
239
#endif        
240
        thread->priority += thread->compensation_tickets;
241
    }
242
}
243
 
244
// -------------------------------------------------------------------------
245
// register thread with scheduler
246
 
247
void Cyg_Scheduler_Implementation::register_thread(Cyg_Thread *thread)
248
{
249
    CYG_REPORT_FUNCTION();
250
 
251
    // No registration necessary in this scheduler
252
}
253
 
254
// -------------------------------------------------------------------------
255
 
256
// deregister thread
257
void Cyg_Scheduler_Implementation::deregister_thread(Cyg_Thread *thread)
258
{
259
    CYG_REPORT_FUNCTION();
260
 
261
    // No registration necessary in this scheduler    
262
}
263
 
264
// -------------------------------------------------------------------------
265
// Test the given priority for uniqueness
266
 
267
cyg_bool Cyg_Scheduler_Implementation::unique( cyg_priority priority)
268
{
269
    CYG_REPORT_FUNCTION();
270
 
271
    // Priorities are not unique
272
    return true;
273
}
274
 
275
//==========================================================================
276
// Support for timeslicing option
277
 
278
#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
279
 
280
void Cyg_Scheduler_Implementation::timeslice()
281
{
282
    CYG_REPORT_FUNCTION();
283
 
284
    if( --timeslice_count <= 0 )
285
    {
286
        CYG_INSTRUMENT_SCHED(TIMESLICE,0,0);
287
 
288
        // Force a reschedule on each timeslice
289
        need_reschedule = true;
290
        timeslice_count = CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS;
291
    }
292
}
293
 
294
#endif
295
 
296
//==========================================================================
297
// Cyg_Cyg_SchedThread_Implementation class members
298
 
299
Cyg_SchedThread_Implementation::Cyg_SchedThread_Implementation
300
(
301
    CYG_ADDRWORD sched_info
302
)
303
{
304
    CYG_REPORT_FUNCTION();
305
 
306
    priority = cyg_priority(sched_info);
307
 
308
    // point the next and prev field at this thread.
309
 
310
    next = prev = CYG_CLASSFROMBASE(Cyg_Thread,
311
                                    Cyg_SchedThread_Implementation,
312
                                    this);
313
}
314
 
315
// -------------------------------------------------------------------------
316
// Insert thread in front of this
317
 
318
void Cyg_SchedThread_Implementation::insert( Cyg_Thread *thread)
319
{
320
    CYG_REPORT_FUNCTION();
321
 
322
    thread->next        = CYG_CLASSFROMBASE(Cyg_Thread,
323
                                            Cyg_SchedThread_Implementation,
324
                                            this);
325
    thread->prev        = prev;
326
    prev->next          = thread;
327
    prev                = thread;
328
}
329
 
330
// -------------------------------------------------------------------------
331
// remove this from queue
332
 
333
void Cyg_SchedThread_Implementation::remove()
334
{
335
    CYG_REPORT_FUNCTION();
336
 
337
    next->prev          = prev;
338
    prev->next          = next;
339
    next = prev         = CYG_CLASSFROMBASE(Cyg_Thread,
340
                                            Cyg_SchedThread_Implementation,
341
                                            this);
342
}
343
 
344
// -------------------------------------------------------------------------
345
// Yield the processor to another thread
346
 
347
void Cyg_SchedThread_Implementation::yield()
348
{
349
    CYG_REPORT_FUNCTION();
350
 
351
 
352
}
353
 
354
//==========================================================================
355
// Cyg_ThreadQueue_Implementation class members
356
 
357
void Cyg_ThreadQueue_Implementation::enqueue(Cyg_Thread *thread)
358
{
359
    CYG_REPORT_FUNCTION();
360
 
361
    // Always put thread at head of queue
362
    if( queue == NULL ) queue = thread;
363
    else
364
    {
365
        queue->insert(thread);
366
//        queue->next->insert(thread);
367
//        queue = thread;
368
    }
369
 
370
    thread->queue = CYG_CLASSFROMBASE(Cyg_ThreadQueue,
371
                                      Cyg_ThreadQueue_Implementation,
372
                                      this);
373
}
374
 
375
// -------------------------------------------------------------------------
376
 
377
Cyg_Thread *Cyg_ThreadQueue_Implementation::dequeue()
378
{
379
    CYG_REPORT_FUNCTION();
380
 
381
    if( queue == NULL ) return NULL;
382
 
383
    Cyg_Thread *thread = queue;
384
 
385
    if( thread->next == thread )
386
    {
387
        // sole thread on list, NULL out ptr
388
        queue = NULL;
389
    }
390
    else
391
    {
392
        // advance to next and remove thread
393
        queue = thread->next;
394
        thread->remove();
395
    }
396
 
397
    thread->queue = NULL;
398
 
399
    return thread;
400
}
401
 
402
// -------------------------------------------------------------------------
403
 
404
Cyg_Thread *Cyg_ThreadQueue_Implementation::highpri()
405
{
406
    CYG_REPORT_FUNCTION();
407
 
408
    return queue;
409
}
410
 
411
// -------------------------------------------------------------------------
412
 
413
void Cyg_ThreadQueue_Implementation::remove(Cyg_Thread *thread)
414
{
415
    CYG_REPORT_FUNCTION();
416
 
417
    // If the thread we want is the at the head
418
    // of the list, and is on its own, clear the
419
    // list and return. Otherwise advance to the
420
    // next thread and remove ours. If the thread
421
    // is not at the head of the list, just dequeue
422
    // it.
423
 
424
    thread->queue = NULL;
425
 
426
    if( queue == thread )
427
    {
428
        if( thread->next == thread )
429
        {
430
            queue = NULL;
431
            return;
432
        }
433
        else queue = thread->next;
434
    }
435
 
436
    thread->Cyg_SchedThread_Implementation::remove();
437
 
438
}
439
 
440
// -------------------------------------------------------------------------
441
// Rotate the front thread on the queue to the back.
442
 
443
void Cyg_ThreadQueue_Implementation::rotate()
444
{
445
    CYG_REPORT_FUNCTION();
446
 
447
    queue = queue->next;
448
}
449
 
450
// -------------------------------------------------------------------------
451
 
452
#endif
453
 
454
// -------------------------------------------------------------------------
455
// EOF sched/lottery.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.