URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [include/] [thread.hxx] - Rev 1765
Compare with Previous | Blame | View Log
#ifndef CYGONCE_KERNEL_THREAD_HXX#define CYGONCE_KERNEL_THREAD_HXX//==========================================================================//// thread.hxx//// Thread class declarations////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####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 typestypedef 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 areacyg_uint32 stack_size; // size of stack area in bytes#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMITCYG_ADDRESS stack_limit; // movable stack limit#endifCYG_ADDRESS stack_ptr; // pointer to saved state on stackcyg_thread_entry *entry_point; // main entry point (code pointer!)CYG_ADDRWORD entry_data; // entry point argument#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORTHAL_SavedRegisters *saved_context; // If non-zero, this points at a more// interesting context than stack_ptr.#endifCyg_HardwareThread(cyg_thread_entry *entry_point, // entry point functionCYG_ADDRWORD entry_data, // entry datacyg_ucount32 stack_size = 0, // stack size, 0 = use defaultCYG_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_entryvoid init_context( Cyg_Thread *thread );// Save current thread's context and load that of the given next thread.void switch_context(Cyg_HardwareThread *next);// attach a stack to this threadvoid attach_stack(CYG_ADDRESS stack, cyg_uint32 stack_size);// detach the stack from this threadCYG_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 stackCYG_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#ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKINGinline void check_stack(void);#endif#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENTinline cyg_uint32 measure_stack_usage(void);#endif};// -------------------------------------------------------------------------// Per-thread timer support class.// This is only included when required.#ifdef CYGFUN_KERNEL_THREADS_TIMERclass Cyg_ThreadTimer: public Cyg_Alarm{friend class Cyg_Thread;// Pointer to current threadCyg_Thread *thread;// ConstructorCyg_ThreadTimer(Cyg_Thread *thread);// Alarm functionstatic 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 abstractionspublic 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 valuesRUNNING = 0, // Thread is runnable or runningSLEEPING = 1, // Thread is waiting for something to happenCOUNTSLEEP = 2, // Sleep in counted mannerSUSPENDED = 4, // Suspend count is non-zeroCREATING = 8, // Thread is being createdEXITED = 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 suspendedcyg_ucount32 suspend_count;// Wakeup counter, if > 0, sleep will not sleep, just decrementcyg_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 creationcyg_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_GLOBALstatic#endifCyg_Exception_Control exception_control;public:static void register_exception(cyg_code exception_number, // exception numbercyg_exception_handler handler, // handler functionCYG_ADDRWORD data, // data argumentcyg_exception_handler **old_handler, // handler functionCYG_ADDRWORD *old_data // data argument);static void deregister_exception(cyg_code exception_number // exception number);void deliver_exception(cyg_code exception_number, // exception being raisedCYG_ADDRWORD exception_info // exception specific info);#endifpublic: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 functionCYG_ADDRWORD entry_data, // entry datacyg_ucount32 stack_size = 0, // stack size, 0 = use defaultCYG_ADDRESS stack_base = 0 // stack base, NULL = allocate);Cyg_Thread (CYG_ADDRWORD sched_info, // Scheduling parameter(s)cyg_thread_entry *entry, // entry point functionCYG_ADDRWORD entry_data, // entry datachar *name, // thread nameCYG_ADDRESS stack_base = 0, // stack base, NULL = allocatecyg_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 sleepstatic void counted_sleep();// Decrement counter or put// thread to sleep#ifdef CYGFUN_KERNEL_THREADS_TIMERstatic void counted_sleep( cyg_tick_count delay );// ...for delay ticks#endifstatic void exit(); // Terminate threadstatic void yield(); // Yield CPU to another threadstatic void rotate_queue( cyg_priority pri );// Rotate that run queuevoid to_queue_head( void );// Move to the head of its queue// (not necessarily a scheduler q)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 threadcyg_uint32 cancel_counted_wake();// Cancel counted wakeups for this// thread and return how many were// pendingvoid 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 threadvoid 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 ticksvoid delay( cyg_tick_count delay );enum cyg_reason // sleep/wakeup reason codes{NONE, // No recorded reasonWAIT, // Wait with no timeoutDELAY, // Simple time delayTIMEOUT, // Wait with timeout/timeout expiredBREAK, // forced break out of sleepDESTRUCT, // wait object destroyed[note]EXIT, // forced terminationDONE // 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_TIMERCyg_ThreadTimer timer; // per-thread timer#endifcyg_reason sleep_reason; // reason for sleepingcyg_reason wake_reason; // reason for waking#ifdef CYGIMP_THREAD_PRIORITYpublic:// 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_DATAprivate:// 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:typedef cyg_count32 cyg_data_index;static CYG_ADDRWORD get_data( cyg_data_index index );static CYG_ADDRWORD *get_data_ptr( cyg_data_index index );void set_data( cyg_data_index index, CYG_ADDRWORD data );// returns -1 if no more indexes availablestatic cyg_data_index new_data_index();static void free_data_index( cyg_data_index index );#endif#ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS// thread destructors, called on thread exit.private:typedef void (*destructor_fn)(CYG_ADDRWORD);struct Cyg_Destructor_Entry {destructor_fn fn;CYG_ADDRWORD data;};#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREADstatic#endifCyg_Destructor_Entry destructors[ CYGNUM_KERNEL_THREADS_DESTRUCTORS ];public:// Add and remove destructors. Returns true on success, false on failure.#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREADstatic#endifcyg_bool add_destructor( destructor_fn fn, CYG_ADDRWORD data );#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREADstatic#endifcyg_bool rem_destructor( destructor_fn fn, CYG_ADDRWORD data );#endif#ifdef CYGVAR_KERNEL_THREADS_NAMEprivate:// An optional thread name string, for humans to readchar *name;public:// function to get the name stringchar *get_name();#endif#ifdef CYGVAR_KERNEL_THREADS_LIST// Housekeeping list that tracks all threadsprivate: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();#endifpublic:// Set sleep reason to reason and wake reason to NONEstatic void set_sleep_reason( cyg_reason reason = WAIT);cyg_reason get_sleep_reason();// Set the wakeup reason to the given valuevoid set_wake_reason( cyg_reason reason = DONE);// Get current wake reasoncyg_reason get_wake_reason();static void set_timer( // Set timeout and sleep reasoncyg_tick_count trigger, // Absolute wakeup timecyg_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: public Cyg_ThreadQueue_Implementation{public:CYGDBG_DEFINE_CHECK_THIS// API used by rest of kernel.// Add thread to queuevoid enqueue(Cyg_Thread *thread);// return first thread on queueCyg_Thread *highpri();// remove first thread on queueCyg_Thread *dequeue();// remove specified thread from queuevoid remove(Cyg_Thread *thread);// test if queue is emptycyg_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
