3 接口实现源码分析
3.1 初始化事件
[cpp] view plaincopyprint
/**
* This function will initialize an event and put it under control of resource
* management.
*
* @param event the event object
* @param name the name of event
* @param flag the flag of event
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)
{
RT_ASSERT(event != RT_NULL);
/* init object */
rt_object_init(&(event->parent.parent), RT_Object_Class_Event, name);//初始化事件的内核对象
/* set parent flag */
event->parent.parent.flag = flag;//设置内核对象的标志
/* init ipc object */
rt_ipc_object_init(&(event->parent));//初始化事件的IPC对象
/* init event */
event->set = 0;//初始化事件收到的事件集为空(每一个位表示一个事件)
return RT_EOK;
}
/**
* This function will initialize an event and put it under control of resource
* management.
*
* @param event the event object
* @param name the name of event
* @param flag the flag of event
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)
{
RT_ASSERT(event != RT_NULL);
/* init object */
rt_object_init(&(event->parent.parent), RT_Object_Class_Event, name);//初始化事件的内核对象
/* set parent flag */
event->parent.parent.flag = flag;//设置内核对象的标志
/* init ipc object */
rt_ipc_object_init(&(event->parent));//初始化事件的IPC对象
/* init event */
event->set = 0;//初始化事件收到的事件集为空(每一个位表示一个事件)
return RT_EOK;
}
3.2 创建事件
[cpp] view plaincopyprint
/**
* This function will create an event object from system resource
*
* @param name the name of event
* @param flag the flag of event
*
* @return the created event, RT_NULL on error happen
*/
rt_event_t rt_event_create(const char *name, rt_uint8_t flag)
{
rt_event_t event;
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不是在ISR中
/* allocate object */
event = (rt_event_t)rt_object_allocate(RT_Object_Class_Event, name);//动态分配事件的内核对象
if (event == RT_NULL)
return event;
/* set parent */
event->parent.parent.flag = flag;//设置事件的内核对象标志
/* init ipc object */
rt_ipc_object_init(&(event->parent));//初始化事件的IPC对象
/* init event */
event->set = 0;//初始化事件的接收到的事件集为空
return event;
}
/**
* This function will create an event object from system resource
*
* @param name the name of event
* @param flag the flag of event
*
* @return the created event, RT_NULL on error happen
*/
rt_event_t rt_event_create(const char *name, rt_uint8_t flag)
{
rt_event_t event;
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不是在ISR中
/* allocate object */
event = (rt_event_t)rt_object_allocate(RT_Object_Class_Event, name);//动态分配事件的内核对象
if (event == RT_NULL)
return event;
/* set parent */
event->parent.parent.flag = flag;//设置事件的内核对象标志
/* init ipc object */
rt_ipc_object_init(&(event->parent));//初始化事件的IPC对象
/* init event */
event->set = 0;//初始化事件的接收到的事件集为空
return event;
}
3.3 脱离事件
[cpp] view plaincopyprint
/**
* This function will detach an event object from resource management
*
* @param event the event object
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_event_detach(rt_event_t event)
{
/* parameter check */
RT_ASSERT(event != RT_NULL);
/* resume all suspended thread */
rt_ipc_list_resume_all(&(event->parent.suspend_thread));//唤醒所有因此事件而挂起的线程
/* detach event object */
rt_object_detach(&(event->parent.parent));//脱离事件的内核对象
return RT_EOK;
}
/**
* This function will detach an event object from resource management
*
* @param event the event object
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_event_detach(rt_event_t event)
{
/* parameter check */
RT_ASSERT(event != RT_NULL);
/* resume all suspended thread */
rt_ipc_list_resume_all(&(event->parent.suspend_thread));//唤醒所有因此事件而挂起的线程
/* detach event object */
rt_object_detach(&(event->parent.parent));//脱离事件的内核对象
return RT_EOK;
}
3.4 删除事件
[cpp] view plaincopyprint
/**
* This function will delete an event object and release the memory
*
* @param event the event object
*
* @return the error code
*/
rt_err_t rt_event_delete(rt_event_t event)
{
/* parameter check */
RT_ASSERT(event != RT_NULL);
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不是在ISR中使用
/* resume all suspended thread */
rt_ipc_list_resume_all(&(event->parent.suspend_thread));//唤醒所有因此事件而挂起的线程
/* delete event object */
rt_object_delete(&(event->parent.parent));//删除事件的内核对象
return RT_EOK;
}
/**
* This function will delete an event object and release the memory
*
* @param event the event object
*
* @return the error code
*/
rt_err_t rt_event_delete(rt_event_t event)
{
/* parameter check */
RT_ASSERT(event != RT_NULL);
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不是在ISR中使用
/* resume all suspended thread */
rt_ipc_list_resume_all(&(event->parent.suspend_thread));//唤醒所有因此事件而挂起的线程
/* delete event object */
rt_object_delete(&(event->parent.parent));//删除事件的内核对象
return RT_EOK;
}
3.5 发送事件
[cpp] view plaincopyprint
/**
* This function will send an event to the event object, if there are threads
* suspended on event object, it will be waked up.
*
* @param event the event object
* @param set the event set
*
* @return the error code
*/
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
{
struct rt_list_node *n;
struct rt_thread *thread;
register rt_ubase_t level;
register rt_base_t status;
rt_bool_t need_schedule;
/* parameter check */
RT_ASSERT(event != RT_NULL);
if (set == 0)//无任何事件,则直接返回
return -RT_ERROR;
need_schedule = RT_FALSE;//需要调度标志初始化为不需要
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(event->parent.parent)));
/* disable interrupt */
level = rt_hw_interrupt_disable();//关中断
/* set event */
event->set |= set;//事件的接收事件集或上发送的事件,即在事件控制块内保存接收到的事件
if (!rt_list_isempty(&event->parent.suspend_thread))//如果事件的挂起线程链表不为空
{
/* search thread list to resume thread */
n = event->parent.suspend_thread.next;//遍历所有挂起的线程
while (n != &(event->parent.suspend_thread))
{
/* get thread */
thread = rt_list_entry(n, struct rt_thread, tlist);//得到挂起的线程控制块
status = -RT_ERROR;
if (thread->event_info & RT_EVENT_FLAG_AND)//如果此挂起的线程为事件过滤方式为逻辑与
{
if ((thread->event_set & event->set) == thread->event_set)//即判断所有事件是否者触发
{
/* received an AND event */
status = RT_EOK;
}
}
else if (thread->event_info & RT_EVENT_FLAG_OR)//事件过滤方式为逻辑或
{
if (thread->event_set & event->set)//判断是否触发任一关心的事件
{
/* save recieved event set */
thread->event_set = thread->event_set & event->set;//将接收到的事件保存到线程中
/* received an OR event */
status = RT_EOK;
}
}
/* move node to the next */
n = n->next;//指向下一挂起的线程
/* condition is satisfied, resume thread */
if (status == RT_EOK)//符合唤醒条件
{
/* clear event */
if (thread->event_info & RT_EVENT_FLAG_CLEAR)//是否需要清除接收到的事件
event->set &= ~thread->event_set;//清除接收到的事件
/* resume thread, and thread list breaks out */
rt_thread_resume(thread);//唤醒此线程
/* need do a scheduling */
need_schedule = RT_TRUE;//设置需要重新调度标志
}
}
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
/* do a schedule */
if (need_schedule == RT_TRUE)
rt_schedule();//重新调试线程
return RT_EOK;
}
/**
* This function will send an event to the event object, if there are threads
* suspended on event object, it will be waked up.
*
* @param event the event object
* @param set the event set
*
* @return the error code
*/
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
{
struct rt_list_node *n;
struct rt_thread *thread;
register rt_ubase_t level;
register rt_base_t status;
rt_bool_t need_schedule;
/* parameter check */
RT_ASSERT(event != RT_NULL);
if (set == 0)//无任何事件,则直接返回
return -RT_ERROR;
need_schedule = RT_FALSE;//需要调度标志初始化为不需要
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(event->parent.parent)));
/* disable interrupt */
level = rt_hw_interrupt_disable();//关中断
/* set event */
event->set |= set;//事件的接收事件集或上发送的事件,即在事件控制块内保存接收到的事件
if (!rt_list_isempty(&event->parent.suspend_thread))//如果事件的挂起线程链表不为空
{
/* search thread list to resume thread */
n = event->parent.suspend_thread.next;//遍历所有挂起的线程
while (n != &(event->parent.suspend_thread))
{
/* get thread */
thread = rt_list_entry(n, struct rt_thread, tlist);//得到挂起的线程控制块
status = -RT_ERROR;
if (thread->event_info & RT_EVENT_FLAG_AND)//如果此挂起的线程为事件过滤方式为逻辑与
{
if ((thread->event_set & event->set) == thread->event_set)//即判断所有事件是否者触发
{
/* received an AND event */
status = RT_EOK;
}
}
else if (thread->event_info & RT_EVENT_FLAG_OR)//事件过滤方式为逻辑或
{
if (thread->event_set & event->set)//判断是否触发任一关心的事件
{
/* save recieved event set */
thread->event_set = thread->event_set & event->set;//将接收到的事件保存到线程中
/* received an OR event */
status = RT_EOK;
}
}
/* move node to the next */
n = n->next;//指向下一挂起的线程
/* condition is satisfied, resume thread */
if (status == RT_EOK)//符合唤醒条件
{
/* clear event */
if (thread->event_info & RT_EVENT_FLAG_CLEAR)//是否需要清除接收到的事件
event->set &= ~thread->event_set;//清除接收到的事件
/* resume thread, and thread list breaks out */
rt_thread_resume(thread);//唤醒此线程
/* need do a scheduling */
need_schedule = RT_TRUE;//设置需要重新调度标志
}
}
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
/* do a schedule */
if (need_schedule == RT_TRUE)
rt_schedule();//重新调试线程
return RT_EOK;
}
发送事件首先会将事件保存到事件控制内部,然后遍历事件控制块内所有因等待事件的接收线程,如果条件符合则唤醒它。