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/] [include/] [thread.hxx] - Blame information for rev 307

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

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_KERNEL_THREAD_HXX
2
#define CYGONCE_KERNEL_THREAD_HXX
3
 
4
//==========================================================================
5
//
6
//      thread.hxx
7
//
8
//      Thread 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:        nickg
48
// Date:        1997-09-09
49
// Purpose:     Define Thread class interfaces
50
// Description: The classes defined here collectively implement the
51
//              internal API used to create, configure and manage threads.
52
// Usage:       #include 
53
//
54
//####DESCRIPTIONEND####
55
//
56
//==========================================================================
57
 
58
#include 
59
#include          // assertion macros
60
#include 
61
#include 
62
#include 
63
 
64
#include 
65
 
66
// -------------------------------------------------------------------------
67
// Miscellaneous types
68
 
69
typedef void cyg_thread_entry(CYG_ADDRWORD data);// Thread entry point function
70
 
71
// -------------------------------------------------------------------------
72
// Hardware thread interface.
73
// The implementation of this class is provided by the HAL.
74
 
75
class Cyg_HardwareThread
76
{
77
    friend class Cyg_Scheduler;
78
 
79
protected:
80
 
81
    CYG_ADDRESS         stack_base;     // pointer to base of stack area
82
 
83
    cyg_uint32          stack_size;     // size of stack area in bytes
84
 
85
#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
86
    CYG_ADDRESS         stack_limit;    // movable stack limit
87
#endif
88
 
89
    CYG_ADDRESS         stack_ptr;      // pointer to saved state on stack
90
 
91
    cyg_thread_entry    *entry_point;   // main entry point (code pointer!)
92
 
93
    CYG_ADDRWORD        entry_data;     // entry point argument
94
 
95
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
96
 
97
    HAL_SavedRegisters  *saved_context; // If non-zero, this points at a more
98
                                        // interesting context than stack_ptr.
99
#endif
100
 
101
    Cyg_HardwareThread(
102
        cyg_thread_entry        *entry_point,   // entry point function
103
        CYG_ADDRWORD            entry_data,     // entry data
104
        cyg_ucount32            stack_size = 0, // stack size, 0 = use default
105
        CYG_ADDRESS             stack_base = 0  // stack base, NULL = allocate
106
    );
107
 
108
    // Thread entry point. This is where all threads begin execution.
109
    // This routine does a little housekeeping and then call the main
110
    // entry_point specified above.
111
    static void thread_entry(Cyg_Thread *thread);
112
 
113
    // Initialize the context of the thread to start execution at thread_entry
114
    void    init_context( Cyg_Thread *thread );
115
 
116
    // Save current thread's context and load that of the given next thread.
117
    void    switch_context(Cyg_HardwareThread *next);
118
 
119
    // attach a stack to this thread
120
    void    attach_stack(CYG_ADDRESS stack, cyg_uint32 stack_size);
121
 
122
    // detach the stack from this thread
123
    CYG_ADDRESS detach_stack();
124
 
125
    // Adjust the thread's saved state to call the exception
126
    // handler when next executed.
127
    void    prepare_exception (
128
        cyg_exception_handler   *exception_handler,
129
        CYG_ADDRWORD            exception_data,
130
        cyg_code                exception_number,
131
        CYG_ADDRWORD            exception_info
132
        );
133
 
134
public:
135
 
136
    CYGDBG_DEFINE_CHECK_THIS
137
 
138
    // Get and set entry_data.
139
 
140
    void set_entry_data( CYG_ADDRWORD data );
141
 
142
    CYG_ADDRWORD get_entry_data();
143
 
144
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
145
    // Return the current saved state for this thread.
146
    HAL_SavedRegisters *get_saved_context();
147
 
148
    // Set the saved context pointer.
149
    void set_saved_context(HAL_SavedRegisters *ctx);
150
#endif
151
 
152
    // get the size/base of this thread's stack
153
    CYG_ADDRESS get_stack_base();
154
 
155
    cyg_uint32 get_stack_size();
156
 
157
#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
158
    // Allocate some memory at the lower end of the stack
159
    // by moving the stack limit pointer.
160
 
161
    void *increment_stack_limit( cyg_ucount32 size);
162
 
163
    CYG_ADDRESS get_stack_limit();
164
#endif
165
 
166
#ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
167
 
168
    inline void check_stack(void);
169
 
170
#endif
171
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
172
 
173
    inline cyg_uint32 measure_stack_usage(void);
174
 
175
#endif
176
};
177
 
178
// -------------------------------------------------------------------------
179
// Per-thread timer support class.
180
// This is only included when required.
181
 
