设为首页 加入收藏

TOP

IPC机制之事件源码分析(二)
2013-07-23 09:04:19 来源: 作者: 【 】 浏览:300
Tags:IPC 机制 事件 源码 分析

 

  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;

  }

  发送事件首先会将事件保存到事件控制内部,然后遍历事件控制块内所有因等待事件的接收线程,如果条件符合则唤醒它。

        

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++大整数排序 下一篇强转是+0.01的习惯

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: