rt-thread的IPC机制之邮箱源码分析(三)

2014-11-24 07:52:27 · 作者: · 浏览: 3
mailbox is empty */
while (mb->entry == 0)//如果当前邮箱无信件
{
/* reset error number in thread */
thread->error = RT_EOK;//初始化error值为RT_EOK
/* no waiting, return timeout */
if (timeout == 0)//如果当前线程无等待时间,则立即返回超时错误
{
/* enable interrupt */
rt_hw_interrupt_enable(temp);
thread->error = -RT_ETIMEOUT;
return -RT_ETIMEOUT;
}
RT_DEBUG_NOT_IN_INTERRUPT;//确保当前不是在ISR中使用
/* suspend current thread */
rt_ipc_list_suspend(&(mb->parent.suspend_thread),//挂起当前接收线程,(当前线程的timeout!=0)
thread,
mb->parent.parent.flag);
/* has waiting time, start thread timer */
if (timeout > 0)
{
/* get the start tick of timer */
tick_delta = rt_tick_get();//得到当前tick
RT_DEBUG_LOG(RT_DEBUG_IPC, ("mb_recv: start timer of thread:%s\n",
thread->name));
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),//设置定时器
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));//启动定时器
}
/* enable interrupt */
rt_hw_interrupt_enable(temp);//开中断
/* re-schedule */
rt_schedule();//重新调度
/* resume from suspend state */
if (thread->error != RT_EOK)//如果没有正常收到邮件,参见互斥锁相关说明
{
/* return error */
return thread->error;//则返回错误
}
/* disable interrupt */
temp = rt_hw_interrupt_disable();//开中断
/* if it's not waiting forever and then re-calculate timeout tick */
if (timeout > 0)//如果时间参数不是RT_WAITING_FOREVER
{
tick_delta = rt_tick_get() - tick_delta;//得到当前已经过了多长时间
timeout -= tick_delta;//计算剩下等待时间
if (timeout < 0)//如果所有等待时间都已耗尽,则直接就timeout设置为0,再进入下一循环
timeout = 0;
}
}
/* fill ptr */
*value = mb->msg_pool[mb->out_offset];//保存接收到的邮件内容
/* increase output offset */
++ mb->out_offset;//出品偏移加1
if (mb->out_offset >= mb->size)//如果指向缓冲末尾,则改为指向首地址,由此得出邮箱的接收缓冲为一个ring buffer
mb->out_offset = 0;
/* decrease message entry */
mb->entry --;//取出邮件后,邮件个数应减1
/* resume suspended thread */
if (!rt_list_isempty(&(mb->suspend_sender_thread)))//如果邮箱的挂起发送线程不为空
{
rt_ipc_list_resume(&(mb->suspend_sender_thread));//则唤醒第一个挂起的发送线程
/* enable interrupt */
rt_hw_interrupt_enable(temp);//开中断
RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent)));
rt_schedule();//重新调度
return RT_EOK;
}
/* enable interrupt */
rt_hw_interrupt_enable(temp);//开中断
RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent)));
return RT_EOK;
}
接收邮件函数会判断当前邮箱是否为空且时间参数为0, 如果是则直接返回,然后进行一个while循环,在这个while循环中的判断条件是邮箱为空,为什么要这么做呢?因此程序将在这个 while循环内一直等待邮件的到达,只有邮件到达才会跳出这个循环(如果等待超时则直接函数返回了),另一个是原因呆会再解释。进入while循环后,程序再次判断当前的等待时间参数是否为0,如果是则直接返回,为什么这里还要这样判断呢?这里是有一定的用意的,且接着往下看。接着挂起当前线程,再次判断时间参数是否大于0,这里主要是扫除timeout=RT_WAITING_FOREVER的情况,因为RT_WA