]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/kernel/v2_0/include/thread.hxx
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / kernel / v2_0 / include / thread.hxx
1 #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 <cyg/kernel/thread.hxx>
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57
58 #include <cyg/kernel/ktypes.h>
59 #include <cyg/infra/cyg_ass.h>         // assertion macros
60 #include <cyg/kernel/sched.hxx>
61 #include <cyg/kernel/clock.hxx>
62 #include <cyg/kernel/except.hxx>
63
64 #include <cyg/hal/hal_arch.h>
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 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     inline 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