Mercurial > flash_v2
diff packages/compat/uitron/current/include/uit_func.inl @ 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/compat/uitron/current/include/uit_func.inl @@ -0,0 +1,1774 @@ +#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 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> + +// ------------------------------------------------------------------------ +// 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_Scheduler::get_sched_lock(), 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(); + 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(); + return ret; +} + +CYG_UIT_FUNC_INLINE +ER +dis_dsp ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + CYG_UITRON_CHECK_CPU_UNLOC(); + // Prevent preemption + if ( 0 == Cyg_Scheduler::get_sched_lock() ) + Cyg_Scheduler::lock(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +ena_dsp ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + CYG_UITRON_CHECK_CPU_UNLOC(); + // Unlock the scheduler (if locked) and maybe switch threads + if ( 0 < Cyg_Scheduler::get_sched_lock() ) + 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 ); +#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_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 +#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE + Cyg_Thread::rotate_queue( tskpri ); +#endif +#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_UITRON_CHECK_TASK_CONTEXT_SELF( self ); + CYG_UIT_PARAMCHECK_PTR( p_tskid ); + *p_tskid = (self - (&cyg_uitron_TASKS[0])) + 1; + 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 + 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_OBJ; + } + 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_OBJ; + } + 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_OBJ; + } + 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_Interrupt::disable_interrupts(); + if ( 0 == Cyg_Scheduler::get_sched_lock() ) + Cyg_Scheduler::lock(); + return E_OK; +} + +CYG_UIT_FUNC_INLINE +ER +unl_cpu ( void ) +{ + CYG_UITRON_CHECK_TASK_CONTEXT(); + Cyg_Interrupt::enable_interrupts(); + if ( 0 < Cyg_Scheduler::get_sched_lock() ) + Cyg_Scheduler::unlock(); + 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_OBJ; + } + 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_OBJ; + } + 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 = + (Cyg_Scheduler::get_sched_lock() == 0) ? 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