182
#ifdef CYGFUN_KERNEL_THREADS_TIMER
183
 
184
class Cyg_ThreadTimer
185
    : public Cyg_Alarm
186
{
187
    friend class Cyg_Thread;
188
 
189
    // Pointer to current thread
190
    Cyg_Thread          *thread;
191
 
192
    // Constructor
193
    Cyg_ThreadTimer(
194
        Cyg_Thread      *thread
195
        );
196
 
197
    // Alarm function
198
    static void alarm( Cyg_Alarm *alarm, CYG_ADDRWORD data);
199
 
200
    CYGDBG_DEFINE_CHECK_THIS
201
 
202
};
203
 
204
#endif
205
 
206
// -------------------------------------------------------------------------
207
// Main Thread class.
208
// This provides the public API for controlling threads.
209
 
210
class Cyg_Thread
211
    : public Cyg_HardwareThread,       // provides hardware abstractions
212
      public Cyg_SchedThread           // provides scheduling abstractions
213
{
214
    friend class Cyg_Scheduler;
215
    friend void deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
216
 
217
    // The following definitions are used by all variants of the
218
    // basic thread object.
219
 
220
public:
221
    enum {                       // Thread state values
222
 
223
        RUNNING    = 0,          // Thread is runnable or running
224
        SLEEPING   = 1,          // Thread is waiting for something to happen
225
        COUNTSLEEP = 2,          // Sleep in counted manner
226
        SUSPENDED  = 4,          // Suspend count is non-zero
227
        CREATING   = 8,          // Thread is being created
228
        EXITED     = 16,         // Thread has exited
229
 
230
        // This is the set of bits that must be cleared by a generic
231
        // wake() or release().
232
        SLEEPSET   = (SLEEPING | COUNTSLEEP)
233
    };
234
 
235
private:
236
    // Current thread state, a logical OR of the above values.
237
    // Only if this word is zero can the thread execute.
238
    cyg_uint32                  state;
239
 
240
    // Suspension counter, if > 0, the thread is suspended
241
    cyg_ucount32                suspend_count;
242
 
243
    // Wakeup counter, if > 0, sleep will not sleep, just decrement
244
    cyg_ucount32                wakeup_count;
245
 
246
    // A word of data used in syncronization object to communicate
247
    // information between sleepers and wakers.
248
    CYG_ADDRWORD                wait_info;
249
 
250
    // Unique thread id assigned on creation
251
    cyg_uint16                  unique_id;
252
 
253
#ifdef CYGPKG_KERNEL_EXCEPTIONS
254
 
255
    // If exceptions are supported, define an exception control
256
    // object that will be used to manage and deliver them. If
257
    // exceptions are global there is a single static instance
258
    // of this object, if they are per-thread then there is one
259
    // for each thread.
260
private:
261
 
262
#ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
263
    static
264
#endif
265
    Cyg_Exception_Control       exception_control;
266
 
267
public:
268
 
269
    static void register_exception(
270
        cyg_code                exception_number,       // exception number
271
        cyg_exception_handler   handler,                // handler function
272
        CYG_ADDRWORD            data,                   // data argument
273
        cyg_exception_handler   **old_handler,          // handler function
274
        CYG_ADDRWORD            *old_data               // data argument
275
        );
276
 
277
    static void deregister_exception(
278
        cyg_code                exception_number        // exception number
279
        );
280
 
281
    void deliver_exception(
282
        cyg_code            exception_number,       // exception being raised
283
        CYG_ADDRWORD        exception_info          // exception specific info
284
        );
285
 
286
#endif
287
 
288
 
289
public:
290
 
291
    CYGDBG_DEFINE_CHECK_THIS
292
 
293
    // Constructor, Initialize the thread structure. The thread is
294
    // created in suspended state, and needs to be resumed to execute.
295
    // It is also started at some (configurable) default priority, which
296
    // may need to be changed before calling resume.
297
 
298
    Cyg_Thread (
299
        cyg_thread_entry        *entry,         // entry point function
300
        CYG_ADDRWORD            entry_data,     // entry data
301
        cyg_ucount32            stack_size = 0, // stack size, 0 = use default
302
        CYG_ADDRESS             stack_base = 0  // stack base, NULL = allocate
303
        );
304
 
305
    Cyg_Thread (
306
        CYG_ADDRWORD            sched_info,     // Scheduling parameter(s)
307
        cyg_thread_entry        *entry,         // entry point function
308
        CYG_ADDRWORD            entry_data,     // entry data
309
        char                    *name,          // thread name
310
        CYG_ADDRESS             stack_base = 0, // stack base, NULL = allocate
311
        cyg_ucount32            stack_size = 0  // stack size, 0 = use default
312
        );
313
 
314
    // Re-initialize the thread back to it's initial state.
315
    void Cyg_Thread::reinitialize();
316
 
317
    ~Cyg_Thread();
318
 
319
    // The following are invoked implicitly on the current thread,
320
    // hence they are static member functions.
321
 
322
    static void         sleep();        // Put thread to sleep
323
 
324
    static void         counted_sleep();// Decrement counter or put
325
                                        // thread to sleep
326
#ifdef CYGFUN_KERNEL_THREADS_TIMER
327
    static void         counted_sleep( cyg_tick_count delay );
328
                                        // ...for delay ticks
329
#endif
330
 
331
    static void         exit();         // Terminate thread
332
 
333
    static void         yield();        // Yield CPU to another thread
334
 
335
    static void         rotate_queue( cyg_priority pri );
336
                                        // Rotate that run queue
337
 
338
    void                to_queue_head( void );
339
                                        // Move to the head of its queue
340
                                        // (not necessarily a scheduler q)
341
 
342
    static Cyg_Thread   *self();        // Return current thread
343
 
344
 
345
    // The following are called on threads other than the current one.
346
 
347
    void                wake();         // Wake this thread from sleep.
348
 
349
    void                counted_wake(); // Increment counter or wake thread
350
    cyg_uint32          cancel_counted_wake();
351
                                        // Cancel counted wakeups for this
352
                                        // thread and return how many were
353
                                        // pending
354
 
355
    void                suspend();      // Suspend this thread: increment counter and
356
                                        // deschedule.
357
 
358
    void                resume();       // Resume this thread: decrement counter and
359
                                        // reschedule if counter is zero.
360
 
361
    void                release();      // Release thread from sleep with BREAK
362
                                        // wake_reason.
363
 
364
    void                kill();         // Kill this thread
365
 
366
    void                force_resume(); // Resume this thread: set counter to zero.
367
 
368
    cyg_uint32          get_state();    // Return current thread state.
369
 
370
 
371
    // Accessor functions to set and get wait_info.
372
 
373
    void                set_wait_info(CYG_ADDRWORD data);
374
 
375
    CYG_ADDRWORD        get_wait_info();
376
 
377
    // This part of the API is used if we have a clock and want
378
    // per-thread timers for doing delays and timeouts.
379
 
380
    // delay the given number of ticks
381
    void delay( cyg_tick_count delay );
382
 
383
 
384
    enum cyg_reason                     // sleep/wakeup reason codes
385
    {
386
        NONE,                           // No recorded reason
387
        WAIT,                           // Wait with no timeout
388
        DELAY,                          // Simple time delay
389
        TIMEOUT,                        // Wait with timeout/timeout expired
390
        BREAK,                          // forced break out of sleep
391
        DESTRUCT,                       // wait object destroyed[note]
392
        EXIT,                           // forced termination
393
        DONE                            // Wait/delay complete
394
    };
395
    // [note] NOT the thread, some object it was waiting on.
396
    //        Thread destruction would first involve EXITing it.
397
 
398
private:
399
 
400
#ifdef CYGFUN_KERNEL_THREADS_TIMER
401
    Cyg_ThreadTimer     timer;          // per-thread timer
402
#endif
403
 
404
    cyg_reason          sleep_reason;   // reason for sleeping
405
 
406
    cyg_reason          wake_reason;    // reason for waking
407
 
408
#ifdef CYGIMP_THREAD_PRIORITY
409
 
410
public:
411
 
412
    // If the scheduler implements priorities, provide
413
    // functions to set and get it.
414
 
415
    void set_priority( cyg_priority pri );
416
 
417
    cyg_priority get_priority();
418
 
419
    // This returns the current dispatching priority of the
420
    // thread. This may differ from the result of get_priority()
421
    // in the presence of priority inheritance or certain
422
    // scheduling algorithms.
423
    cyg_priority get_current_priority();
424
 
425
#endif
426
 
427
#ifdef CYGVAR_KERNEL_THREADS_DATA
428
 
429
private:
430
    // Array of single word entries for each index.
431
    CYG_ADDRWORD        thread_data[CYGNUM_KERNEL_THREADS_DATA_MAX];
432
 
433
    // Map of free thread_data indexes. Each bit represents an index
434
    // and is 1 if that index is free, and 0 if it is in use.
435
    static cyg_ucount32        thread_data_map;
436
 
437
public:
438
 
439
    typedef cyg_count32 cyg_data_index;
440
 
441
    static CYG_ADDRWORD get_data( cyg_data_index index );
442
 
443
    static CYG_ADDRWORD *get_data_ptr( cyg_data_index index );
444
 
445
    void                set_data( cyg_data_index index, CYG_ADDRWORD data );
446
 
447
    // returns -1 if no more indexes available
448
    static cyg_data_index new_data_index();
449
 
450
    static void         free_data_index( cyg_data_index index );
451
 
452
#endif
453
 
454
#ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS
455
 
456
    // thread destructors, called on thread exit.
457
private:
458
    typedef void (*destructor_fn)(CYG_ADDRWORD);
459
    struct Cyg_Destructor_Entry {
460
        destructor_fn fn;
461
        CYG_ADDRWORD data;
462
    };
463
#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
464
    static
465
#endif
466
    Cyg_Destructor_Entry destructors[ CYGNUM_KERNEL_THREADS_DESTRUCTORS ];
467
public:
468
 
469
    // Add and remove destructors. Returns true on success, false on failure.
470
#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
471
    static
472
#endif
473
    cyg_bool     add_destructor( destructor_fn fn, CYG_ADDRWORD data );
474
#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
475
    static
476
#endif
477
    cyg_bool     rem_destructor( destructor_fn fn, CYG_ADDRWORD data );
478
#endif
479
 
480
#ifdef CYGVAR_KERNEL_THREADS_NAME
481
 
482
private:
483
    // An optional thread name string, for humans to read
484
    char                        *name;
485
 
486
public:
487
    // function to get the name string
488
    char                        *get_name();
489
 
490
#endif
491
 
492
 
493
#ifdef CYGVAR_KERNEL_THREADS_LIST
494
 
495
        // Housekeeping list that tracks all threads
496
private:
497
    Cyg_Thread                  *list_next;
498
    static Cyg_Thread           *thread_list;
499
 
500
    void                        add_to_list(      void );
501
    void                        remove_from_list( void );
502
public:
503
 
504
    static Cyg_Thread           *get_list_head();
505
 
506
    Cyg_Thread                  *get_list_next();
507
 
508
#endif
509
 
510
public:
511
 
512
    // Set sleep reason to reason and wake reason to NONE
513
    static void set_sleep_reason( cyg_reason reason = WAIT);
514
 
515
    cyg_reason get_sleep_reason();
516
 
517
    // Set the wakeup reason to the given value
518
    void set_wake_reason( cyg_reason reason = DONE);
519
 
520
    // Get current wake reason
521
    cyg_reason get_wake_reason();
522
 
523
    static void set_timer(              // Set timeout and sleep reason
524
        cyg_tick_count  trigger,        // Absolute wakeup time
525
        cyg_reason      sleep_reason    // reason for sleeping
526
        );
527
 
528
    static void clear_timer();          // disable thread timer
529
 
530
    // Get a 16 bit unique id for this thread. This is
531
    // used in tracing and instrumentation to identify the
532
    // current thread.
533
 
534
    cyg_uint16 get_unique_id();
535
 
536
};
537
 
