线程结构学习笔记
Cyg_Thread分析
依然是从数据结构开始:
enum { // Thread state values
RUNNING = 0, // Thread is runnable or running,正在运行,或者条件就绪,等待CPU
SLEEPING = 1, // Thread is waiting for something to happen,休眠态,等待着事件发生(不报含等待CPU),
COUNTSLEEP = 2, // Sleep in counted manner,休眠态,等待记数器到达指定的数值
SUSPENDED = 4, // Suspend count is non-zero,挂起,且计数器非零
CREATING = 8, // Thread is being created,线程正在被创建,代码中未发现使用该状态
EXITED = 16, // Thread has exited,线程已经退出
// This is the set of bits that must be cleared by a generic
// wake() or release().
SLEEPSET = (SLEEPING | COUNTSLEEP) //休眠集合,通常由wake()函数或者release()函数清除。
};
cyg_uint32 state; //记录线程的状态
// Suspension counter, if > 0, the thread is suspended,挂起计数器,大于0表示线程处于挂起的状态
cyg_ucount32 suspend_count;
// Wakeup counter, if > 0, sleep will not sleep, just decrement,唤醒计数器,大于0时,线程将不会休眠,仅仅是此数值减1
cyg_ucount32 wakeup_count;
// A word of data used in syncronization object to communicate
// information between sleepers and wakers.
CYG_ADDRWORD wait_info; //等待信息,说明线程等待的事件,用于休眠线程和唤醒线程之间的通信
// Unique thread id assigned on creation,线程ID,每个线程都有一个唯一的ID
cyg_uint16 unique_id;
Cyg_Exception_Control exception_control;//异常控制句柄
enum cyg_reason // sleep/wakeup reason codes 休眠/唤醒的原因
{
NONE, // No recorded reason,未记录的原因
WAIT, // Wait with no timeout,正在等待定时器时刻到来
DELAY, // Simple time delay,简单的事件延迟
TIMEOUT, // Wait with timeout/timeout expired,等待时间到
BREAK, // forced break out of sleep,强行脱离休眠状态
DESTRUCT, // wait object destroyed[note],等待对象给destory
EXIT, // forced termination,线程被强行终止
DONE // Wait/delay complete,等待/延迟结束
};
#ifdef CYGFUN_KERNEL_THREADS_TIMER
Cyg_ThreadTimer timer; // per-thread timer,线程定时器,每个线程都会有一个
#endif
cyg_reason sleep_reason; // reason for sleeping,休眠原因
cyg_reason wake_reason; // reason for waking,唤醒原因
char *name; //线程名称
Cyg_Thread *list_next; //指向下一个线程的指针
static Cyg_Thread *thread_list; //指向线程链表的指针
下面详细分析线程状态的切换,以及切换原因的分析
cyg_uint32 state; //记录线程的状态
(1)线程刚刚创建的时候线程状态为SUSPENDED,参见Cyg_Thread类的构造函数。
// Start the thread in suspended state.
state = SUSPENDED;
suspend_count = 1;
wakeup_count = 0;
// Initialize sleep_reason which is used by kill, release
sleep_reason = NONE;
wake_reason = NONE;
(2)sleep() 函数:将RUNNING转换为SLEEPING,注意直接与SLEEPING相或,因为RUNNING的值为0
// If running, remove from run qs
if ( current->state == RUNNING )
Cyg_Scheduler::scheduler.rem_thread(current);
// Set the state
current->state |= SLEEPING;
(3)wake()函数:清除SLEEPSET,此时可能还有别的状态,因此要进一步判断是否为RUNNING
if( 0 != (state & SLEEPSET) )
{
// Set the state
state &= ~SLEEPSET;
// remove from any queue we were on
remove();
// If the thread is now runnable, return it to run queue
if( state == RUNNING )
Cyg_Scheduler::scheduler.add_thread(this);
}
(4)counted_sleep()函数(后一个为定时器版本):wakeup_count为0,进入休眠态,否则wakeup_count--
if ( 0 == current->wakeup_count ) {
set_sleep_reason( Cyg_Thread::WAIT );
current->sleep(); // prepare to sleep
current->state |= COUNTSLEEP; // Set the state
}
else
// there is a queued wakeup, do not sleep
current->wakeup_count--;
if ( 0 == current->wakeup_count ) {
// Set the timer (once outside any waiting loop.)
set_timer( Cyg_Clock::real_time_clock->current_value()+delay,
Cyg_Thread::TIMEOUT );
// If the timeout is in the past, the wake reason will have been
// set to something other than NONE already.
if( current->get_wake_reason() == Cyg_Thread::NONE )
{
set_sleep_reason( Cyg_Thread::TIMEOUT );
current->sleep(); // prepare to sleep
current->state |= COUNTSLEEP; // Set the state
Cyg_Scheduler::reschedule();
// clear the timer; if it actually fired, no worries.
clear_timer();
}
}
else
// there is a queued wakeup, do not sleep
current->wakeup_count--;
(5)counted_wake()函数:
if ( 0 == (state & COUNTSLEEP) ) // already awake, or waiting:
wakeup_count++; // not in a counted sleep anyway.
else {
sleep_reason = NONE;
wake_reason = DONE;
wake(); // and awaken the thread
}
(6)suspend()函数:suspend_count计数器,每调用一次该数值增加1。如果原来在运行态,要退出运行队列。注意后面的或运算。
suspend_count++;
#ifdef CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT
CYG_ASSERT( CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT > suspend_count,
"suspend_count overflow" );
#endif
// If running, remove from run qs
if( state == RUNNING )
Cyg_Scheduler::scheduler.rem_thread(this);
// Set the state
state |= SUSPENDED;
(7)resume()函数:suspend_count--,如果为0,且状态变为RUNNING进入运行队列。
if( suspend_count == 1 )
{
suspend_count = 0;
CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
// Set the state
state &= ~SUSPENDED;
// Return thread to scheduler if runnable
if( state == RUNNING )
Cyg_Scheduler::scheduler.add_thread(this);
}
else
if( suspend_count > 0 )
suspend_count--;
(8)force_resume()函数:suspend_count置零,如果为RUNNING,则进入RUNNING队列
if ( 0 < suspend_count ) {
suspend_count = 0;
CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
// Set the state
state &= ~SUSPENDED;
// Return thread to scheduler if runnable
if( state == RUNNING )
Cyg_Scheduler::scheduler.add_thread(this);
}
(9)exit()函数:进入EXITED状态,并从运行队列中删除(确定一定在运行队列吗?)
if( self->state != EXITED )
{
self->state = EXITED;
Cyg_Scheduler::scheduler.rem_thread(self);
}
(10)kill函数:如果是运行态要先退出
case NONE:
// The thread is not sleeping for any reason, it must be
// on a run queue.
// We can safely deschedule and set its state.
if( state == RUNNING ) Cyg_Scheduler::scheduler.rem_thread(this);
state = EXITED;
break;
(11)set_priority():线程在运行态要先退出运行队列,如果是休眠态也要退出所在的队列
// 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();
}
}
优先级设置完毕后,要重新放回原来的队列。注意从原来的队列中删除时并没有改变响应的状态。
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);
}
}
由上述11个函数,我们可以对线程状态有个大概了解。
(1)线程刚刚创建的时候线程状态为SUSPENDED
(2)RUNNING 通过sleep函数变为SLEEPING态
(3)wake函数清除SLEEPSET状态
(4)counted_sleep()函数在wakeup_count==0进入COUNTEDSLEEP状态,否则wakeup_count--
(5)counted_wake()函数清除COUNTSLEEP状态,如果已经清除则wakeup_count开始计数
(6)suspend函数进入SUSPEND状态,并增加suspend_count计数器
(7)resume()suspend_count计数器--,为0消除SUSPENDED状态
(8)force_resume()直接清除SUSPENDED状态
(9)exit函数进入EXIT状态
(10)kill函数进入EXIT状态
suspend_count计数器的操作:suspend函数加1,resume函数减1
wake_count计数器的操作:
cancel_counted_wake()清0;
counted_sleep()函数在wakeup_count==0进入COUNTEDSLEEP状态,否则wakeup_count--;
counted_wake()函数在COUNTSLEEP状态清除后每调用一次,wakeup_count++
评论