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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [include/] [smp.hxx] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
#ifndef CYGONCE_KERNEL_SMP_HXX
2
#define CYGONCE_KERNEL_SMP_HXX
3
 
4
//==========================================================================
5
//
6
//      smp.hxx
7
//
8
//      SMP kernel support
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 Free Software Foundation, 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
19
// version.
20
//
21
// eCos is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License
27
// along with eCos; if not, write to the Free Software Foundation, Inc.,
28
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
29
//
30
// As a special exception, if other files instantiate templates or use
31
// macros or inline functions from this file, or you compile this file
32
// and link it with other works to produce a work based on this file,
33
// this file does not by itself cause the resulting work to be covered by
34
// the GNU General Public License. However the source code for this file
35
// must still be made available in accordance with section (3) of the GNU
36
// General Public License v2.
37
//
38
// This exception does not invalidate any other reasons why a work based
39
// on this file might be covered by the GNU General Public License.
40
// -------------------------------------------
41
// ####ECOSGPLCOPYRIGHTEND####
42
//==========================================================================
43
//#####DESCRIPTIONBEGIN####
44
//
45
// Author(s):   nickg
46
// Contributors:nickg
47
// Date:        2001-02-10
48
// Purpose:     Kernel SMP support
49
// Description: If SMP support is configured into the kernel, then this file
50
//              translates HAL defined macros into C and C++ classes and methods
51
//              that can be called from the rest of the kernel. If SMP is not
52
//              configured in, then the same classes and methods are defined here
53
//              to operate correctly in a single CPU configuration.
54
//
55
// Usage:       #include 
56
//
57
//####DESCRIPTIONEND####
58
//
59
//==========================================================================
60
 
61
#include 
62
#include           // assertion macros
63
 
64
#include            // HAL_DISABLE_INTERRUPTS() etc.
65
 
66
#include 
67
 
68
//==========================================================================
69
 
70
#if defined(CYGPKG_KERNEL_SMP_SUPPORT) && (CYGPKG_HAL_SMP_SUPPORT)
71
 
72
//==========================================================================
73
// SMP support is included
74
 
75
#define CYG_KERNEL_SMP_ENABLED
76
 
77
// -------------------------------------------------------------------------
78
// Get HAL support
79
 
80
#include 
81
 
82
// -------------------------------------------------------------------------
83
// Defined values
84
// These all just map straight through to the HAL.
85
 
86
#define CYGNUM_KERNEL_CPU_MAX           HAL_SMP_CPU_MAX
87
 
88
#define CYG_KERNEL_CPU_COUNT()          HAL_SMP_CPU_COUNT()
89
 
90
#define CYG_KERNEL_CPU_THIS()           HAL_SMP_CPU_THIS()
91
 
92
#define CYG_KERNEL_CPU_NONE             HAL_SMP_CPU_NONE
93
 
94
// -------------------------------------------------------------------------
95
// CPU control
96
 
97
#define CYG_KERNEL_CPU_START( __cpu ) HAL_SMP_CPU_START( __cpu )
98
 
99
#define CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait ) \
100
        HAL_SMP_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait )
101
 
102
#define CYG_KERNEL_CPU_TIMESLICE_INTERRUPT( __cpu, __wait ) \
103
        HAL_SMP_CPU_TIMESLICE_INTERRUPT( __cpu, __wait )
104
 
105
// -------------------------------------------------------------------------
106
// Scheduler lock default implementation.
107
 
108
// This implementation should serve for most targets. However, some
109
// targets may have hardware or other features that make simple
110
// spinlocks impossible, or allow us to implement the scheduler lock
111
// in a more efficient manner. If that is the case then the HAL will
112
// implement these macros itself.
113
 
114
#ifndef HAL_SMP_SCHEDLOCK_DATA_TYPE
115
 
116
#define HAL_SMP_SCHEDLOCK_DATA_TYPE struct hal_smp_schedlock_data_type
117
 
118
struct hal_smp_schedlock_data_type {
119
    HAL_SPINLOCK_TYPE           spinlock;
120
    volatile HAL_SMP_CPU_TYPE   holder;
121
};
122
 
