RT-Thread内部机制 事件组

事件组

  • 队列:用来传递数据,大小不限。
  • 邮箱:用来传递数据,数据是一个长整型。
  • 信号量:表示资源数量。
  • 互斥量:实现互斥操作,跟信号量的主要区别在于实现了优先级继承。

上述每次唤醒只唤醒一个。

  • 事件组:等待“多个事件”。
    唤醒所有满足条件的线程。
    写事件唤醒线程之前先清除。

事件组结构体

struct rt_event
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */

    rt_uint32_t          set;                           //线程期待的事件集
};

struct rt_ipc_object
{
    struct rt_object parent;                            /**< inherit from rt_object */

    rt_list_t        suspend_thread;                    //等待事件集的线程链表
};

线程结构体多加了

#if defined(RT_USING_EVENT)
    /* thread event */
    rt_uint32_t event_set;
    rt_uint8_t  event_info;
#endif

等待事件集

/**
 * This function will receive an event from event object, if the event is
 * unavailable, the thread shall wait for a specified time.
 *
 * @param event the fast event object
 * @param set the interested event set
 * @param option the receive option, either RT_EVENT_FLAG_AND or
 *        RT_EVENT_FLAG_OR should be set.选择set所有事件或等待其中的一个,等待到后是否需要清除。
 * @param timeout the waiting time
 * @param recved the received event, if you don't care, RT_NULL can be set.
 *
 * @return the error code
 */
rt_err_t rt_event_recv(rt_event_t   event,
                       rt_uint32_t  set,
                       rt_uint8_t   option,
                       rt_int32_t   timeout,
                       rt_uint32_t *recved)
{
	level = rt_hw_interrupt_disable();
	if (option & RT_EVENT_FLAG_AND)
    {
        if ((event->set & set) == set)
            status = RT_EOK;
    }
    else if (option & RT_EVENT_FLAG_OR)
    {
        if (event->set & set)
            status = RT_EOK;
    }
    else
    {
        /* either RT_EVENT_FLAG_AND or RT_EVENT_FLAG_OR should be set */
        RT_ASSERT(0);
    }
    if (status == RT_EOK) //事件集已经满足条件
    {
        /* set received event */
        if (recved)
            *recved = (event->set & set); //给接收到的事件集赋值

        /* received event */
        if (option & RT_EVENT_FLAG_CLEAR) //立刻清除我已经获取成功的事件集
            event->set &= ~set;
    }
    else if (timeout == 0)
    {
        /* no waiting */
        thread->error = -RT_ETIMEOUT;
    }
    else
    {
        /* fill thread event info */
        thread->event_set  = set; //等待的事件集与选择赋值给线程
        thread->event_info = option;

        /* put thread to suspended thread list */
        rt_ipc_list_suspend(&(event->parent.suspend_thread),
                            thread,
                            event->parent.parent.flag);

        /* if there is a waiting timeout, active thread timer */
        if (timeout > 0)
        {
            /* 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(level);

        /* do a schedule */
        rt_schedule();

        if (thread->error != RT_EOK)
        {
            /* return error */
            return thread->error;
        }

        /* received an event, disable interrupt to protect */
        level = rt_hw_interrupt_disable();

        /* set received event */
        if (recved) 
            *recved = thread->event_set; //记录事件集,被唤醒后,没有清除操作。 
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent)));

    return thread->error;
}
}

清除事件留在发送事件时清除

rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
{
	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 the received 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;
            }
        }
    }

}

你可能感兴趣的:(RT-Thread,windows,网络,linux,RT-Thread)