Mercurial > nand-ecoscentric
view packages/compat/uitron/current/include/uit_func.inl @ 2:443894e2e912 ecos-v1_2_1-release
Block commit of eCos version 1.2.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 12:24:34 +0000 |
| parents | 3111d98ba7b3 |
| children | ece80412419a |
line wrap: on
line source
#ifndef CYGONCE_COMPAT_UITRON_UIT_FUNC_INL #define CYGONCE_COMPAT_UITRON_UIT_FUNC_INL //=========================================================================== // // uit_func.inl // // uITRON compatibility functions // //=========================================================================== //####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,1999 Cygnus Solutions. All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### //=========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): hmt // Contributors: hmt // Date: 1998-03-13 // Purpose: uITRON compatibility functions // Description: // //####DESCRIPTIONEND#### // //=========================================================================== #ifdef CYGPKG_UITRON #ifdef CYGPRI_UITRON_FUNCS_HERE_AND_NOW #include <cyg/compat/uitron/uit_objs.hxx> // uITRON setup CYGNUM_UITRON_SEMAS // kernel facilities only needed here #include <cyg/kernel/intr.hxx> #include <cyg/kernel/sched.hxx> // and the implementations of other kernel facilities #include <cyg/kernel/thread.inl> #include <cyg/kernel/sched.inl> #include <cyg/kernel/clock.inl> // ------------------------------------------------------------------------ // The variable where dis_dsp/ena_dsp state is held: extern cyg_uint32 cyg_uitron_dis_dsp_old_priority; // ------------------------------------------------------------------------ // Parameter checking; either check the expression and return an error code // if not true, or assert the truth with a made-up message. #ifdef CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS // default: uitron error codes are returned #define CYG_UIT_PARAMCHECK( _true_, _error_ ) CYG_MACRO_START \ if ( ! (_true_) ) return (_error_); \ CYG_MACRO_END #else // ...but they are asserted if asserts are on #define CYG_UIT_PARAMCHECK( _true_, _error_ ) CYG_MACRO_START \ CYG_ASSERT( (_true_), "CYG_UIT_PARAMCHECK fail: " #_true_ ); \ CYG_MACRO_END #endif // else !CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS // ------------------------------------------------------------------------ // CYG_UITRON_CHECK_AND_GETP // // Macro to rangecheck and do the addressing of a static uitron system // object; _which_ sort of object is given, and token pasting is used // horribly to get the static array, limits and the like. // // Usage: // INT snd_msg( ID mbxid, ... ) { // Cyg_Mbox *p; // CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); // p->...(...); // internal: plain assignment to the object pointer, from static array #define CYG_UIT_SPTR( _which_, _idx_, _ptr_ ) CYG_MACRO_START \ (_ptr_) = CYG_UITRON_OBJS( _which_ ) + ((_idx_) - 1); \ CYG_MACRO_END // internal: plain assignment to the object pointer, from pointer array // with error checking. #define CYG_UIT_SPTR_PTR( _which_, _idx_, _ptr_ ) CYG_MACRO_START \ (_ptr_) = CYG_UITRON_PTRS( _which_ )[ ((_idx_) - 1) ]; \ if ( NULL == (_ptr_) ) return E_NOEXS; \ CYG_MACRO_END #define CYG_UITRON_CHECK_AND_GETP_DIRECT( _which_, _idx_, _ptr_ ) \ CYG_MACRO_START \ CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ CYG_UIT_SPTR( _which_, _idx_, _ptr_ ); \ CYG_MACRO_END #define CYG_UITRON_CHECK_AND_GETP_INDIRECT( _which_, _idx_, _ptr_ ) \ CYG_MACRO_START \ CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ CYG_UIT_SPTR_PTR( _which_, _idx_, _ptr_ ); \ CYG_MACRO_END // As above but for handler numbers which return E_PAR when out of range #define CYG_UITRON_CHECK_AND_GETHDLR( _which_, _num_, _ptr_ ) \ CYG_MACRO_START \ CYG_UIT_PARAMCHECK( 0 < (_num_), E_PAR ); \ CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_num_), E_PAR ); \ CYG_UIT_SPTR( _which_, _num_, _ptr_ ); \ CYG_MACRO_END // And a macro to check that creation of an object is OK #define CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( _which_, _idx_ ) \ CYG_MACRO_START \ CYG_UIT_PARAMCHECK( 0 < (_idx_), E_ID ); \ CYG_UIT_PARAMCHECK( CYG_UITRON_NUM( _which_ ) >= (_idx_), E_ID ); \ Cyg_Scheduler::lock(); \ if ( NULL != CYG_UITRON_PTRS( _which_ )[ ((_idx_) - 1) ] ) { \ Cyg_Scheduler::unlock(); \ return E_OBJ; \ } \ CYG_MACRO_END // define a magic new operator in order to call constructors #define CYG_UITRON_NEWFUNCTION( _class_ ) \ inline void *operator new(size_t size, _class_ *ptr) \ { \ CYG_CHECK_DATA_PTR( ptr, "Bad pointer" ); \ return ptr; \ } // now configury to support selectable create/delete support ie. an // array of pointers to the objects themselves. #ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_TASKS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( TASKS, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_TASKS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( TASKS, _idx_, _ptr_ ) #endif #ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_SEMAS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( SEMAS, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_SEMAS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( SEMAS, _idx_, _ptr_ ) #endif #ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_MBOXES( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( MBOXES, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_MBOXES( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( MBOXES, _idx_, _ptr_ ) #endif #ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_FLAGS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( FLAGS, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_FLAGS( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( FLAGS, _idx_, _ptr_ ) #endif #ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( MEMPOOLFIXED, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( MEMPOOLFIXED, _idx_, _ptr_ ) #endif #ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE #define CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_INDIRECT( MEMPOOLVAR, _idx_, _ptr_ ) #else #define CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( _idx_, _ptr_ ) \ CYG_UITRON_CHECK_AND_GETP_DIRECT( MEMPOOLVAR, _idx_, _ptr_ ) #endif // ------------------------------------------------------------------------ // Common error checking macros #if !defined( CYGSEM_UITRON_BAD_PARAMS_RETURN_ERRORS ) && \ !defined( CYGDBG_USE_ASSERTS ) // if not checking and not asserted, these are removed to avoid usused // variable warnings. #define CYG_UITRON_CHECK_TASK_CONTEXT_SELF( _self_ ) CYG_EMPTY_STATEMENT #define CYG_UITRON_CHECK_TASK_CONTEXT() CYG_EMPTY_STATEMENT #define CYG_UITRON_CHECK_DISPATCH_ENABLED() CYG_EMPTY_STATEMENT #define CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( _tmout_ ) CYG_EMPTY_STATEMENT #else // the default: // Check a task is actually a uITRON task #define CYG_UITRON_CHECK_TASK_CONTEXT_SELF( _self_ ) CYG_MACRO_START \ CYG_UIT_PARAMCHECK( \ (&cyg_uitron_TASKS[0] <= (_self_)) && \ ((_self_) < &cyg_uitron_TASKS[CYGNUM_UITRON_TASKS]), \ E_CTX ); \ CYG_MACRO_END #define CYG_UITRON_CHECK_TASK_CONTEXT() CYG_MACRO_START \ Cyg_Thread *self = Cyg_Thread::self(); \ CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); \ CYG_MACRO_END // Check dispatching is enabled for calls which might wait #define CYG_UITRON_CHECK_DISPATCH_ENABLED() CYG_MACRO_START \ CYG_UIT_PARAMCHECK( 0 == cyg_uitron_dis_dsp_old_priority, E_CTX ); \ CYG_MACRO_END #define CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO(_tmout_) CYG_MACRO_START \ CYG_UIT_PARAMCHECK( -1 <= (_tmout_), E_PAR ); \ if ( TMO_POL != (_tmout_) ) \ CYG_UITRON_CHECK_DISPATCH_ENABLED(); \ CYG_MACRO_END #endif #ifdef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR #define CYG_UIT_PARAMCHECK_PTR( _p_ ) CYG_MACRO_START \ CYG_UIT_PARAMCHECK( NADR != (_p_), E_PAR ); \ CYG_MACRO_END #else // do check for NULL #define CYG_UIT_PARAMCHECK_PTR( _p_ ) CYG_MACRO_START \ CYG_UIT_PARAMCHECK( NADR != (_p_), E_PAR ); \ CYG_UIT_PARAMCHECK( NULL != (_p_), E_PAR ); \ CYG_MACRO_END #endif // !CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR // ------------------------------------------------------------------------ // CYG_UITRON_FAIL_RETURN // // After a call which waits, it might return with success, or due to a // timeout or a release wait (a forced escape from the waiting condition). // This macro examines context and finds out which, then executes a return // with the correct uITRON condition code. #define CYG_UITRON_FAIL_RETURN_SELF( _self_ ) CYG_MACRO_START \ Cyg_Thread::cyg_reason reason = (_self_)->get_wake_reason(); \ if ( Cyg_Thread::TIMEOUT == reason ) \ return E_TMOUT; \ if ( Cyg_Thread::BREAK == reason ) \ return E_RLWAI; \ if ( Cyg_Thread::DESTRUCT == reason ) \ return E_DLT; \ return E_SYS; /* if no plausible reason was found */ \ CYG_MACRO_END #define CYG_UITRON_FAIL_RETURN() CYG_MACRO_START \ Cyg_Thread *self = Cyg_Thread::self(); \ CYG_UITRON_FAIL_RETURN_SELF( self ); \ CYG_MACRO_END // ------------------------------------------------------------------------ // Interrupts disabled? #define CYG_UITRON_CHECK_CPU_UNLOC() \ CYG_UIT_PARAMCHECK( (Cyg_Interrupt::interrupts_enabled()), E_CTX ) // ------------------------------------------------------------------------ // the function definitions themselves: // ****************************************************** // *** 6.5 C Language Interfaces *** // ****************************************************** // - Task Management Functions #ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Thread ) CYG_UIT_FUNC_INLINE ER cre_tsk ( ID tskid, T_CTSK *pk_ctsk ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_ctsk ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( TASKS, tskid ); Cyg_Thread *p = &(CYG_UITRON_OBJS( TASKS )[ tskid - 1 ]); cyg_uint32 state = p->get_state(); if ( 0 == (state & Cyg_Thread::EXITED) ) ret = E_OBJ; // how did it get to be running? else if ( ((INT)p->get_stack_size()) < pk_ctsk->stksz ) ret = E_NOMEM; // more stack requested than available else { CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = new( p ) Cyg_Thread( (CYG_ADDRWORD) pk_ctsk->itskpri, (cyg_thread_entry *)pk_ctsk->task, (CYG_ADDRWORD) 0, // preserve the original name and stack: #ifdef CYGVAR_KERNEL_THREADS_NAME p->get_name(), #else NULL, #endif p->get_stack_base(), p->get_stack_size() ); // but ensure the task state is dormant: // (it is not constructed dormant, but suspended) p->kill(); // and record the initial priority outside the task too. CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ) = pk_ctsk->itskpri; } Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } cyg_uint32 state = p->get_state(); if ( state & Cyg_Thread::EXITED ) // just disconnect the pointer from its object CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = NULL; else ret = E_OBJ; Cyg_Scheduler::unlock(); return ret; } #endif // CYGPKG_UITRON_TASKS_CREATE_DELETE CYG_UIT_FUNC_INLINE ER sta_tsk ( ID tskid, INT stacd ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); Cyg_Scheduler::lock(); cyg_uint32 state = p->get_state(); #ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE // there is a race condition with deleting the task // so test it now that we have the scheduler locked if ( p != CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] ) ret = E_NOEXS; else // NOTE dangling else to the next line: #endif if ( state & Cyg_Thread::EXITED ) { p->reinitialize(); #ifdef CYGIMP_THREAD_PRIORITY p->set_priority( CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ) ); #endif p->set_entry_data( (CYG_ADDRWORD)stacd ); p->force_resume(); } else ret = E_OBJ; Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE void ext_tsk ( void ) { Cyg_Thread::exit(); } CYG_UIT_FUNC_INLINE void exd_tsk ( void ) { #ifdef CYGPKG_UITRON_TASKS_CREATE_DELETE Cyg_Thread *p; Cyg_Scheduler::lock(); p = Cyg_Thread::self(); ID tskid = (p - (&cyg_uitron_TASKS[0])) + 1; // just disconnect the pointer from its object CYG_UITRON_PTRS( TASKS )[ tskid - 1 ] = NULL; // Any associated storage management, and possibly calling the task // destructor, is for future versions. #else // do nothing - deletion not supported so just exit... #endif Cyg_Thread::exit(); // does not return, does unlock the scheduler for us } CYG_UIT_FUNC_INLINE ER ter_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); if ( (0 != (Cyg_Thread::EXITED & p->get_state())) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) // already dormant ret = E_OBJ; else { p->force_resume(); // let it run p->kill(); // and set prio high so it runs RIGHT NOW!! #ifdef CYGIMP_THREAD_PRIORITY p->set_priority( (cyg_priority) 0 ); #endif } Cyg_Scheduler::unlock(); #ifdef CYGIMP_THREAD_PRIORITY if ( (E_OK == ret) && (0 != cyg_uitron_dis_dsp_old_priority) ) { // then dispatching is disabled, so our prio is 0 too Cyg_Thread::yield(); // so let the dying thread run; Cyg_Thread::yield(); // no cost here of making sure. } #endif return ret; } CYG_UIT_FUNC_INLINE ER dis_dsp ( void ) { CYG_UITRON_CHECK_TASK_CONTEXT(); CYG_UITRON_CHECK_CPU_UNLOC(); Cyg_Scheduler::lock(); // Prevent preemption by going up to prio 0 if ( 0 == cyg_uitron_dis_dsp_old_priority ) { #ifdef CYGIMP_THREAD_PRIORITY Cyg_Thread *p = Cyg_Thread::self(); cyg_uitron_dis_dsp_old_priority = p->get_priority(); p->set_priority( 0 ); #else cyg_uitron_dis_dsp_old_priority = 1; #endif } Cyg_Scheduler::unlock(); return E_OK; } CYG_UIT_FUNC_INLINE ER ena_dsp ( void ) { CYG_UITRON_CHECK_TASK_CONTEXT(); CYG_UITRON_CHECK_CPU_UNLOC(); Cyg_Scheduler::lock(); // Enable dispatching (if disabled) and maybe switch threads if ( 0 != cyg_uitron_dis_dsp_old_priority ) { // We had prevented preemption by going up to prio 0 #ifdef CYGIMP_THREAD_PRIORITY Cyg_Thread *p = Cyg_Thread::self(); p->set_priority( cyg_uitron_dis_dsp_old_priority ); p->to_queue_head(); // to ensure we continue to run // if nobody higher pri #endif cyg_uitron_dis_dsp_old_priority = 0; } Cyg_Scheduler::unlock(); CYG_UITRON_CHECK_DISPATCH_ENABLED(); // NB: afterwards! return E_OK; } CYG_UIT_FUNC_INLINE ER chg_pri ( ID tskid, PRI tskpri ) { Cyg_Thread *p; ER ret = E_OK; if ( 0 == tskid ) { p = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); } else CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( 0 < tskpri, E_PAR ); #ifdef CYGIMP_THREAD_PRIORITY #if CYG_THREAD_MAX_PRIORITY < CYG_THREAD_MIN_PRIORITY CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY <= tskpri && tskpri <= CYG_THREAD_MIN_PRIORITY, E_PAR ); #else CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY >= tskpri && tskpri >= CYG_THREAD_MIN_PRIORITY, E_PAR ); #endif // Handle changing our own prio specially, if dispatch disabled: if ( 0 != cyg_uitron_dis_dsp_old_priority ) { // our actual prio is 0 now and must remain so: if ( Cyg_Thread::self() == p ) { // by whichever route p was set // set the priority we will return to when dispatch is enabled: cyg_uitron_dis_dsp_old_priority = (cyg_uint32)tskpri; return E_OK; } } Cyg_Scheduler::lock(); if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) ret = E_OBJ; // task is dormant else p->set_priority( (cyg_priority)tskpri ); Cyg_Scheduler::unlock(); #endif // CYGIMP_THREAD_PRIORITY got priorities at all? return ret; } CYG_UIT_FUNC_INLINE ER rot_rdq ( PRI tskpri ) { // zero means our level; easiet way is to yield() the CPU. if ( 0 == tskpri ) { Cyg_Thread::yield(); return E_OK; } #ifdef CYGIMP_THREAD_PRIORITY #if CYG_THREAD_MAX_PRIORITY < CYG_THREAD_MIN_PRIORITY CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY <= tskpri && tskpri <= CYG_THREAD_MIN_PRIORITY, E_PAR ); #else CYG_UIT_PARAMCHECK( CYG_THREAD_MAX_PRIORITY >= tskpri && tskpri >= CYG_THREAD_MIN_PRIORITY, E_PAR ); #endif Cyg_Thread::rotate_queue( tskpri ); #endif // CYGIMP_THREAD_PRIORITY got priorities at all? return E_OK; } CYG_UIT_FUNC_INLINE ER rel_wai ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); // get an atomic view of the task if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) ret = E_OBJ; // task is dormant else { p->release(); // return E_OBJ if the thread was not sleeping if ( Cyg_Thread::BREAK != p->get_wake_reason() ) ret = E_OBJ; } Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER get_tid ( ID *p_tskid ) { Cyg_Thread *self = Cyg_Thread::self(); CYG_UIT_PARAMCHECK_PTR( p_tskid ); if ( (&cyg_uitron_TASKS[0] <= (self)) && ((self) < &cyg_uitron_TASKS[CYGNUM_UITRON_TASKS]) ) // then I am a uITRON task *p_tskid = (self - (&cyg_uitron_TASKS[0])) + 1; else *p_tskid = 0; // Otherwise, non-task portion return E_OK; } CYG_UIT_FUNC_INLINE ER ref_tsk ( T_RTSK *pk_rtsk, ID tskid ) { Cyg_Thread *p; if ( 0 == tskid ) { p = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); tskid = (p - (&cyg_uitron_TASKS[0])) + 1; // it gets used below } else CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rtsk ); pk_rtsk->exinf = NADR; Cyg_Scheduler::lock(); // get an atomic view of the task cyg_uint32 state = p->get_state(); if ( (state & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) pk_rtsk->tskstat = TTS_DMT; else if ( state == Cyg_Thread::RUNNING ) // If it's us, it's running, else it's ready pk_rtsk->tskstat = (Cyg_Thread::self() == p) ? TTS_RUN // RUN state (we are it) : TTS_RDY; // READY state else if ( state & Cyg_Thread::SUSPENDED ) pk_rtsk->tskstat = (state & (Cyg_Thread::COUNTSLEEP | Cyg_Thread::SLEEPING)) ? TTS_WAS // WAIT-SUSPEND state : TTS_SUS; // SUSPEND state else pk_rtsk->tskstat = (state & (Cyg_Thread::COUNTSLEEP | Cyg_Thread::SLEEPING)) ? TTS_WAI // WAIT state : 0; // Not sure what's happening here! #ifdef CYGIMP_THREAD_PRIORITY if ( TTS_DMT == pk_rtsk->tskstat ) pk_rtsk->tskpri = CYG_UITRON_TASK_INITIAL_PRIORITY( tskid ); else if ( (TTS_RUN == pk_rtsk->tskstat) && (0 != cyg_uitron_dis_dsp_old_priority) ) // then we are it and dispatching is disabled, so // report our "real" priority - it is 0 in the kernel at the moment pk_rtsk->tskpri = cyg_uitron_dis_dsp_old_priority; else pk_rtsk->tskpri = p->get_priority(); #else pk_rtsk->tskpri = -1; // Not applicable #endif Cyg_Scheduler::unlock(); return E_OK; } // - Task-Dependent Synchronization Functions CYG_UIT_FUNC_INLINE ER sus_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); // get an atomic view of the task if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) ret = E_OBJ; // task is dormant else p->suspend(); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER rsm_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); // get an atomic view of the task cyg_uint32 state = p->get_state(); if ( 0 == (Cyg_Thread::SUSPENDED & state) ) ret = E_OBJ; // thread is not suspended else p->resume(); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER frsm_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); // get an atomic view of the task cyg_uint32 state = p->get_state(); if ( 0 == (Cyg_Thread::SUSPENDED & state) ) ret = E_OBJ; // thread is not suspended else p->force_resume(); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER slp_tsk ( void ) { Cyg_Thread *self = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); // do this now for the case when no sleeping actually occurs self->set_wake_reason( Cyg_Thread::DONE ); Cyg_Thread::counted_sleep(); if ( Cyg_Thread::DONE != self->get_wake_reason() ) CYG_UITRON_FAIL_RETURN_SELF( self ); return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER tslp_tsk ( TMO tmout ) { Cyg_Thread *self = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); CYG_UIT_PARAMCHECK( -1 <= tmout, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); // do this now for the case when no sleeping actually occurs self->set_wake_reason( Cyg_Thread::DONE ); // note that TMO_POL is not treated specially, though it // happens to work almost as a poll (some sleeping may occur) if ( TMO_FEVR == tmout ) Cyg_Thread::counted_sleep(); else Cyg_Thread::counted_sleep( (cyg_tick_count)tmout ); if ( Cyg_Thread::DONE != self->get_wake_reason() ) CYG_UITRON_FAIL_RETURN_SELF( self ); return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER wup_tsk ( ID tskid ) { Cyg_Thread *p; ER ret = E_OK; CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK( Cyg_Thread::self() != p, E_OBJ ); Cyg_Scheduler::lock(); // get an atomic view of the task if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) ret = E_OBJ; // task is dormant else p->counted_wake(); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER can_wup ( INT *p_wupcnt, ID tskid ) { Cyg_Thread *p; ER ret = E_OK; if ( 0 == tskid ) { p = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( p ); } else CYG_UITRON_CHECK_AND_GETP_TASKS( tskid, p ); CYG_UIT_PARAMCHECK_PTR( p_wupcnt ); Cyg_Scheduler::lock(); // get an atomic view of the task if ( (p->get_state() & (Cyg_Thread::EXITED | Cyg_Thread::CREATING)) || (Cyg_Thread::EXIT == p->get_wake_reason()) ) ret = E_OBJ; // task is dormant else { cyg_uint32 result = p->cancel_counted_wake(); *p_wupcnt = result; } Cyg_Scheduler::unlock(); return ret; } // - Synchronization and Communication Functions #ifdef CYGPKG_UITRON_SEMAS #if 0 < CYG_UITRON_NUM( SEMAS ) #ifdef CYGPKG_UITRON_SEMAS_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Counting_Semaphore2 ) CYG_UIT_FUNC_INLINE ER cre_sem ( ID semid, T_CSEM *pk_csem ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_csem ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( SEMAS, semid ); if ( TA_TFIFO != pk_csem->sematr ) ret = E_RSATR; else CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] = new( &(CYG_UITRON_OBJS( SEMAS )[ semid - 1 ]) ) Cyg_Counting_Semaphore2( (cyg_count32)pk_csem->isemcnt ); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_sem ( ID semid ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } CYG_UITRON_PTRS( SEMAS )[ semid - 1 ] = NULL; p->~Cyg_Counting_Semaphore2(); Cyg_Scheduler::unlock(); return E_OK; } #endif // CYGPKG_UITRON_SEMAS_CREATE_DELETE CYG_UIT_FUNC_INLINE ER sig_sem( ID semid ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); p->post(); return E_OK; } CYG_UIT_FUNC_INLINE ER wai_sem( ID semid ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); cyg_bool result = p->wait(); if ( !result ) CYG_UITRON_FAIL_RETURN(); return E_OK; } CYG_UIT_FUNC_INLINE ER preq_sem ( ID semid ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); cyg_bool result = p->trywait(); if ( !result ) return E_TMOUT; return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER twai_sem ( ID semid, TMO tmout ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); // do this now for the case when no sleeping actually occurs Cyg_Thread *self = Cyg_Thread::self(); self->set_wake_reason( Cyg_Thread::TIMEOUT ); cyg_bool result; if ( TMO_FEVR == tmout ) result = p->wait(); else if ( TMO_POL == tmout ) result = p->trywait(); else result = p->wait( Cyg_Clock::real_time_clock->current_value() + (cyg_tick_count)tmout ); if ( ! result ) CYG_UITRON_FAIL_RETURN_SELF( self ); return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER ref_sem ( T_RSEM *pk_rsem, ID semid ) { Cyg_Counting_Semaphore2 *p; CYG_UITRON_CHECK_AND_GETP_SEMAS( semid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rsem ); pk_rsem->exinf = NADR; pk_rsem->wtsk = p->waiting(); pk_rsem->semcnt = p->peek(); return E_OK; } #endif // 0 < CYG_UITRON_NUM( SEMAS ) #endif // CYGPKG_UITRON_SEMAS #ifdef CYGPKG_UITRON_FLAGS #if 0 < CYG_UITRON_NUM( FLAGS ) #ifdef CYGPKG_UITRON_FLAGS_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Flag ) CYG_UIT_FUNC_INLINE ER cre_flg ( ID flgid, T_CFLG *pk_cflg ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_cflg ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( FLAGS, flgid ); if ( 0 != ((~(TA_WMUL | TA_WSGL)) & pk_cflg->flgatr) ) ret = E_RSATR; else CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] = new( &(CYG_UITRON_OBJS( FLAGS )[ flgid - 1 ]) ) Cyg_Flag( (Cyg_FlagValue) pk_cflg->iflgptn ); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_flg ( ID flgid ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } CYG_UITRON_PTRS( FLAGS )[ flgid - 1 ] = NULL; p->~Cyg_Flag(); Cyg_Scheduler::unlock(); return E_OK; } #endif // CYGPKG_UITRON_FLAGS_CREATE_DELETE CYG_UIT_FUNC_INLINE ER set_flg ( ID flgid, UINT setptn ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); p->setbits( setptn ); return E_OK; } CYG_UIT_FUNC_INLINE ER clr_flg ( ID flgid, UINT clrptn ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); p->maskbits( clrptn ); return E_OK; } CYG_UIT_FUNC_INLINE ER wai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); CYG_UIT_PARAMCHECK_PTR( p_flgptn ); CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); // check we can use the wfmode value unchanged CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); UINT result = p->wait( waiptn, wfmode ); if ( ! result ) CYG_UITRON_FAIL_RETURN(); *p_flgptn = result; return E_OK; } CYG_UIT_FUNC_INLINE ER pol_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); CYG_UIT_PARAMCHECK_PTR( p_flgptn ); CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); // check we can use the wfmode value unchanged CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); UINT result = p->poll( waiptn, wfmode ); if ( ! result ) return E_TMOUT; *p_flgptn = result; return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER twai_flg ( UINT *p_flgptn, ID flgid, UINT waiptn, UINT wfmode, TMO tmout ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); CYG_UIT_PARAMCHECK_PTR( p_flgptn ); CYG_UIT_PARAMCHECK( 0 == (wfmode & ~Cyg_Flag::MASK), E_PAR ); CYG_UIT_PARAMCHECK( 0 != waiptn, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); // check we can use the wfmode value unchanged CYG_ASSERT( Cyg_Flag::AND == TWF_ANDW, "Flag AND value bad" ); CYG_ASSERT( Cyg_Flag::OR == TWF_ORW, "Flag OR value bad" ); CYG_ASSERT( Cyg_Flag::CLR == TWF_CLR, "Flag CLR value bad" ); // do this now for the case when no sleeping actually occurs Cyg_Thread *self = Cyg_Thread::self(); self->set_wake_reason( Cyg_Thread::TIMEOUT ); UINT result; if ( TMO_FEVR == tmout ) result = p->wait( waiptn, wfmode ); else if ( TMO_POL == tmout ) result = p->poll( waiptn, wfmode ); else result = p->wait( waiptn, wfmode, Cyg_Clock::real_time_clock->current_value() + (cyg_tick_count)tmout ); if ( ! result ) CYG_UITRON_FAIL_RETURN_SELF( self ); *p_flgptn = result; return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER ref_flg ( T_RFLG *pk_rflg, ID flgid ) { Cyg_Flag *p; CYG_UITRON_CHECK_AND_GETP_FLAGS( flgid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rflg ); pk_rflg->exinf = NADR; pk_rflg->wtsk = p->waiting(); pk_rflg->flgptn = p->peek(); return E_OK; } #endif // 0 < CYG_UITRON_NUM( FLAGS ) #endif // CYGPKG_UITRON_FLAGS #ifdef CYGPKG_UITRON_MBOXES #if 0 < CYG_UITRON_NUM( MBOXES ) #ifdef CYGPKG_UITRON_MBOXES_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Mbox ) CYG_UIT_FUNC_INLINE ER cre_mbx ( ID mbxid, T_CMBX* pk_cmbx ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_cmbx ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MBOXES, mbxid ); if ( ((ATR)(TA_TFIFO + TA_MFIFO)) != pk_cmbx->mbxatr ) ret = E_RSATR; else CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] = new( &(CYG_UITRON_OBJS( MBOXES )[ mbxid - 1 ]) ) Cyg_Mbox(); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_mbx ( ID mbxid ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } CYG_UITRON_PTRS( MBOXES )[ mbxid - 1 ] = NULL; p->~Cyg_Mbox(); Cyg_Scheduler::unlock(); return E_OK; } #endif // CYGPKG_UITRON_MBOXES_CREATE_DELETE // This bit of unpleasantness is to allow uITRON programs to send a NULL // message - if permitted by the parameter checking. // // NULL is used internally to mean no message; but -1 is fine. So we send // a NULL as a NADR and if we see a NULL coming back, change it to a NADR. // // One hopes that often this will be optimized out, since the one or both // of these being true has been detected and errored out just above. #ifdef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR // represent a NULL as NADR internally #define CYG_UIT_TMSG_FIXUP_IN( _p_ ) CYG_MACRO_START \ if ( NULL == (_p_) ) \ (_p_) = (T_MSG *)NADR; \ CYG_MACRO_END // we get a NADR back sometimes, meaning NULL #define CYG_UIT_TMSG_FIXUP_OUT( _p_ ) CYG_MACRO_START \ if ( NADR == (_p_) ) \ (_p_) = (T_MSG *)NULL; \ CYG_MACRO_END #else // NULL is checked for and makes an error #define CYG_UIT_TMSG_FIXUP_IN( _p_ ) CYG_EMPTY_STATEMENT #define CYG_UIT_TMSG_FIXUP_OUT( _p_ ) CYG_EMPTY_STATEMENT #endif // and sometimes either in status enquiries #define CYG_UIT_TMSG_FIXUP_ALL( _p_ ) CYG_MACRO_START \ if ( NULL == (_p_) ) \ (_p_) = (T_MSG *)NADR; \ else if ( NADR == (_p_) ) \ (_p_) = (T_MSG *)NULL; \ CYG_MACRO_END CYG_UIT_FUNC_INLINE ER snd_msg ( ID mbxid, T_MSG *pk_msg ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); CYG_UIT_PARAMCHECK_PTR( pk_msg ); CYG_UIT_TMSG_FIXUP_IN( pk_msg ); cyg_bool result = p->tryput( (void *)pk_msg ); if ( ! result ) return E_QOVR; return E_OK; } CYG_UIT_FUNC_INLINE ER rcv_msg ( T_MSG **ppk_msg, ID mbxid ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); CYG_UIT_PARAMCHECK_PTR( ppk_msg ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); T_MSG *result = (T_MSG *)p->get(); if ( ! result ) CYG_UITRON_FAIL_RETURN(); CYG_UIT_TMSG_FIXUP_OUT( result ); *ppk_msg = result; return E_OK; } CYG_UIT_FUNC_INLINE ER prcv_msg ( T_MSG **ppk_msg, ID mbxid ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); CYG_UIT_PARAMCHECK_PTR( ppk_msg ); T_MSG *result = (T_MSG *)p->tryget(); if ( ! result ) return E_TMOUT; CYG_UIT_TMSG_FIXUP_OUT( result ); *ppk_msg = result; return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER trcv_msg ( T_MSG **ppk_msg, ID mbxid, TMO tmout ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); CYG_UIT_PARAMCHECK_PTR( ppk_msg ); CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); // do this now for the case when no sleeping actually occurs Cyg_Thread *self = Cyg_Thread::self(); self->set_wake_reason( Cyg_Thread::TIMEOUT ); T_MSG *result; if ( TMO_FEVR == tmout ) result = (T_MSG *)p->get(); else if ( TMO_POL == tmout ) result = (T_MSG *)p->tryget(); else result = (T_MSG *)p->get( Cyg_Clock::real_time_clock->current_value() + (cyg_tick_count)tmout ); if ( ! result ) CYG_UITRON_FAIL_RETURN_SELF( self ); CYG_UIT_TMSG_FIXUP_OUT( result ); *ppk_msg = result; return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER ref_mbx ( T_RMBX *pk_rmbx, ID mbxid ) { Cyg_Mbox *p; CYG_UITRON_CHECK_AND_GETP_MBOXES( mbxid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rmbx ); pk_rmbx->exinf = NADR; pk_rmbx->wtsk = p->waiting_to_get(); pk_rmbx->pk_msg = (T_MSG *)p->peek_item(); CYG_UIT_TMSG_FIXUP_ALL( pk_rmbx->pk_msg ); return E_OK; } #undef CYG_UIT_TMSG_FIXUP_IN #undef CYG_UIT_TMSG_FIXUP_OUT #undef CYG_UIT_TMSG_FIXUP_ALL #endif // 0 < CYG_UITRON_NUM( MBOXES ) #endif // CYGPKG_UITRON_MBOXES // - Extended Synchronization and Communication Functions #if 0 // NOT SUPPORTED ER cre_mbf ( ID mbfid, T_CMBF *pk_cmbf ); ER del_mbf ( ID mbfid ); ER snd_mbf ( ID mbfid, VP msg, INT msgsz ); ER psnd_mbf ( ID mbfid, VP msg, INT msgsz ); ER tsnd_mbf ( ID mbfid, VP msg, INT msgsz, TMO tmout ); ER rcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); ER prcv_mbf ( VP msg, INT *p_msgsz, ID mbfid ); ER trcv_mbf ( VP msg, INT *p_msgsz, ID mbfid, TMO tmout ); ER ref_mbf ( T_RMBF *pk_rmbf, ID mbfid ); ER cre_por ( ID porid, T_CPOR *pk_cpor ); ER del_por ( ID porid ); ER cal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz ); ER pcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz ); ER tcal_por ( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz, TMO tmout ); ER acp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT acpptn ); ER pacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT acpptn ); ER tacp_por ( RNO *p_rdvno, VP msg, INT *p_cmsgsz, ID porid, UINT acpptn, TMO tmout ); ER fwd_por ( ID porid, UINT calptn, RNO rdvno, VP msg, INT cmsgsz ); ER rpl_rdv ( RNO rdvno, VP msg, INT rmsgsz ); ER ref_por ( T_RPOR *pk_rpor, ID porid ); #endif // - Interrupt Management Functions #if 0 // NOT SUPPORTED ER def_int ( UINT dintno, T_DINT *pk_dint ); void ret_wup ( ID tskid ); #endif CYG_UIT_FUNC_INLINE ER loc_cpu ( void ) { CYG_UITRON_CHECK_TASK_CONTEXT(); Cyg_Scheduler::lock(); // Prevent preemption by going up to prio 0 if ( 0 == cyg_uitron_dis_dsp_old_priority ) { #ifdef CYGIMP_THREAD_PRIORITY Cyg_Thread *p = Cyg_Thread::self(); cyg_uitron_dis_dsp_old_priority = p->get_priority(); p->set_priority( 0 ); #else cyg_uitron_dis_dsp_old_priority = 1; #endif } Cyg_Interrupt::disable_interrupts(); Cyg_Scheduler::unlock(); return E_OK; } CYG_UIT_FUNC_INLINE ER unl_cpu ( void ) { CYG_UITRON_CHECK_TASK_CONTEXT(); Cyg_Scheduler::lock(); // Enable dispatching (if disabled) and maybe switch threads if ( 0 != cyg_uitron_dis_dsp_old_priority ) { // We had prevented preemption by going up to prio 0 #ifdef CYGIMP_THREAD_PRIORITY Cyg_Thread *p = Cyg_Thread::self(); p->set_priority( cyg_uitron_dis_dsp_old_priority ); #endif cyg_uitron_dis_dsp_old_priority = 0; } Cyg_Interrupt::enable_interrupts(); Cyg_Scheduler::unlock(); CYG_UITRON_CHECK_DISPATCH_ENABLED(); // NB: afterwards! return E_OK; } #if 0 // NOT SUPPORTED ER dis_int ( UINT eintno ); ER ena_int ( UINT eintno ); ER chg_iXX ( UINT iXXXX ); ER ref_iXX ( UINT *p_iXXXX ); #endif // - Memorypool Management Functions #ifdef CYGPKG_UITRON_MEMPOOLVAR #if 0 < CYG_UITRON_NUM( MEMPOOLVAR ) #ifdef CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Mempool_Variable ) CYG_UIT_FUNC_INLINE ER cre_mpl ( ID mplid, T_CMPL *pk_cmpl ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_cmpl ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MEMPOOLVAR, mplid ); Cyg_Mempool_Variable *p = &(CYG_UITRON_OBJS( MEMPOOLVAR )[ mplid - 1 ]); cyg_uint8 *base; cyg_int32 size; CYG_ADDRWORD scratch; // preserve the original memory area to use p->get_arena( base, size, scratch ); if ( size < pk_cmpl->mplsz ) ret = E_NOMEM; else if ( TA_TFIFO != pk_cmpl->mplatr ) ret = E_RSATR; else CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] = new( p ) Cyg_Mempool_Variable( base, size ); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_mpl ( ID mplid ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } CYG_UITRON_PTRS( MEMPOOLVAR )[ mplid - 1 ] = NULL; p->~Cyg_Mempool_Variable(); Cyg_Scheduler::unlock(); return E_OK; } #endif // CYGPKG_UITRON_MEMPOOLVAR_CREATE_DELETE CYG_UIT_FUNC_INLINE ER get_blk ( VP *p_blk, ID mplid, INT blksz ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); CYG_UIT_PARAMCHECK_PTR( p_blk ); CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); VP result = (VP)p->alloc(blksz); if ( ! result ) CYG_UITRON_FAIL_RETURN(); *p_blk = result; return E_OK; } CYG_UIT_FUNC_INLINE ER pget_blk ( VP *p_blk, ID mplid, INT blksz ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); CYG_UIT_PARAMCHECK_PTR( p_blk ); CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); VP result = (VP)p->try_alloc(blksz); if ( ! result ) return E_TMOUT; *p_blk = result; return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER tget_blk ( VP *p_blk, ID mplid, INT blksz, TMO tmout ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); CYG_UIT_PARAMCHECK_PTR( p_blk ); CYG_UIT_PARAMCHECK( blksz > 0, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); // do this now for the case when no sleeping actually occurs Cyg_Thread *self = Cyg_Thread::self(); self->set_wake_reason( Cyg_Thread::TIMEOUT ); VP result; if ( TMO_FEVR == tmout ) result = p->alloc(blksz); else if ( TMO_POL == tmout ) result = p->try_alloc(blksz); else result = p->alloc( blksz, Cyg_Clock::real_time_clock->current_value() + (cyg_tick_count)tmout ); if ( ! result ) CYG_UITRON_FAIL_RETURN_SELF( self ); *p_blk = result; return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER rel_blk ( ID mplid, VP blk ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); CYG_UIT_PARAMCHECK_PTR( blk ); cyg_bool result = p->free( (cyg_uint8 *)blk, 0 ); if ( ! result ) return E_PAR; return E_OK; } CYG_UIT_FUNC_INLINE ER ref_mpl ( T_RMPL *pk_rmpl, ID mplid ) { Cyg_Mempool_Variable *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLVAR( mplid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rmpl ); pk_rmpl->exinf = NADR; pk_rmpl->wtsk = p->waiting(); pk_rmpl->frsz = p->get_freemem(); cyg_uint8 *base; cyg_int32 size; CYG_ADDRWORD maxfree; p->get_arena(base, size, maxfree); pk_rmpl->maxsz = maxfree; return E_OK; } #endif // 0 < CYG_UITRON_NUM( MEMPOOLVAR ) #endif // CYGPKG_UITRON_MEMPOOLVAR #ifdef CYGPKG_UITRON_MEMPOOLFIXED #if 0 < CYG_UITRON_NUM( MEMPOOLFIXED ) #ifdef CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE CYG_UITRON_NEWFUNCTION( Cyg_Mempool_Fixed ) CYG_UIT_FUNC_INLINE ER cre_mpf ( ID mpfid, T_CMPF *pk_cmpf ) { ER ret = E_OK; CYG_UIT_PARAMCHECK_PTR( pk_cmpf ); CYG_UITRON_CHECK_NO_OBJ_LOCK_SCHED( MEMPOOLFIXED, mpfid ); Cyg_Mempool_Fixed *p = &(CYG_UITRON_OBJS( MEMPOOLFIXED )[ mpfid - 1 ]); cyg_uint8 *base; cyg_int32 size; CYG_ADDRWORD scratch; // preserve the original memory area to use p->get_arena( base, size, scratch ); if ( size < (pk_cmpf->blfsz * (pk_cmpf->mpfcnt + 1)) ) ret = E_NOMEM; else if ( TA_TFIFO != pk_cmpf->mpfatr ) ret = E_RSATR; else CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] = new( p ) Cyg_Mempool_Fixed( base, size, (CYG_ADDRWORD)pk_cmpf->blfsz ); Cyg_Scheduler::unlock(); return ret; } CYG_UIT_FUNC_INLINE ER del_mpf ( ID mpfid ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); Cyg_Scheduler::lock(); // deal with the race condition here if ( p != CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] ) { Cyg_Scheduler::unlock(); return E_NOEXS; } CYG_UITRON_PTRS( MEMPOOLFIXED )[ mpfid - 1 ] = NULL; p->~Cyg_Mempool_Fixed(); Cyg_Scheduler::unlock(); return E_OK; } #endif // CYGPKG_UITRON_MEMPOOLFIXED_CREATE_DELETE CYG_UIT_FUNC_INLINE ER get_blf ( VP *p_blf, ID mpfid ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); CYG_UIT_PARAMCHECK_PTR( p_blf ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); VP result = (VP)p->alloc(); if ( ! result ) CYG_UITRON_FAIL_RETURN(); *p_blf = result; return E_OK; } CYG_UIT_FUNC_INLINE ER pget_blf ( VP *p_blf, ID mpfid ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); CYG_UIT_PARAMCHECK_PTR( p_blf ); VP result = (VP)p->try_alloc(); if ( ! result ) return E_TMOUT; *p_blf = result; return E_OK; } #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER tget_blf ( VP *p_blf, ID mpfid, TMO tmout ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); CYG_UIT_PARAMCHECK_PTR( p_blf ); CYG_UITRON_CHECK_DISPATCH_ENABLED_TMO( tmout ); // do this now for the case when no sleeping actually occurs Cyg_Thread *self = Cyg_Thread::self(); self->set_wake_reason( Cyg_Thread::TIMEOUT ); VP result; if ( TMO_FEVR == tmout ) result = p->alloc(); else if ( TMO_POL == tmout ) result = p->try_alloc(); else result = p->alloc( Cyg_Clock::real_time_clock->current_value() + (cyg_tick_count)tmout ); if ( ! result ) CYG_UITRON_FAIL_RETURN_SELF( self ); *p_blf = result; return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER rel_blf ( ID mpfid, VP blf ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); CYG_UIT_PARAMCHECK_PTR( blf ); cyg_bool result = p->free( (cyg_uint8 *)blf ); if ( ! result ) return E_PAR; return E_OK; } CYG_UIT_FUNC_INLINE ER ref_mpf ( T_RMPF *pk_rmpf, ID mpfid ) { Cyg_Mempool_Fixed *p; CYG_UITRON_CHECK_AND_GETP_MEMPOOLFIXED( mpfid, p ); CYG_UIT_PARAMCHECK_PTR( pk_rmpf ); pk_rmpf->exinf = NADR; pk_rmpf->wtsk = p->waiting(); cyg_int32 blocksize = p->get_blocksize(); pk_rmpf->frbcnt = p->get_freemem() / blocksize; // these two are "implementation dependent" ie. eCos only pk_rmpf->numbcnt = p->get_totalmem() / blocksize; pk_rmpf->bsize = blocksize; return E_OK; } #endif // 0 < CYG_UITRON_NUM( MEMPOOLFIXED ) #endif // CYGPKG_UITRON_MEMPOOLFIXED // - Time Management Functions #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK CYG_UIT_FUNC_INLINE ER set_tim ( SYSTIME *pk_tim ) { CYG_UIT_PARAMCHECK_PTR( pk_tim ); Cyg_Clock::real_time_clock->set_value( *pk_tim ); return E_OK; } CYG_UIT_FUNC_INLINE ER get_tim ( SYSTIME *pk_tim ) { CYG_UIT_PARAMCHECK_PTR( pk_tim ); *pk_tim = Cyg_Clock::real_time_clock->current_value(); return E_OK; } #endif // CYGVAR_KERNEL_COUNTERS_CLOCK #ifdef CYGFUN_KERNEL_THREADS_TIMER CYG_UIT_FUNC_INLINE ER dly_tsk ( DLYTIME dlytim ) { CYG_UIT_PARAMCHECK( 0 <= dlytim, E_PAR ); CYG_UITRON_CHECK_DISPATCH_ENABLED(); if ( 0 >= dlytim ) return E_OK; Cyg_Thread *self = Cyg_Thread::self(); CYG_UITRON_CHECK_TASK_CONTEXT_SELF( self ); self->delay( dlytim ); if ( Cyg_Thread::DONE != self->get_wake_reason() ) CYG_UITRON_FAIL_RETURN_SELF( self ); return E_OK; } #endif // CYGFUN_KERNEL_THREADS_TIMER #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK #ifdef CYGPKG_UITRON_CYCLICS #if 0 < CYG_UITRON_NUM( CYCLICS ) CYG_UIT_FUNC_INLINE ER def_cyc ( HNO cycno, T_DCYC *pk_dcyc ) { // pk_dcyc->cycatr is ignored // The only relevant attribute is TA_HLNG/TA_ASM. // This can be ignored as assembler routines are defined to be // more conservative with registers than the procedure call standard. Cyg_Timer *p; CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); #ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR CYG_UIT_PARAMCHECK( NULL != pk_dcyc, E_PAR ); #endif if( NADR == pk_dcyc ) { p->~Cyg_Timer(); return E_OK; } CYG_UIT_PARAMCHECK( 0 == (pk_dcyc->cycact & ~TCY_ON), E_PAR ); CYG_UIT_PARAMCHECK( 0 < pk_dcyc->cyctim, E_PAR ); p->initialize( Cyg_Clock::real_time_clock, (cyg_alarm_fn *)pk_dcyc->cychdr, (CYG_ADDRWORD)pk_dcyc->exinf, Cyg_Clock::real_time_clock->current_value() + pk_dcyc->cyctim, pk_dcyc->cyctim, pk_dcyc->cycact); return E_OK; } CYG_UIT_FUNC_INLINE ER act_cyc ( HNO cycno, UINT cycact ) { Cyg_Timer *p; CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); CYG_UIT_PARAMCHECK( 0 == (cycact & ~(TCY_ON | TCY_INI)), E_PAR ); p->activate(cycact); return E_OK; } CYG_UIT_FUNC_INLINE ER ref_cyc ( T_RCYC *pk_rcyc, HNO cycno ) { Cyg_Timer *p; cyg_tick_count t; CYG_UITRON_CHECK_AND_GETHDLR( CYCLICS, cycno, p ); CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); CYG_UIT_PARAMCHECK_PTR( pk_rcyc ); pk_rcyc->exinf = (VP)p->get_data(); Cyg_Scheduler::lock(); t = p->get_trigger() - Cyg_Clock::real_time_clock->current_value(); Cyg_Scheduler::unlock(); pk_rcyc->lfttim = t; pk_rcyc->cycact = (UINT)p->is_enabled(); return E_OK; } #endif // 0 < CYG_UITRON_NUM( CYCLICS ) #endif // CYGPKG_UITRON_CYCLICS #ifdef CYGPKG_UITRON_ALARMS #if 0 < CYG_UITRON_NUM( ALARMS ) CYG_UIT_FUNC_INLINE ER def_alm ( HNO almno, T_DALM *pk_dalm ) { Cyg_Timer *p; cyg_tick_count t, now; CYG_UITRON_CHECK_AND_GETHDLR( ALARMS, almno, p ); #ifndef CYGSEM_UITRON_PARAMS_NULL_IS_GOOD_PTR CYG_UIT_PARAMCHECK( NULL != pk_dalm, E_PAR ); #endif if( NADR == pk_dalm ) { p->~Cyg_Timer(); return E_OK; } CYG_UIT_PARAMCHECK( 0 == (pk_dalm->tmmode & ~TTM_REL), E_PAR ); // make the time arithmetic safe without locking now = Cyg_Clock::real_time_clock->current_value(); t = pk_dalm->almtim; if( TTM_REL & pk_dalm->tmmode ) t += now; CYG_UIT_PARAMCHECK( now < t, E_PAR ); p->initialize(Cyg_Clock::real_time_clock, (cyg_alarm_fn *)pk_dalm->almhdr, (CYG_ADDRWORD)pk_dalm->exinf, t, 0, Cyg_Timer::ENABLE); return E_OK; } CYG_UIT_FUNC_INLINE ER ref_alm ( T_RALM *pk_ralm, HNO almno ) { Cyg_Timer *p; cyg_tick_count t; CYG_UITRON_CHECK_AND_GETHDLR( ALARMS, almno, p ); CYG_UIT_PARAMCHECK_PTR( pk_ralm ); CYG_UIT_PARAMCHECK( p->is_initialized(), E_NOEXS); Cyg_Scheduler::lock(); t = p->get_trigger() - Cyg_Clock::real_time_clock->current_value(); Cyg_Scheduler::unlock(); pk_ralm->exinf = (VP)p->get_data(); pk_ralm->lfttim = t; return E_OK; } #endif // 0 < CYG_UITRON_NUM( ALARMS ) #endif // CYGPKG_UITRON_ALARMS #endif // CYGVAR_KERNEL_COUNTERS_CLOCK // - System Management Functions CYG_UIT_FUNC_INLINE ER get_ver ( T_VER *pk_ver ) { CYG_UIT_PARAMCHECK_PTR( pk_ver ); pk_ver->maker = CYGNUM_UITRON_VER_MAKER; pk_ver->id = CYGNUM_UITRON_VER_ID; pk_ver->spver = CYGNUM_UITRON_VER_SPVER; pk_ver->prver = CYGNUM_UITRON_VER_PRVER; pk_ver->prno[0] = CYGNUM_UITRON_VER_PRNO_0; pk_ver->prno[1] = CYGNUM_UITRON_VER_PRNO_1; pk_ver->prno[2] = CYGNUM_UITRON_VER_PRNO_2; pk_ver->prno[3] = CYGNUM_UITRON_VER_PRNO_3; pk_ver->cpu = CYGNUM_UITRON_VER_CPU; pk_ver->var = CYGNUM_UITRON_VER_VAR; return E_OK; } CYG_UIT_FUNC_INLINE ER ref_sys ( T_RSYS *pk_rsys ) { CYG_UIT_PARAMCHECK_PTR( pk_rsys ); if ( ! Cyg_Interrupt::interrupts_enabled() ) // CPU is locked pk_rsys->sysstat = TSS_LOC; else pk_rsys->sysstat = (0 == cyg_uitron_dis_dsp_old_priority) ? TSS_TSK : TSS_DDSP; return E_OK; } CYG_UIT_FUNC_INLINE ER ref_cfg ( T_RCFG *pk_rcfg ) { CYG_UIT_PARAMCHECK_PTR( pk_rcfg ); // no details here yet return E_OK; } #if 0 // NOT SUPPORTED ER def_svc ( FN s_fncd, T_DSVC *pk_dsvc ); ER def_exc ( UINT exckind, T_DEXC *pk_dexc ); #endif // - Network Support Functions #if 0 // NOT SUPPORTED ER nrea_dat ( INT *p_reasz, VP dstadr, NODE srcnode, VP srcadr, INT datsz ); ER nwri_dat ( INT *p_wrisz, NODE dstnode, VP dstadr, VP srcadr, INT datsz ); ER nget_nod ( NODE *p_node ); ER nget_ver ( T_VER *pk_ver, NODE node ); #endif // ======================================================================== #endif // CYGPKG_UITRON #endif // CYGPRI_UITRON_FUNCS_HERE_AND_NOW #endif // CYGONCE_COMPAT_UITRON_UIT_FUNC_INL //EOF uit_func.inl