123
#define HAL_SMP_SCHEDLOCK_INIT( __lock, __data )        \
124
CYG_MACRO_START                                         \
125
{                                                       \
126
    __lock = 1;                                         \
127
    HAL_SPINLOCK_CLEAR(__data.spinlock);                \
128
    HAL_SPINLOCK_SPIN(__data.spinlock);                 \
129
    __data.holder = HAL_SMP_CPU_THIS();                 \
130
}                                                       \
131
CYG_MACRO_END
132
 
133
 
134
#define HAL_SMP_SCHEDLOCK_INC( __lock, __data )                 \
135
CYG_MACRO_START                                                 \
136
{                                                               \
137
    CYG_INTERRUPT_STATE __state;                                \
138
    HAL_DISABLE_INTERRUPTS(__state);                            \
139
    if( __data.holder == HAL_SMP_CPU_THIS() )                   \
140
        __lock++;                                               \
141
    else                                                        \
142
    {                                                           \
143
        CYG_INSTRUMENT_SMP(LOCK_WAIT,CYG_KERNEL_CPU_THIS(),0);  \
144
        HAL_SPINLOCK_SPIN(__data.spinlock);                     \
145
        __data.holder = HAL_SMP_CPU_THIS();                     \
146
        __lock++;                                               \
147
        CYG_INSTRUMENT_SMP(LOCK_GOT,CYG_KERNEL_CPU_THIS(),0);   \
148
    }                                                           \
149
    HAL_RESTORE_INTERRUPTS(__state);                            \
150
}                                                               \
151
CYG_MACRO_END
152
 
153
#define HAL_SMP_SCHEDLOCK_ZERO( __lock, __data )                                                 \
154
CYG_MACRO_START                                                                                  \
155
{                                                                                                \
156
    CYG_INTERRUPT_STATE __state;                                                                 \
157
    HAL_DISABLE_INTERRUPTS(__state);                                                             \
158
    CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Zeroing schedlock not owned by me!");      \
159
    __lock = 0;                                                                                  \
160
    __data.holder = HAL_SMP_CPU_NONE;                                                            \
161
    HAL_SPINLOCK_CLEAR(__data.spinlock);                                                         \
162
    HAL_RESTORE_INTERRUPTS(__state);                                                             \
163
}                                                                                                \
164
CYG_MACRO_END
165
 
166
#define HAL_SMP_SCHEDLOCK_SET( __lock, __data, __new )                                          \
167
CYG_MACRO_START                                                                                 \
168
{                                                                                               \
169
    CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Setting schedlock not owned by me!");     \
170
    __lock = __new;                                                                             \
171
}                                                                                               \
172
CYG_MACRO_END
173
 
174
#endif
175
 
176
// -------------------------------------------------------------------------
177
// SpinLock class
178
// This class supplies a C++ wrapper for the HAL spinlock API.
179
 
180
#ifdef __cplusplus
181
 
182
#ifdef HAL_SPINLOCK_SPIN
183
 
184
class Cyg_SpinLock
185
{
186
    HAL_SPINLOCK_TYPE   lock;
187
 
188
public:
189
 
190
    // Constructor, initialize the lock to clear
191
    Cyg_SpinLock() { lock = HAL_SPINLOCK_INIT_CLEAR; };
192
 
193
    ~Cyg_SpinLock()
194
    {
195
//        CYG_ASSERT( !test(), "spinlock still claimed");
196
    };
197
 
198
    // Spin on the lock.
199
    void spin()
200
    {
201
        HAL_SPINLOCK_SPIN(lock);
202
    };
203
 
204
    // Clear the lock.
205
    void clear()
206
    {
207
        HAL_SPINLOCK_CLEAR(lock);
208
    };
209
 
210
    // Try to claim the lock. Return true if successful, false if not.
211
    cyg_bool trylock()
212
    {
213
        cyg_bool testval;
214
        HAL_SPINLOCK_TRY(lock,testval);
215
        return testval;
216
    };
217
 
218
    // Test the current value of the lock
219
    cyg_bool test()
220
    {
221
        cyg_bool testval;
222
        HAL_SPINLOCK_TEST(lock, testval);
223
        return testval;
224
    };
225
 
226
 
227
    // The following two member functions are only necessary if the
228
    // spinlock is to be used in an ISR.
229
 
230
    // Claim the spinlock, but also mask this CPU's interrupts while
231
    // we have it.
232
    void spin_intsave(CYG_INTERRUPT_STATE *state)
233
    {
234
        CYG_INTERRUPT_STATE s;
235
        HAL_DISABLE_INTERRUPTS(s);
236
        *state = s;
237
        spin();
238
    };
239
 
240
    // Clear the lock, and restore the interrupt state saved in
241
    // spin_intsave().
242
    void clear_intsave(CYG_INTERRUPT_STATE state)
243
    {
244
        clear();
245
        HAL_RESTORE_INTERRUPTS(state);
246
    };
247
};
248
 
