Mercurial > flash_v2
diff packages/kernel/current/include/thread.hxx @ 0:3111d98ba7b3 ecos-v1_1-release
Initial commit of eCos version 1.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 11:16:07 +0000 |
| parents | |
| children | 443894e2e912 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/kernel/current/include/thread.hxx @@ -0,0 +1,540 @@ +#ifndef CYGONCE_KERNEL_THREAD_HXX +#define CYGONCE_KERNEL_THREAD_HXX + +//========================================================================== +// +// thread.hxx +// +// Thread class declarations +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Cygnus eCos Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://sourceware.cygnus.com/ecos +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Cygnus Operating System, released +// September 30, 1998. +// +// The Initial Developer of the Original Code is Cygnus. Portions created +// by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 1997-09-09 +// Purpose: Define Thread class interfaces +// Description: The classes defined here collectively implement the +// internal API used to create, configure and manage threads. +// Usage: #include <cyg/kernel/thread.hxx> +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/kernel/ktypes.h> +#include <cyg/infra/cyg_ass.h> // assertion macros +#include <cyg/kernel/sched.hxx> +#include <cyg/kernel/clock.hxx> +#include <cyg/kernel/except.hxx> + +#include <cyg/hal/hal_arch.h> + +// ------------------------------------------------------------------------- +// Miscellaneous types + +typedef void cyg_thread_entry(CYG_ADDRWORD data);// Thread entry point function + +// ------------------------------------------------------------------------- +// Hardware thread interface. +// The implementation of this class is provided by the HAL. + +class Cyg_HardwareThread +{ + friend class Cyg_Scheduler; + +protected: + + CYG_ADDRESS stack_base; // pointer to base of stack area + + cyg_uint32 stack_size; // size of stack area in bytes + +#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT + CYG_ADDRESS stack_limit; // movable stack limit +#endif + + CYG_ADDRESS stack_ptr; // pointer to saved state on stack + + cyg_thread_entry *entry_point; // main entry point (code pointer!) + + CYG_ADDRWORD entry_data; // entry point argument + +#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT + + HAL_SavedRegisters *saved_context; // If non-zero, this points at a more + // interesting context than stack_ptr. +#endif + + Cyg_HardwareThread( + cyg_thread_entry *entry_point, // entry point function + CYG_ADDRWORD entry_data, // entry data + cyg_ucount32 stack_size = 0, // stack size, 0 = use default + CYG_ADDRESS stack_base = 0 // stack base, NULL = allocate + ); + + // Thread entry point. This is where all threads begin execution. + // This routine does a little housekeeping and then call the main + // entry_point specified above. + static void thread_entry(Cyg_Thread *thread); + + // Initialize the context of the thread to start execution at thread_entry + void init_context( Cyg_Thread *thread ); + + // Save current thread's context and load that of the given next thread. + void switch_context(Cyg_HardwareThread *next); + + // load this thread's context without saving current context + void load_context(); + + // attach a stack to this thread + void attach_stack(CYG_ADDRESS stack, cyg_uint32 stack_size); + + // detach the stack from this thread + CYG_ADDRESS detach_stack(); + + // Adjust the thread's saved state to call the exception + // handler when next executed. + void prepare_exception ( + cyg_exception_handler *exception_handler, + CYG_ADDRWORD exception_data, + cyg_code exception_number, + CYG_ADDRWORD exception_info + ); + +public: + + CYGDBG_DEFINE_CHECK_THIS + + // Get and set entry_data. + + void set_entry_data( CYG_ADDRWORD data ); + + CYG_ADDRWORD get_entry_data(); + +#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT + // Return the current saved state for this thread. + HAL_SavedRegisters *get_saved_context(); + + // Set the saved context pointer. + void set_saved_context(HAL_SavedRegisters *ctx); +#endif + + // get the size/base of this thread's stack + CYG_ADDRESS get_stack_base(); + + cyg_uint32 get_stack_size(); + +#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT + // Allocate some memory at the lower end of the stack + // by moving the stack limit pointer. + + void *increment_stack_limit( cyg_ucount32 size); + + CYG_ADDRESS get_stack_limit(); +#endif +}; + +// ------------------------------------------------------------------------- +// Per-thread timer support class. +// This is only included when required. + +#ifdef CYGFUN_KERNEL_THREADS_TIMER + +class Cyg_ThreadTimer + : public Cyg_Alarm +{ + friend class Cyg_Thread; + + // Pointer to current thread + Cyg_Thread *thread; + + // Constructor + Cyg_ThreadTimer( + Cyg_Thread *thread + ); + + // Alarm function + static void alarm( Cyg_Alarm *alarm, CYG_ADDRWORD data); + + CYGDBG_DEFINE_CHECK_THIS + +}; + +#endif + +// ------------------------------------------------------------------------- +// Main Thread class. +// This provides the public API for controlling threads. + +class Cyg_Thread + : public Cyg_HardwareThread, // provides hardware abstractions + public Cyg_SchedThread // provides scheduling abstractions +{ + friend class Cyg_Scheduler; + friend void deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); + + // The following definitions are used by all variants of the + // basic thread object. + +public: + enum { // Thread state values + + RUNNING = 0, // Thread is runnable or running + SLEEPING = 1, // Thread is waiting for something to happen + COUNTSLEEP = 2, // Sleep in counted manner + SUSPENDED = 4, // Suspend count is non-zero + CREATING = 8, // Thread is being created + EXITED = 16, // Thread has exited + + // This is the set of bits that must be cleared by a generic + // wake() or release(). + SLEEPSET = (SLEEPING | COUNTSLEEP) + }; + +private: + // Current thread state, a logical OR of the above values. + // Only if this word is zero can the thread execute. + cyg_uint32 state; + + // Suspension counter, if > 0, the thread is suspended + cyg_ucount32 suspend_count; + + // Wakeup counter, if > 0, sleep will not sleep, just decrement + cyg_ucount32 wakeup_count; + + // A word of data used in syncronization object to communicate + // information between sleepers and wakers. + CYG_ADDRWORD wait_info; + + // Unique thread id assigned on creation + cyg_uint16 unique_id; + +#ifdef CYGPKG_KERNEL_EXCEPTIONS + + // If exceptions are supported, define an exception control + // object that will be used to manage and deliver them. If + // exceptions are global there is a single static instance + // of this object, if they are per-thread then there is one + // for each thread. +private: + +#ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL + static +#endif + Cyg_Exception_Control exception_control; + +public: + + static void register_exception( + cyg_code exception_number, // exception number + cyg_exception_handler handler, // handler function + CYG_ADDRWORD data, // data argument + cyg_exception_handler **old_handler, // handler function + CYG_ADDRWORD *old_data // data argument + ); + + static void deregister_exception( + cyg_code exception_number // exception number + ); + + void deliver_exception( + cyg_code exception_number, // exception being raised + CYG_ADDRWORD exception_info // exception specific info + ); + +#endif + + +public: + + CYGDBG_DEFINE_CHECK_THIS + + // Constructor, Initialize the thread structure. The thread is + // created in suspended state, and needs to be resumed to execute. + // It is also started at some (configurable) default priority, which + // may need to be changed before calling resume. + + Cyg_Thread ( + cyg_thread_entry *entry, // entry point function + CYG_ADDRWORD entry_data, // entry data + cyg_ucount32 stack_size = 0, // stack size, 0 = use default + CYG_ADDRESS stack_base = 0 // stack base, NULL = allocate + ); + + Cyg_Thread ( + CYG_ADDRWORD sched_info, // Scheduling parameter(s) + cyg_thread_entry *entry, // entry point function + CYG_ADDRWORD entry_data, // entry data + char *name, // thread name + CYG_ADDRESS stack_base = 0, // stack base, NULL = allocate + cyg_ucount32 stack_size = 0 // stack size, 0 = use default + ); + + // Re-initialize the thread back to it's initial state. + void Cyg_Thread::reinitialize(); + + ~Cyg_Thread(); + + // The following are invoked implicitly on the current thread, + // hence they are static member functions. + + static void sleep(); // Put thread to sleep + + static void counted_sleep();// Decrement counter or put + // thread to sleep +#ifdef CYGFUN_KERNEL_THREADS_TIMER + static void counted_sleep( cyg_tick_count delay ); + // ...for delay ticks +#endif + + static void exit(); // Terminate thread + + static void yield(); // Yield CPU to another thread + +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE + static void rotate_queue( cyg_priority pri ); + // Rotate that run queue +#endif + + static Cyg_Thread *self(); // Return current thread + + + // The following are called on threads other than the current one. + + void wake(); // Wake this thread from sleep. + + void counted_wake(); // Increment counter or wake thread + cyg_uint32 cancel_counted_wake(); + // Cancel counted wakeups for this + // thread and return how many were + // pending + + void suspend(); // Suspend this thread: increment counter and + // deschedule. + + void resume(); // Resume this thread: decrement counter and + // reschedule if counter is zero. + + void release(); // Release thread from sleep with BREAK + // wake_reason. + + void kill(); // Kill this thread + + void force_resume(); // Resume this thread: set counter to zero. + + cyg_uint32 get_state(); // Return current thread state. + + + // Accessor functions to set and get wait_info. + + void set_wait_info(CYG_ADDRWORD data); + + CYG_ADDRWORD get_wait_info(); + + // This part of the API is used if we have a clock and want + // per-thread timers for doing delays and timeouts. + + // delay the given number of ticks + void delay( cyg_tick_count delay ); + + + enum cyg_reason // sleep/wakeup reason codes + { + NONE, // No recorded reason + WAIT, // Wait with no timeout + DELAY, // Simple time delay + TIMEOUT, // Wait with timeout/timeout expired + BREAK, // forced break out of sleep + DESTRUCT, // wait object destroyed[note] + EXIT, // forced termination + DONE // Wait/delay complete + }; + // [note] NOT the thread, some object it was waiting on. + // Thread destruction would first involve EXITing it. + +private: + +#ifdef CYGFUN_KERNEL_THREADS_TIMER + Cyg_ThreadTimer timer; // per-thread timer +#endif + + cyg_reason sleep_reason; // reason for sleeping + + cyg_reason wake_reason; // reason for waking + +#ifdef CYGIMP_THREAD_PRIORITY + +public: + + // If the scheduler implements priorities, provide + // functions to set and get it. + + void set_priority( cyg_priority pri ); + + cyg_priority get_priority(); + + // This returns the current dispatching priority of the + // thread. This may differ from the result of get_priority() + // in the presence of priority inheritance or certain + // scheduling algorithms. + cyg_priority get_current_priority(); + +#endif + +#ifdef CYGVAR_KERNEL_THREADS_DATA + +private: + // Array of single word entries for each index. + CYG_ADDRWORD thread_data[CYGNUM_KERNEL_THREADS_DATA_MAX]; + + // Map of free thread_data indexes. Each bit represents an index + // and is 1 if that index is free, and 0 if it is in use. + static cyg_ucount32 thread_data_map; + +public: + + static CYG_ADDRWORD get_data( cyg_ucount32 index ); + + static CYG_ADDRWORD *get_data_ptr( cyg_ucount32 index ); + + void set_data( cyg_ucount32 index, CYG_ADDRWORD data ); + + static cyg_ucount32 new_data_index(); + + static void free_data_index( cyg_ucount32 index ); + +#endif + +#ifdef CYGVAR_KERNEL_THREADS_NAME + +private: + // An optional thread name string, for humans to read + char *name; + +public: + // function to get the name string + char *get_name(); + +#endif + + +#ifdef CYGVAR_KERNEL_THREADS_LIST + + // Housekeeping list that tracks all threads +private: + Cyg_Thread *list_next; + static Cyg_Thread *thread_list; + + void add_to_list( void ); + void remove_from_list( void ); +public: + + static Cyg_Thread *get_list_head(); + + Cyg_Thread *get_list_next(); + +#endif + +public: + + // Set sleep reason to reason and wake reason to NONE + static void set_sleep_reason( cyg_reason reason = WAIT); + + cyg_reason get_sleep_reason(); + + // Set the wakeup reason to the given value + void set_wake_reason( cyg_reason reason = DONE); + + // Get current wake reason + cyg_reason get_wake_reason(); + + static void set_timer( // Set timeout and sleep reason + cyg_tick_count trigger, // Absolute wakeup time + cyg_reason sleep_reason // reason for sleeping + ); + + static void clear_timer(); // disable thread timer + + // Get a 16 bit unique id for this thread. This is + // used in tracing and instrumentation to identify the + // current thread. + + cyg_uint16 get_unique_id(); + +}; + +// ------------------------------------------------------------------------- +// Thread Queue class. +// This defines the main API for manipulating queues of threads. + +class Cyg_ThreadQueue + : private Cyg_ThreadQueue_Implementation +{ + +public: + + CYGDBG_DEFINE_CHECK_THIS + + // API used by rest of kernel. + + // Add thread to queue + void enqueue(Cyg_Thread *thread); + + // return first thread on queue + Cyg_Thread *highpri(); + + // remove first thread on queue + Cyg_Thread *dequeue(); + + // remove specified thread from queue + void remove(Cyg_Thread *thread); + + // test if queue is empty + cyg_bool empty(); + +}; + +// ------------------------------------------------------------------------- +// Thread inlines + +// Return current thread state. +inline cyg_uint32 Cyg_Thread::get_state() +{ + return state; +} + +inline void Cyg_Thread::set_wait_info(CYG_ADDRWORD data) +{ + wait_info = data; +} + +inline CYG_ADDRWORD Cyg_Thread::get_wait_info() +{ + return wait_info; +} + +// ------------------------------------------------------------------------- +#endif // ifndef CYGONCE_KERNEL_THREAD_HXX +// EOF thread.hxx
