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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [include/] [smp.hxx] - Blame information for rev 1254

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

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

powered by: WebSVN 2.1.0

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