538
// -------------------------------------------------------------------------
539
// Thread Queue class.
540
// This defines the main API for manipulating queues of threads.
541
 
542
class Cyg_ThreadQueue
543
    : public Cyg_ThreadQueue_Implementation
544
{
545
 
546
public:
547
 
548
    CYGDBG_DEFINE_CHECK_THIS
549
 
550
    // API used by rest of kernel.
551
 
552
                        // Add thread to queue
553
    void                enqueue(Cyg_Thread *thread);
554
 
555
                        // return first thread on queue
556
    Cyg_Thread          *highpri();
557
 
558
                        // remove first thread on queue
559
    Cyg_Thread          *dequeue();
560
 
561
                        // remove specified thread from queue
562
    void                remove(Cyg_Thread *thread);
563
 
564
                        // test if queue is empty
565
    cyg_bool            empty();
566
 
567
};
568
 
569
// -------------------------------------------------------------------------
570
// Thread inlines
571
 
572
// Return current thread state.
573
inline cyg_uint32 Cyg_Thread::get_state()
574
{
575
    return state;
576
}
577
 
578
inline void Cyg_Thread::set_wait_info(CYG_ADDRWORD data)
579
{
580
    wait_info = data;
581
}
582
 
583
inline CYG_ADDRWORD Cyg_Thread::get_wait_info()
584
{
585
    return wait_info;
586
}
587
 
588
// -------------------------------------------------------------------------
589
#endif // ifndef CYGONCE_KERNEL_THREAD_HXX
590
// EOF thread.hxx

powered by: WebSVN 2.1.0

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