249
#endif
250
 
251
// -------------------------------------------------------------------------
252
// Scheduler lock class
253
// This uses the scheduler lock API defined by the HAL, or the defaults
254
// defined above.
255
 
256
class Cyg_Scheduler_SchedLock
257
{
258
    static volatile cyg_ucount32 sched_lock         // lock counter
259
                    CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock )
260
                    CYGBLD_ANNOTATE_VARIABLE_SCHED
261
                    ;
262
 
263
    static HAL_SMP_SCHEDLOCK_DATA_TYPE lock_data
264
                                       CYGBLD_ANNOTATE_VARIABLE_SCHED;
265
 
266
protected:
267
 
268
    Cyg_Scheduler_SchedLock()
269
    {
270
        HAL_SMP_SCHEDLOCK_INIT( sched_lock, lock_data );
271
    };
272
 
273
    // Increment the scheduler lock. If this takes the lock from zero
274
    // to one then this code must also do whatever is necessary to
275
    // serialize CPUs through the scheduler.
276
    static void inc_sched_lock()
277
    {
278
        CYG_INSTRUMENT_SMP(LOCK_INC,CYG_KERNEL_CPU_THIS(),0);
279
        HAL_SMP_SCHEDLOCK_INC( sched_lock, lock_data );
280
    };
281
 
282
    // Zero the scheduler lock. This will release the CPU serializing
283
    // lock and allow another CPU in.
284
    static void zero_sched_lock()
285
    {
286
        CYG_INSTRUMENT_SMP(LOCK_ZERO,CYG_KERNEL_CPU_THIS(),0);
287
        CYG_ASSERT( sched_lock != 0, "Scheduler lock already zero");
288
        HAL_SMP_SCHEDLOCK_ZERO( sched_lock, lock_data );
289
    };
290
 
291
    // Set the scheduler lock to a non-zero value. Both the scheduler
292
    // lock and the new value must be non-zero.
293
    static void set_sched_lock(cyg_uint32 new_lock)
294
    {
295
        CYG_INSTRUMENT_SMP(LOCK_SET,CYG_KERNEL_CPU_THIS(),new_lock);
296
        CYG_ASSERT( new_lock > 0, "New scheduler lock value == 0");
297
        CYG_ASSERT( sched_lock > 0, "Scheduler lock == 0");
298
        HAL_SMP_SCHEDLOCK_SET( sched_lock, lock_data, new_lock );
299
    };
300
 
301
    static cyg_ucount32 get_sched_lock()
302
    {
303
        return sched_lock;
304
    };
305
};
306
 
307
#define CYGIMP_KERNEL_SCHED_LOCK_DEFINITIONS                    \
308
volatile cyg_ucount32 Cyg_Scheduler_SchedLock::sched_lock = 1;  \
309
HAL_SMP_SCHEDLOCK_DATA_TYPE Cyg_Scheduler_SchedLock::lock_data;
310
 
311
#endif // __cplusplus
312
 
313
// -------------------------------------------------------------------------
314
 
315
#else // defined(CYGSEM_KERNEL_SMP_SUPPORT) && (CYGSEM_HAL_SMP_SUPPORT)
316
 
317
//==========================================================================
318
// SMP support is NOT included.
319
 
320
#undef CYG_KERNEL_SMP_ENABLED
321
 
322
// -------------------------------------------------------------------------
323
// Defined values
324
// Supply a set of values that describe a single CPU system.
325
 
326
#ifndef HAL_SMP_CPU_TYPE
327
#define HAL_SMP_CPU_TYPE                cyg_uint32
328
#endif
329
 
330
#define CYGNUM_KERNEL_CPU_MAX           1
331
 
332
#define CYG_KERNEL_CPU_COUNT()          1
333
 
334
#define CYG_KERNEL_CPU_THIS()           0
335
 
336
#define CYG_KERNEL_CPU_NONE             -1
337
 
