線程結(jié)構(gòu)學(xué)習(xí)筆記
Cyg_Thread分析
依然是從數(shù)據(jù)結(jié)構(gòu)開(kāi)始:
enum { // Thread state values
RUNNING = 0, // Thread is runnable or running,正在運(yùn)行,或者條件就緒,等待CPU
SLEEPING = 1, // Thread is waiting for something to happen,休眠態(tài),等待著事件發(fā)生(不報(bào)含等待CPU),
COUNTSLEEP = 2, // Sleep in counted manner,休眠態(tài),等待記數(shù)器到達(dá)指定的數(shù)值
SUSPENDED = 4, // Suspend count is non-zero,掛起,且計(jì)數(shù)器非零
CREATING = 8, // Thread is being created,線程正在被創(chuàng)建,代碼中未發(fā)現(xiàn)使用該狀態(tài)
EXITED = 16, // Thread has exited,線程已經(jīng)退出
// This is the set of bits that must be cleared by a generic
// wake() or release().
SLEEPSET = (SLEEPING | COUNTSLEEP) //休眠集合,通常由wake()函數(shù)或者release()函數(shù)清除。
};
cyg_uint32 state; //記錄線程的狀態(tài)
// Suspension counter, if > 0, the thread is suspended,掛起計(jì)數(shù)器,大于0表示線程處于掛起的狀態(tài)
cyg_ucount32 suspend_count;
// Wakeup counter, if > 0, sleep will not sleep, just decrement,喚醒計(jì)數(shù)器,大于0時(shí),線程將不會(huì)休眠,僅僅是此數(shù)值減1
cyg_ucount32 wakeup_count;
// A word of data used in syncronization object to communicate
// information between sleepers and wakers.
CYG_ADDRWORD wait_info; //等待信息,說(shuō)明線程等待的事件,用于休眠線程和喚醒線程之間的通信
// Unique thread id assigned on creation,線程ID,每個(gè)線程都有一個(gè)唯一的ID
cyg_uint16 unique_id;
Cyg_Exception_Control exception_control;//異??刂凭浔?/P>
enum cyg_reason // sleep/wakeup reason codes 休眠/喚醒的原因
{
NONE, // No recorded reason,未記錄的原因
WAIT, // Wait with no timeout,正在等待定時(shí)器時(shí)刻到來(lái)
DELAY, // Simple time delay,簡(jiǎn)單的事件延遲
TIMEOUT, // Wait with timeout/timeout expired,等待時(shí)間到
BREAK, // forced break out of sleep,強(qiáng)行脫離休眠狀態(tài)
DESTRUCT, // wait object destroyed[note],等待對(duì)象給destory
EXIT, // forced termination,線程被強(qiáng)行終止
DONE // Wait/delay complete,等待/延遲結(jié)束
};
#ifdef CYGFUN_KERNEL_THREADS_TIMER
Cyg_ThreadTimer timer; // per-thread timer,線程定時(shí)器,每個(gè)線程都會(huì)有一個(gè)
#endif
cyg_reason sleep_reason; // reason for sleeping,休眠原因
cyg_reason wake_reason; // reason for waking,喚醒原因
char *name; //線程名稱
Cyg_Thread *list_next; //指向下一個(gè)線程的指針
static Cyg_Thread *thread_list; //指向線程鏈表的指針
下面詳細(xì)分析線程狀態(tài)的切換,以及切換原因的分析
cyg_uint32 state; //記錄線程的狀態(tài)
(1)線程剛剛創(chuàng)建的時(shí)候線程狀態(tài)為SUSPENDED,參見(jiàn)Cyg_Thread類的構(gòu)造函數(shù)。
// 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() 函數(shù):將RUNNING轉(zhuǎn)換為SLEEPING,注意直接與SLEEPING相或,因?yàn)镽UNNING的值為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()函數(shù):清除SLEEPSET,此時(shí)可能還有別的狀態(tài),因此要進(jìn)一步判斷是否為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()函數(shù)(后一個(gè)為定時(shí)器版本):wakeup_count為0,進(jìn)入休眠態(tài),否則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()函數(shù):
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()函數(shù):suspend_count計(jì)數(shù)器,每調(diào)用一次該數(shù)值增加1。如果原來(lái)在運(yùn)行態(tài),要退出運(yùn)行隊(duì)列。注意后面的或運(yùn)算。
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()函數(shù):suspend_count--,如果為0,且狀態(tài)變?yōu)镽UNNING進(jìn)入運(yùn)行隊(duì)列。
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()函數(shù):suspend_count置零,如果為RUNNING,則進(jìn)入RUNNING隊(duì)列
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()函數(shù):進(jìn)入EXITED狀態(tài),并從運(yùn)行隊(duì)列中刪除(確定一定在運(yùn)行隊(duì)列嗎?)
if( self->state != EXITED )
{
self->state = EXITED;
Cyg_Scheduler::scheduler.rem_thread(self);
}
(10)kill函數(shù):如果是運(yùn)行態(tài)要先退出
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():線程在運(yùn)行態(tài)要先退出運(yùn)行隊(duì)列,如果是休眠態(tài)也要退出所在的隊(duì)列
// 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();
}
}
優(yōu)先級(jí)設(shè)置完畢后,要重新放回原來(lái)的隊(duì)列。注意從原來(lái)的隊(duì)列中刪除時(shí)并沒(méi)有改變響應(yīng)的狀態(tài)。
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個(gè)函數(shù),我們可以對(duì)線程狀態(tài)有個(gè)大概了解。
(1)線程剛剛創(chuàng)建的時(shí)候線程狀態(tài)為SUSPENDED
(2)RUNNING 通過(guò)sleep函數(shù)變?yōu)镾LEEPING態(tài)
(3)wake函數(shù)清除SLEEPSET狀態(tài)
(4)counted_sleep()函數(shù)在wakeup_count==0進(jìn)入COUNTEDSLEEP狀態(tài),否則wakeup_count--
(5)counted_wake()函數(shù)清除COUNTSLEEP狀態(tài),如果已經(jīng)清除則wakeup_count開(kāi)始計(jì)數(shù)
(6)suspend函數(shù)進(jìn)入SUSPEND狀態(tài),并增加suspend_count計(jì)數(shù)器
(7)resume()suspend_count計(jì)數(shù)器--,為0消除SUSPENDED狀態(tài)
(8)force_resume()直接清除SUSPENDED狀態(tài)
(9)exit函數(shù)進(jìn)入EXIT狀態(tài)
(10)kill函數(shù)進(jìn)入EXIT狀態(tài)
suspend_count計(jì)數(shù)器的操作:suspend函數(shù)加1,resume函數(shù)減1
wake_count計(jì)數(shù)器的操作:
cancel_counted_wake()清0;
counted_sleep()函數(shù)在wakeup_count==0進(jìn)入COUNTEDSLEEP狀態(tài),否則wakeup_count--;
counted_wake()函數(shù)在COUNTSLEEP狀態(tài)清除后每調(diào)用一次,wakeup_count++
評(píng)論