⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.cxx

📁 ecos实时嵌入式操作系统
💻 CXX
📖 第 1 页 / 共 3 页
字号:
{    CYG_REPORT_FUNCTION();//    CYG_ASSERT( new_priority >=  CYG_THREAD_MAX_PRIORITY, "Priority out of range");//    CYG_ASSERT( new_priority <=  CYG_THREAD_MIN_PRIORITY, "Priority out of range");        CYG_INSTRUMENT_THREAD(PRIORITY,this,new_priority);            // Prevent preemption    Cyg_Scheduler::lock();    Cyg_ThreadQueue *queue = NULL;        // If running, remove from run qs    if( state == RUNNING )        Cyg_Scheduler::scheduler.rem_thread(this);    else if( state & SLEEPING )    {        // Remove thread from current queue.        queue = get_current_queue();        // if indeed we are on a queue        if ( NULL != queue ) {            CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");                    remove();        }    }    Cyg_Scheduler::scheduler.deregister_thread(this);    #if CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES    // Check that there are no other threads at this priority.    // If so, leave is as it is.    CYG_ASSERT( Cyg_Scheduler::scheduler.unique(new_priority), "Priority not unique");        if( Cyg_Scheduler::scheduler.unique(new_priority) )        priority = new_priority;#else // !CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE    // When we have priority inheritance, we must update the original    // priority and not the inherited one.  If the new priority is    // better than the current inherited one, then use that    // immediately. We remain in inherited state to avoid problems    // with multiple mutex inheritances.        if( priority_inherited )    {        original_priority = new_priority;        if( priority > new_priority ) priority = new_priority;    }    else priority = new_priority;    #else        priority = new_priority;#endif    #endif // CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES    Cyg_Scheduler::scheduler.register_thread(this);        // Return thread to scheduler if runnable    if( state == RUNNING )        Cyg_Scheduler::scheduler.add_thread(this);    else if ( state & SLEEPING )    {        // return to current queue        // if indeed we are on a queue        if ( NULL != queue ) {            CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");            queue->enqueue(this);        }    }    // If the current thread is being reprioritized, set the    // reschedule flag to ensure that it gets rescheduled if    // necessary. (Strictly we only need to do this if the new    // priority is less than that of some other runnable thread, in    // practice checking that is as expensive as what the scheduler    // will do anyway).    // If it is not the current thread then we need to see whether    // it is more worthy of execution than any current thread and    // rescheduled if necessary.        if( this == Cyg_Scheduler::get_current_thread() )         Cyg_Scheduler::set_need_reschedule();    else Cyg_Scheduler::set_need_reschedule(this);        // Unlock the scheduler and maybe switch threads    Cyg_Scheduler::unlock();    CYG_REPORT_RETURN();}#endif// -------------------------------------------------------------------------// Thread delay functionvoidCyg_Thread::delay( cyg_tick_count delay){    CYG_REPORT_FUNCTION();#ifdef CYGFUN_KERNEL_THREADS_TIMER    CYG_INSTRUMENT_THREAD(DELAY,this,delay);    // Prevent preemption    Cyg_Scheduler::lock();        sleep();    set_timer( Cyg_Clock::real_time_clock->current_value()+delay, DELAY );    // Unlock the scheduler and maybe switch threads    Cyg_Scheduler::unlock();    // Clear the timeout. It is irrelevant whether the alarm has    // actually gone off or not.    clear_timer();    // and deal with anything else we must do when we return    switch( wake_reason ) {    case DESTRUCT:    case EXIT:                    exit();        break;            default:        break;    }#endif    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------//#ifdef CYGPKG_KERNEL_EXCEPTIONSvoidCyg_Thread::deliver_exception(    cyg_code            exception_number,       // exception being raised    CYG_ADDRWORD        exception_info          // exception specific info    ){    if( this == Cyg_Scheduler::get_current_thread() )    {        // Delivering to current thread, probably as a result        // of a real hardware exception. Simply invoke the appropriate        // handler.        exception_control.deliver_exception( exception_number, exception_info );    }#ifdef CYGIMP_EXCEPTION_ASYNC        else    {        // Delivering to another thread, probably as a result of one thread        // invoking this function on another thread. Adjust the other thread's        // state to make it execute the exception routine when it next runs.        // At present there is an unresolved problem here. We do not know what        // state the destination thread is in. It may not be a suitable point at        // which to invoke an exception routine. In most cases the exception        // routine will be run in the scheduler thread switch code, where the world is        // in an inconsistent state. We really need to run the routine at the        // end of unlock_inner(). However this would add extra code to the scheduler,        // and require a way of storing pending exceptions. So for now this option is        // disabled and not yet implemented, it may never be.            }#endif    }#endif// -------------------------------------------------------------------------// Per-thread data support#ifdef CYGVAR_KERNEL_THREADS_DATA// Set the data map bits for each free slot in the data array.cyg_ucount32 Cyg_Thread::thread_data_map = (~CYGNUM_KERNEL_THREADS_DATA_ALL) &             (1+(((cyg_ucount32)(1<<(CYGNUM_KERNEL_THREADS_DATA_MAX-1))-1)<<1));// the second expression is equivalent to ((1<<CYGNUM_KERNEL_THREADS_DATA_MAX)-1);// but avoids overflow. The compiler will compile to a constant just fine.Cyg_Thread::cyg_data_indexCyg_Thread::new_data_index(){    Cyg_Scheduler::lock();    Cyg_Thread::cyg_data_index index;    if (0 == thread_data_map)        return -1;        // find ls set bit    HAL_LSBIT_INDEX( index, thread_data_map );    // clear the bit    thread_data_map &= ~(1<<index);        Cyg_Scheduler::unlock();    return index;}void Cyg_Thread::free_data_index( Cyg_Thread::cyg_data_index index ){    Cyg_Scheduler::lock();    thread_data_map |= (1<<index);        Cyg_Scheduler::unlock();    }#endif// -------------------------------------------------------------------------// Allocate some memory at the lower end of the stack// by moving the stack limit pointer.#if defined(CYGFUN_KERNEL_THREADS_STACK_LIMIT) && \    defined(CYGFUN_KERNEL_THREADS_STACK_CHECKING)// if not doing stack checking, implementation can be found in thread.inl// This implementation puts the magic buffer area (to watch for overruns// *above* the stack limit, i.e. there is no official demarcation between// the stack and the buffer. But that's okay if you think about it... having// a demarcation would not accomplish anything more.void *Cyg_HardwareThread::increment_stack_limit( cyg_ucount32 size ){    void *ret = (void *)stack_limit;    // First lock the scheduler because we're going to be tinkering with    // the check data    Cyg_Scheduler::lock();    // if we've inc'd the limit before, it will be off by the check data    // size, so lets correct it    if (stack_limit != stack_base)        stack_limit -= CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;    stack_limit += size;    // determine base of check data by rounding up to nearest word aligned    // address if not already aligned    cyg_uint32 *p = (cyg_uint32 *)((stack_limit + 3) & ~3);    // i.e. + sizeof(cyg_uint32)-1) & ~(sizeof(cyg_uint32)-1);    cyg_ucount32 i;    cyg_uint32 sig = (cyg_uint32)this;        for ( i = 0;          i < CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE/sizeof(cyg_uint32);          i++ ) {        p[i] = (sig ^ (i * 0x01010101));    }    // increment limit by the check size. Note this will not necessarily    // reach the end of the check data. But that doesn't really matter.    // Doing this allows better checking of the saved stack pointer in    // Cyg_Thread::check_this()    stack_limit += CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;    Cyg_Scheduler::unlock();        return ret;}#endif    // =========================================================================// Cyg_ThreadTimer member functions// -------------------------------------------------------------------------// Timer alarm function. Inspect the sleep_reason and if necessary wake// up the thread with an appropriate wake_reason.#ifdef CYGFUN_KERNEL_THREADS_TIMERvoidCyg_ThreadTimer::alarm(    Cyg_Alarm           *alarm,    CYG_ADDRWORD        data){    CYG_REPORT_FUNCTION();    Cyg_ThreadTimer *self = (Cyg_ThreadTimer *)data;    Cyg_Thread *thread = self->thread;        CYG_INSTRUMENT_THREAD(ALARM, 0, 0);        Cyg_Scheduler::lock();    Cyg_Thread::cyg_reason sleep_reason = thread->get_sleep_reason();        switch( sleep_reason ) {            case Cyg_Thread::DESTRUCT:    case Cyg_Thread::BREAK:    case Cyg_Thread::EXIT:    case Cyg_Thread::NONE:    case Cyg_Thread::WAIT:    case Cyg_Thread::DONE:        // Do nothing in any of these cases. Most are here to        // keep the compiler happy.        Cyg_Scheduler::unlock();        CYG_REPORT_RETURN();        return;    case Cyg_Thread::DELAY:        // The thread was simply delaying, unless it has been        // woken up for some other reason, wake it now.        thread->set_wake_reason(Cyg_Thread::DONE);        break;    case Cyg_Thread::TIMEOUT:        // The thread has timed out, set the wake reason to        // TIMEOUT and restart.        thread->set_wake_reason(Cyg_Thread::TIMEOUT);        break;    }    thread->wake();    Cyg_Scheduler::unlock();    CYG_REPORT_RETURN();}#endif// =========================================================================// The Idle thread// The idle thread is implemented as a single instance of the// Cyg_IdleThread class. This is so that it can be initialized before// main in a static constructor.// -------------------------------------------------------------------------// Data definitions// stack#ifdef CYGNUM_HAL_STACK_SIZE_MINIMUM# ifdef CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE#  if CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM// then override the configured stack size#   undef CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE#   define CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM#  endif // CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM# endif // CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE#endif // CYGNUM_HAL_STACK_SIZE_MINIMUMstatic char idle_thread_stack[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];// Loop counter for debugging/housekeepingcyg_uint32 idle_thread_loops[CYGNUM_KERNEL_CPU_MAX];// -------------------------------------------------------------------------// Idle thread code.voididle_thread_main( CYG_ADDRESS data ){    CYG_REPORT_FUNCTION();    for(;;)    {        idle_thread_loops[CYG_KERNEL_CPU_THIS()]++;        HAL_IDLE_THREAD_ACTION(idle_thread_loops[CYG_KERNEL_CPU_THIS()]);#if 0        // For testing, it is useful to be able to fake        // clock interrupts in the idle thread.                Cyg_Clock::real_time_clock->tick();#endif#ifdef CYGIMP_IDLE_THREAD_YIELD        // In single priority and non-preemptive systems,        // the idle thread should yield repeatedly to        // other threads.        Cyg_Thread::yield();#endif    }}// -------------------------------------------------------------------------// Idle thread classclass Cyg_IdleThread : public Cyg_Thread{public:    Cyg_IdleThread();        };// -------------------------------------------------------------------------// Instantiate the idle threadCyg_IdleThread idle_thread[CYGNUM_KERNEL_CPU_MAX] CYG_INIT_PRIORITY( IDLE_THREAD );// -------------------------------------------------------------------------// Idle threads constructorCyg_IdleThread::Cyg_IdleThread()    : Cyg_Thread( CYG_THREAD_MIN_PRIORITY,                  idle_thread_main,                  0,                  "Idle Thread",                  (CYG_ADDRESS)idle_thread_stack[this-&idle_thread[0]],                  CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE){    CYG_REPORT_FUNCTION();    // Call into scheduler to set up this thread as the default    // current thread for its CPU.        Cyg_Scheduler::scheduler.set_idle_thread( this, this-&idle_thread[0] );    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// EOF common/thread.cxx

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -