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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [src/] [sched/] [lottery.cxx] - Blame information for rev 228

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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