系统进程etimer_process管理timelist,本文先给出etimer_process的启动,而后深入源码分析etimer_process的执行主体,追踪了其所涉及到的宏和函数。
一、启动etimer_process
在main函数中,先是进行一系列初始化,接着启动系统进程etimer_process和指针数组autostart_processes[]里的所有进程。源代码如下:
-
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是否到期。源代码如下:
-
//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*p =data; //此时通过data传递将要退出的进程,data是void *类型
/*遍历timerlist,查找是否有etimer绑定该退出进程*/
while(timerlist !=NULL&&timerlist->p ==p)
{
timerlist =timerlist->next;
}
/*有etimer绑定该退出进程,将etimer从timerlist删除*/
{
t =timerlist;
while(t->next!=NULL)
{
if(t->next->p ==p)
{
t->next=t->next->next;
}
else
t =t->next;
}
}
continue;//删除所有与退出进程绑定的etimer
}
elseif(ev !=PROCESS_EVENT_POLL) //不解?
{
continue;
}
again:
u =NULL;
for(t =timerlist;t !=NULL;t =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->p =PROCESS_NONE; //如果etimer的p指向的是PROCESS_NONE,则表示该etimer已到期。用于后续etimer_expired()函数判断该etimer是否到期,etimer_expired(),也见2.2
if(u !=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)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->p ==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,p ==PROCESS_BROADCAST ?
"
}
/*事件队列已满,返回PROCESS_ERR_FULL,即1*/
if(nevents ==PROCESS_CONF_NUMEVENTS)
{
#ifDEBUG
if(p ==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 =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 =t->next;t !=NULL;t =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(p !=NULL)
{
if(p->state==PROCESS_STATE_RUNNING ||p->state==PROCESS_STATE_CALLED)
{
p->needspoll =1;
poll_requested =1;//全局变量,标识是否有needspoll为1的进程
}
}