etimer处理由系统进程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.etimer_process
<span style="font-size:14px;">//PROCESS(etimer_process, "Event timer");
PROCESS_THREAD(etimer_process, ev, data)
{
struct etimer *t, *u;
PROCESS_BEGIN();
timerlist = NULL;
while (1)
{
PROCESS_YIELD();//见2
/*进程退出时,需向所有进程(当然也包括etimer_process)发送事件PROCESS_EVENT_EXITED。etimer_process收到该事件,就会遍历timerlist,并把与该退出进程相关的etimer从timerlist删除*/
if (ev == PROCESS_EVENT_EXITED)
{
struct process *p = data;//此时通过data传递将要退出的进程,data是void *类型
//遍历timerlist,查找是否有etimer绑定该退出进程
while (timerlist != NULL && timerlist->p == p)
{
timerlist = timerlist->next;
}
//有etimer绑定该退出进程,将etimer从timerlist删除
if (timerlist != NULL)
{
t = timerlist;
while (t->next != NULL)
{
if (t->next->p == p)
{
t->next = t->next->next;
}
else
t = t->next;
}
}
continue; //删除所有与退出进程绑定的etimer
}
else if (ev != PROCESS_EVENT_POLL)
{
continue;
}
again:
u = NULL;
for (t = timerlist; t != NULL; t = t->next)
{
if (timer_expired(&t->timer)) //检查该etimer的timer是不是到期,返回1表示过期,详情见3
{
//详情见4,即把事件PROCESS_EVENT_TIMER加入到事件队列
if(process_post(t->p,PROCESS_EVENT_TIMER,t)==PROCESS_ERR_OK)
{
/*成功加入事件队列*/
t->p = PROCESS_NONE;//如果etimer的p指向的是PROCESS_NONE,则表示该etimer已到期。用于后续etimer_expired()函数判断该etimer是否到期,etimer_expired(),也见3.5.3
if (u != NULL)
{
u->next = t->next;
}
else
{
timerlist = t->next;
}
t->next = NULL;
update_time(); /*见5,即求出下一个到期时间next_expiration (全局静态变量),即还有next_expiration时间,就有timer到期*/
goto again;
}
else
{
etimer_request_poll(); //详情见6,若加入事件PROCESS_EVENT_TIMER出错(可能是事件队列已满),执行etimer_request_poll(),即process_poll(&etimer_process),使其有更高的优先级
}
}
u = t;
}
}
PROCESS_END();
}</span><span style="font-size:18px;">
</span>
2.PROCESS_YEILD
//即进程主动让出执行权
#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) {
return PT_YIELDED;
}
} while(0)
#define LC_SET(s) s = __LINE__; case __LINE__: /*保存被中断的行数*/
3.timer_expired
/* etimer_expired跟timer_expired不一样,后者到期是指定时器超时(通过比较当前时间与start+interval来判断timer是否到期),而前者到期是指已发送事件PROCESS_EVENT_TIMER给etimer绑定的进程(通过etimer的p指向是否为PROCESS_NONE来判断)。*/
//①timer_expired函数
//即检查timer是不是到期了,若到期返回1,否则返回0
int timer_expired(struct timer *t)
{
clock_time_t diff = (clock_time() - t->start) + 1;
return t->interval < diff;
}
//②etimer_expired函数
int etimer_expired(struct etimer *et)
{
return et->p == PROCESS_NONE;
}
4.process_post
//即把把事件加入到事件队列
int process_post(struct process *p, process_event_t ev, process_data_t data)
{
static process_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_NAME_STRING(p), nevents);
}
/*事件队列已满,返回PROCESS_ERR_FULL,即1*/
if (nevents == PROCESS_CONF_NUMEVENTS)
{
#if DEBUG
if (p == PROCESS_BROADCAST)
{
printf(
"soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));
}
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 */
return PROCESS_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;
#if PROCESS_CONF_STATS
if (nevents > process_maxevents)
{
process_maxevents = nevents;
}
#endif /* PROCESS_CONF_STATS */
return PROCESS_ERR_OK;
}
5.update_time
/*即求出下一个到期时间next_expiration(全局静态变量),即还有next_expiration时间,就有timer到期*/
static void update_time(void)
{
clock_time_t tdist;
clock_time_t now;
struct etimer *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;
}
}
6.etime_request_poll
void etimer_request_poll(void)
{
process_poll(&etimer_process);
}
//将进程p的needspoll设为1,使其获得更高优先级,即让etimer_process更快地再次获得执行权
void process_poll(struct process *p)
{
if (p != NULL)
{
if (p->state == PROCESS_STATE_RUNNING || p->state == PROCESS_STATE_CALLED)
{
p->needspoll = 1;
poll_requested = 1; //全局变量,标识是否有needspoll为1的进程
}
}
}