Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393239
  • 博文数量: 87
  • 博客积分: 1171
  • 博客等级: 少尉
  • 技术积分: 1068
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-19 14:34
文章分类

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-12 20:25:46

       

        系统进程etimer_process管理timelist,本文先给出etimer_process的启动,而后深入源码分析etimer_process的执行主体,追踪了其所涉及到的宏和函数。


一、启动etimer_process

    在main函数中,先是进行一系列初始化,接着启动系统进程etimer_process和指针数组autostart_processes[]里的所有进程。源代码如下:

  1. intmain()

    {

      dbg_setup_uart();

      clock_init();

      process_init();


      process_start(&etimer_process,NULL);//启动etimer_process

      autostart_start(autostart_processes); //启动指针数组autostart_processes[]里的所有进程


      while(1)

      {

        do

        {}while(process_run()>0);

      }

      return0;

    }

   

 


二、etimer_process执行主体剖析

   进程退出时,需向所有进程(当然也包括etimer_process)发送事件PROCESS_EVENT_EXITED。etimer_process收到该事件,就会遍历timerlist,并把与该退出进程相关的etimer从timerlist删除。紧接着,遍历timerlist,检查etimer是否有到期的,凡有timer到期就把事件PROCESS_EVENT_TIMER加入到事件队列中,并将该etimer成员变量p指向PROCESS_NONE。在这里,PROCESS_NONE用于标识该etimer是否到期,即由etimer_expired函数根据etimer的p是否指向PROCESS_NONE来判断该etimer是否到期。源代码如下:

  1. //PROCESS(etimer_process, "Event timer");

    PROCESS_THREAD(etimer_process,ev,data)

    {

      structetimer *t,*u;


      PROCESS_BEGIN();


      timerlist =NULL;


      while(1)

      {

        PROCESS_YIELD();/*见2.1*/


        /*进程退出时,需向所有进程(当然也包括etimer_process)发送事件PROCESS_EVENT_EXITED。etimer_process收到该事件,就会遍历timerlist,并把与该退出进程相关的etimer从timerlist删除*/

        if(ev ==PROCESS_EVENT_EXITED)

        {

          structprocess*=data;  //此时通过data传递将要退出的进程,data是void *类型


          /*遍历timerlist,查找是否有etimer绑定该退出进程*/

          while(timerlist !=NULL&&timerlist->==p)

          {

            timerlist =timerlist->next;

          }


          /*有etimer绑定该退出进程,将etimer从timerlist删除*/

          

          {

            t =timerlist;

            while(t->next!=NULL)

            {

              if(t->next->==p)

              {

                t->next=t->next->next;

              }

              else

                t =t->next;

            }

          }


          continue;//删除所有与退出进程绑定的etimer

        }

        elseif(ev !=PROCESS_EVENT_POLL)  //不解?

        {

          continue;

        }


        again:


        u =NULL;

        for(=timerlist;!=NULL;=t->next)

        {

          if(timer_expired(&t->timer)) //检查该etimer的timer是不是到期,返回1表示过期,详情见2.2

          {

            if(process_post(t->p,PROCESS_EVENT_TIMER,t)==PROCESS_ERR_OK//详情见2.3,即把事件PROCESS_EVENT_TIMER加入到事件队列

            {

              /*成功加入事件队列*/


              t->=PROCESS_NONE; //如果etimer的p指向的是PROCESS_NONE,则表示该etimer已到期。用于后续etimer_expired()函数判断该etimer是否到期,etimer_expired(),也见2.2


              if(!=NULL)

              {

                u->next=t->next;

              }

              else

              {

                timerlist =t->next;

              }

              t->next=NULL;

              update_time(); /*见2.4,即求出下一个到期时间next_expiration (全局静态变量),即还有next_expiration时间,就有timer到期*/

              gotoagain;

            }

            else

            {

              etimer_request_poll(); //详情见2.5 若加入事件PROCESS_EVENT_TIMER出错(可能是事件队列已满),执行etimer_request_poll(),即process_poll(&etimer_process),使其有更高的优先级

            }

          }

          u =t;

        }


      }


      PROCESS_END

    }

2.1 PROCESS_YIELD宏

/*即进程主动让出执行权*/

#define PROCESS_YIELD()PT_YIELD(process_pt)


/*继续展开如下,Yield from the current protothread*/

#define PT_YIELD(pt)\

do{\

PT_YIELD_FLAG =0;\

LC_SET((pt)->lc);\

if(PT_YIELD_FLAG ==0){\

returnPT_YIELDED;\

}\

}while(0)


#define LC_SET(s)=__LINE__;case__LINE__:  /*保存被中断的行数*/

2.2 timer_expired和etimer_expired

2.2.1 timer_expired

/*即检查timer是不是到期了,若到期返回1,否则返回0*/

inttimer_expired(structtimer*t)

{

  clock_time_t diff =(clock_time()-t->start)+1;

  returnt->interval <diff;

}

注:为什么不直接return diff >= t->interval,源代码注释给出原因,如下:

Note: Can not return diff >= t->interval so we add 1 to diff and return t->interval < diff - required to avoid an internal error in mspgcc.

2.2.2 etimer_expired

    etimer_expired跟timer_expired不一样,后者到期是指定时器超时(通过比较当前时间与start+interval来判断timer是否到期),而前者到期是指已发送事件PROCESS_EVENT_TIMER给etimer绑定的进程(通过etimer的p指向是否为PROCESS_NONE来判断)。源码如下:

intetimer_expired(structetimer *et)

{

  returnet->==PROCESS_NONE;

}

2.3 process_post函数

//即把把事件加入到事件队列

intprocess_post(structprocess*p,process_event_t ev,process_data_t data)

{

  staticprocess_num_events_t snum;


  /*调试信息,直接无视*/

  if(PROCESS_CURRENT()==NULL)

  {

    PRINTF(

      "process_post: NULL process posts event %d to process '%s', nevents %d\n",

      ev,PROCESS_NAME_STRING(p),nevents);

  }

  else

  {

    PRINTF(

      "process_post: Process '%s' posts event %d to process '%s', nevents %d\n",

      PROCESS_NAME_STRING(PROCESS_CURRENT()),ev,==PROCESS_BROADCAST ?

      "":PROCESS_NAME_STRING(p),nevents);

  }


  /*事件队列已满,返回PROCESS_ERR_FULL,即1*/

  if(nevents ==PROCESS_CONF_NUMEVENTS)

  {

    #ifDEBUG

      if(==PROCESS_BROADCAST)

      {

        printf(

          

      }

      else

      {

        printf(

          "soft panic: event queue is full when event %d was posted to %s frpm %s\n",ev,PROCESS_NAME_STRING(p),PROCESS_NAME_STRING(process_current));

      }

    #endif /* DEBUG */

    returnPROCESS_ERR_FULL;

  }


  /*将事件加入事件队列,并绑定进程p*/

  snum =(process_num_events_t)(fevent +nevents)%PROCESS_CONF_NUMEVENTS;

  //事件队列用环形组织

  events[snum].ev =ev;

  events[snum].data =data;

  events[snum].=p;

  ++nevents;


  #ifPROCESS_CONF_STATS

    if(nevents >process_maxevents)

    {

      process_maxevents =nevents;

    }

  #endif /* PROCESS_CONF_STATS */


  

}

2.4 update_time函数

/*即求出下一个到期时间next_expiration(全局静态变量),即还有next_expiration时间,就有timer到期*/

staticvoidupdate_time(void)

{

  clock_time_t tdist;

  clock_time_t now;

  structetimer *t;


  if(timerlist ==NULL)

  {

    next_expiration =0;

  }

  else

  {

    now =clock_time();

    t =timerlist;


    /*遍历timerlist,找出最近到期的timer,并求得下一个到期时间next_expiration*/

    tdist =t->timer.start+t->timer.interval -now;//还有tdist就到期了

    for(=t->next;!=NULL;=t->next)

    {

      if(t->timer.start+t->timer.interval -now <tdist)

      {

        tdist =t->timer.start+t->timer.interval -now;

      }

    }

    next_expiration =now +tdist;

  }

}

2.5 etimer_request_poll函数

voidetimer_request_poll(void)

{

  process_poll(&etimer_process);

}


//将进程p的needspoll设为1,使其获得更高优先级,即让etimer_process更快地再次获得执行权

voidprocess_poll(structprocess*p)

{

  if(!=NULL)

  {

    if(p->state==PROCESS_STATE_RUNNING ||p->state==PROCESS_STATE_CALLED)

    {

      p->needspoll =1;

      poll_requested =1;//全局变量,标识是否有needspoll为1的进程

    }

  }

}
 
 
阅读(1737) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~