338
#define CYG_KERNEL_CPU_LOWPRI()         CYG_KERNEL_CPU_THIS()
339
 
340
// -------------------------------------------------------------------------
341
// SpinLock class
342
// This single CPU version simply goes through the motions of setting
343
// and clearing the lock variable for debugging purposes.
344
 
345
#ifdef __cplusplus
346
 
347
class Cyg_SpinLock
348
{
349
    volatile cyg_uint32 lock;
350
 
351
public:
352
 
353
    // Constructor, initialize the lock to clear
354
    Cyg_SpinLock() { lock = 0; };
355
 
356
    ~Cyg_SpinLock()
357
    {
358
        CYG_ASSERT( lock == 0, "spinlock still claimed");
359
    };
360
 
361
    // Spin on the lock. In this case we just set it to 1 and proceed.
362
    void spin()
363
    {
364
        CYG_ASSERT( lock == 0, "spinlock already claimed!");
365
        lock = 1;
366
    };
367
 
368
    // Clear the lock. Again, just set the value.
369
    void clear()
370
    {
371
        CYG_ASSERT( lock != 0, "spinlock already cleared!");
372
        lock = 0;
373
    };
374
 
375
    // Try to claim the lock. Return true if successful, false if not.
376
    cyg_bool trylock()
377
    {
378
        if( lock ) return false;
379
        else { lock = 1; return true; }
380
    };
381
 
382
    // Test the current value of the lock
383
    cyg_bool test() { return lock; };
384
 
385
 
386
    // The following two member functions are only necessary if the
387
    // spinlock is to be used in an ISR.
388
 
389
    // Claim the spinlock, but also mask this CPU's interrupts while
390
    // we have it.
391
    void spin_intsave(CYG_INTERRUPT_STATE *state)
392
    {
393
        CYG_INTERRUPT_STATE s;
394
        HAL_DISABLE_INTERRUPTS(s);
395
        *state = s;
396
        spin();
397
    };
398
 
399
    // Clear the lock, and restore the interrupt state saved in
400
    // spin_intsave().
401
    void clear_intsave(CYG_INTERRUPT_STATE state)
402
    {
403
        clear();
404
        HAL_RESTORE_INTERRUPTS(state);
405
    };
406
 
407
};
408
 
409
// -------------------------------------------------------------------------
410
// Scheduler lock class
411
 
412
class Cyg_Scheduler_SchedLock
413
{
414
    static volatile cyg_ucount32 sched_lock         // lock counter
415
                    CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock )
416
                    CYGBLD_ANNOTATE_VARIABLE_SCHED
417
                    ;
418
 
419
    // For non-SMP versions, the code here does the basic and obvious things.
420
protected:
421
 
422
    Cyg_Scheduler_SchedLock()
423
    {
424
        sched_lock = 1;
425
    };
426
 
427
    // Increment the scheduler lock, possibly taking it from zero to
428
    // one.
429
    static void inc_sched_lock()
430
    {
431
        sched_lock++;
432
    };
433
 
434
    static void zero_sched_lock()
435
    {
436
        CYG_ASSERT( sched_lock != 0, "Scheduler lock already zero");
437
        sched_lock = 0;
438
    };
439
 
440
    // Set the scheduler lock to a non-zero value. Both the scheduler
441
    // lock and the new value must be non-zero.
442
    static void set_sched_lock(cyg_uint32 new_lock)
443
    {
444
        CYG_ASSERT( new_lock > 0, "New scheduler lock value == 0");
445
        CYG_ASSERT( sched_lock > 0, "Scheduler lock == 0");
446
        sched_lock = new_lock;
447
    };
448
 
449
    static cyg_ucount32 get_sched_lock()
450
    {
451
        return sched_lock;
452
    };
453
};
454
 
455
#define CYGIMP_KERNEL_SCHED_LOCK_DEFINITIONS                    \
456
volatile cyg_ucount32 Cyg_Scheduler_SchedLock::sched_lock = 1;
457
 
458
#endif // __cplusplus
459
 
460
#endif // defined(CYGSEM_KERNEL_SMP_SUPPORT) && (CYGSEM_HAL_SMP_SUPPORT)
461
 
462
// -------------------------------------------------------------------------
463
#endif // ifndef CYGONCE_KERNEL_SMP_HXX
464
 
465
// EOF smp.hxx

powered by: WebSVN 2.1.0

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