📄 thread.cxx
字号:
// Allow preemption Cyg_Scheduler::unlock(); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Set thread priority#ifdef CYGIMP_THREAD_PRIORITYvoidCyg_Thread::set_priority( cyg_priority new_priority ){ 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,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 CYG_SCHED_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 // !CYG_SCHED_UNIQUE_PRIORITIES#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_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 // CYG_SCHED_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( this == Cyg_Scheduler::get_current_thread() ) Cyg_Scheduler::need_reschedule = true; // 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<<CYGNUM_KERNEL_THREADS_DATA_MAX)-1);cyg_ucount32Cyg_Thread::new_data_index(){ Cyg_Scheduler::lock(); cyg_ucount32 index; CYG_ASSERT( thread_data_map != 0 , "No more thread data indexes"); // 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_ucount32 index ){ Cyg_Scheduler::lock(); thread_data_map |= (1<<index); Cyg_Scheduler::unlock(); }#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_THREADS_IDLE_STACK_SIZE];// Loop counter for debugging/housekeepingcyg_uint32 idle_thread_loops = 1;// -------------------------------------------------------------------------// Idle thread code.voididle_thread_main( CYG_ADDRESS data ){ CYG_REPORT_FUNCTION(); for(;;) { idle_thread_loops++; HAL_IDLE_THREAD_ACTION(idle_thread_loops);#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( cyg_thread_entry *entry, // entry point function CYG_ADDRWORD entry_data, // entry data cyg_ucount32 stack_size = 0, // stack size, 0 = use default CYG_ADDRESS stack_base = 0 // stack base, NULL = allocate ); };// -------------------------------------------------------------------------// Idle threads constructorCyg_IdleThread::Cyg_IdleThread( cyg_thread_entry *entry, // entry point function CYG_ADDRWORD entry_data, // entry data cyg_ucount32 stack_size, // stack size, 0 = use default CYG_ADDRESS stack_base // stack base, NULL = allocate ) : Cyg_Thread( CYG_THREAD_MIN_PRIORITY, entry, entry_data, "Idle Thread", stack_base, stack_size){ CYG_REPORT_FUNCTION(); resume(); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Instantiate the idle threadCyg_IdleThread idle_thread CYG_INIT_PRIORITY( IDLE_THREAD ) =Cyg_IdleThread( idle_thread_main, 0, CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE, CYG_ADDRESS(idle_thread_stack) ); // -------------------------------------------------------------------------// EOF common/thread.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -