新闻中心

EEPW首页 > 学习方法与实践 > 线程结构学习笔记

线程结构学习笔记

——
作者:时间:2007-03-06来源:收藏

 

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++

尘埃粒子计数器相关文章:尘埃粒子计数器原理


关键词: 线程结构

评论


技术专区

关闭