📄 uit_func.inl
字号:
#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_DELETECYG_UITRON_NEWFUNCTION( Cyg_Thread )CYG_UIT_FUNC_INLINEERcre_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_INLINEERdel_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_DELETECYG_UIT_FUNC_INLINEERsta_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_INLINEvoidext_tsk ( void ){ Cyg_Thread::exit();}CYG_UIT_FUNC_INLINEvoidexd_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_INLINEERter_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_INLINEERdis_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -