Event source code analysis of the IPC Mechanism of rt-thread

Source: Internet
Author: User

1 Preface events are mainly used for synchronization between threads. Unlike semaphores, events are characterized by one-to-many and many-to-many synchronization. That is, one thread can wait for multiple events to trigger: either of them can trigger a wake-up thread to process the events; it can also be triggered after several events arrive to wake up the thread for subsequent processing. Similarly, an event can be synchronized by multiple threads. The collection of multiple events can be represented by a 32-bit unsigned integer variable. One of the variables represents an event, A thread establishes an association with one or more events through logic and or logic to form an event set. The "logical or" of an event is also called independent synchronization, which means that the thread synchronizes with any event. The "logical and" of an event is also called associated synchronization, it means that the thread is synchronized with several events. Events defined by RT-Thread have the following features: 1. events are only related to threads and are mutually independent. Each Thread defined by RT-Thread has 32 event signs, which are recorded with a 32-bit unsigned integer, each bit represents an event. Several events constitute an event set. 2. the event is only used for synchronization and does not provide the data transmission function. 3. the event is not queued, that is, the same event is sent to the thread multiple times (if the thread has not had time to read it), the effect is equivalent to sending only once. In the RT-Thread implementation, each Thread also has an event information tag (see the description of the Thread control block in Chapter 1 of the http://blog.csdn.net/flydream0/article/details/8584362), which has three attributes, RT_EVENT_FLAG_AND (logical and), RT_EVENT_FLAG_OR (logical or), and RT_EVENT_FLAG_CLEAR (clear mark ). When the thread waits for event synchronization, it can identify whether the currently received event meets the synchronization conditions by using 32 event signs and one event information mark. As shown in, the third and tenth bits in the event flag of thread 1 are set to logical and, it indicates that thread 1 will be triggered and awakened only when both event 3 and event 10 occur. If the event information flag bit is set to logical or, event 3 or any occurrence of event 10 triggers wake-up thread 1. If both the information flag and the clear flag are set, the event will cause the corresponding event flag of thread 1 to be reset to zero. 2. The control blocks of event control blocks are defined as follows: [cpp]/** event structure */struct rt_event {struct rt_ipc_object parent; /** <inherit from ipc_object * // derive rt_uint32_t set from the IPC object;/** <event set * // Save the received event set }; typedef struct rt_event * rt_event_t; it can be seen from the source code that the control block of the event is also derived from the IPC object. 3 interface implementation source code Analysis 3.1 initialization event [cpp]/*** 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); // Kernel Object of the initialization event/* set parent flag */event-> parent. parent. flag = flag; // set the flag of the kernel object/* init ipc object */rt_ipc_object_init (& (event-> parent )); // The IPC object of the initialization event/* init event */event-> set = 0; // The event set received by the initialization event is empty (each bit represents an event) return RT_EOK ;} 3.2 create an event [cpp]/*** This function will create an event object from E M 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; // make sure that this function is not in ISR/* allocate object */event = (rt_event_t) rt_object_allocate (RT_Object_Class_Event, name ); // The Kernel Object for dynamically allocating events if (event = RT_NULL) return event ;/* Set parent */event-> parent. parent. flag = flag; // set the kernel object flag of the event/* init ipc object */rt_ipc_object_init (& (event-> parent )); // The IPC object of the initialization event/* init event */event-> set = 0; // The event set received by the initialization event is empty return event ;} 3.3 escape event [cpp]/*** 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_de Tach (rt_event_t event) {/* parameter check */RT_ASSERT (event! = RT_NULL);/* resume all suincluded thread */rt_ipc_list_resume_all (& (event-> parent. suspend_thread); // wake up all threads suspended for this event/* detach event object */rt_object_detach (& (event-> parent. parent); // return RT_EOK from the event kernel object ;} 3.4 delete event [cpp]/*** 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; // ensure that this function is not used in ISR/* resume all suincluded thread */rt_ipc_list_resume_all (& (event-> parent. suspend_thread); // wake up all threads suspended for this event/* delete event object */rt_object_delete (& (event-> parent. parent); // Delete the event's kernel object return RT_EOK;} 3.5 send the event [cpp]/*** This function will send an event to the event object, if there are threads * suincluded on event object, it will be waked u P. ** @ 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) // if no event exists, return-RT_ERROR; need_schedule = RT_FALSE; // scheduling flag Initialization is not required RT_OBJECT_HOOK_CALL (rt_object_put_hook, (& (event-> parent. parent);/* disable interrupt */level = rt_hw_interrupt_disable (); // Guanzhong disconnection/* set event */event-> set | = set; // event receiving event set or event sent on, that is, save the received event if (! Rt_list_isempty (& event-> parent. suspend_thread) // If the linked list of suspended threads of the event is not empty {/* search thread list to resume thread */n = event-> parent. suspend_thread.next; // traverses all pending threads while (n! = & (Event-> parent. suspend_thread) {/* get thread */thread = rt_list_entry (n, struct rt_thread, tlist); // get the suspended thread control block status =-RT_ERROR; if (thread-> event_info & RT_EVENT_FLAG_AND) // if the suspended thread is in the event Filtering mode, the logic and {if (thread-> event_set & event-> set) = thread-> event_set) // determines whether all events are triggered. {/* fired an AND event */status = RT_EOK ;}} else if (thread-> event_info & RT_EVENT_FLAG_OR) // The Event Filtering Method is logical or {if (thread -> Event_set & event-> set) // determine whether to trigger any concerned event {/* save recieved event set */thread-> event_set = thread-> event_set & event-> set; // Save the received event to the thread/* received an OR event */status = RT_EOK ;}} /* move node to the next */n = n-> next; // point to the next suspended thread/* condition is satisfied, resume thread */if (status = RT_EOK) // meets the wake-up condition {/* clear event */if (thread-> event_info & RT_EVENT_FLAG_CLEAR) // whether to clear the received event-> Set & = ~ Thread-> event_set; // clear the received events/* resume thread, and thread list breaks out */rt_thread_resume (thread ); // wake up this thread/* need do a scheduling */need_schedule = RT_TRUE; // set the scheduling flag to be rescheduled}/* enable interrupt */rt_hw_interrupt_enable (level ); // enable/* do a schedule */if (need_schedule = RT_TRUE) rt_schedule (); // re-debug the thread return RT_EOK ;} when an event is sent, the event is saved to the event control, and all receiving threads waiting for the event in the event control block are traversed. If the conditions are met, the event is awakened. 3.6 receive event [cpp]/*** 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 * @ param timeout the waiting time * @ param recved the received event ** @ return the error code */rt_err_t rt_event_recv (rt_event_t event, Rt_uint32_t set, // alert option, // filtering mode rt_int32_t timeout, optional * recved) {struct rt_thread * thread; register rt_ubase_t level; register rt_base_t status; success; // make sure that this function does not use/* parameter check */RT_ASSERT (event! = RT_NULL); if (set = 0) // if not interested in any event, return-RT_ERROR;/* init status */status =-RT_ERROR; /* get current thread */thread = rt_thread_self (); // get the current thread/* reset thread error */thread-> error = RT_EOK; // reset the err code of the thread RT_OBJECT_HOOK_CALL (rt_object_trytake_hook, (& (event-> parent. parent);/* disable interrupt */level = rt_hw_interrupt_disable (); // Guanzhong disconnection/* check event set */if (option & RT_EVENT_F LAG_AND) // if the filter option is logical and {if (event-> set & set) = set) // determine whether all events of interest have been received. status = RT_EOK;} else if (option & RT_EVENT_FLAG_OR) // if the filtering option is logical or {if (event-> set & set) // determines whether to receive any event of interest status = RT_EOK ;} if (status = RT_EOK) // if the event is successfully received {/* set already ed event */* recved = (event-> set & set ); // Save the received event set to the space pointed to by recved/* sorted ed event */if (option & RT_EVENT_FLAG_CLEAR) // clear the received event set event-> set & = ~ Set;} else if (timeout = 0) // if no event is received and the wait parameter is 0, then immediately return the error {/* no waiting */thread-> error =-RT_ETIMEOUT;} else // if no event is received and the waiting parameter is not 0, the current thread {/* fill thread event info */thread-> event_set = set; thread-> event_info = option; /* put thread to suincluded thread list */rt_ipc_list_suspend (& (event-> parent. suspend_thread), // suspends the current 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 ), // set the timer parameter RT_TIMER_CTRL_SET_TIME, & timeout); rt_timer_start (& (thread-> thread_timer); // start the timer}/* enable interrupt */rt_hw_interrupt_enable (level ); // enable/* do a schedule */rt_schedule (); // start rescheduling, and the current thread will actually suspend if (thread-> error! = RT_EOK) // only two possibilities can be run to this end: 1. The timer times out and the current thread does not wait until the event arrives, the timeout callback handler of the timer sets the thread error to-RT_ETIMOUT; 2: The Event arrives, and the current thread is awakened, at this time, the error of the thread remains unchanged {/* return error */return thread-> error; // The error code}/* received an event is returned if the event does not arrive, disable interrupt to protect */level = rt_hw_interrupt_disable (); // when the event arrives/* set already ed event */* recved = thread-> event_set; // Save the received event set to the memory pointed to by recved}/* enable interrupt */ Rt_hw_interrupt_enable (level); // enable or disable RT_OBJECT_HOOK_CALL (rt_object_take_hook, (& (event-> parent. parent); return thread-> error;} The receiving thread is relatively simple. If an event is received, it determines whether it is an event of interest to it. If yes, the event is saved, if not, it is processed together when no event is received. The next step is when no event arrives, or the old rule. First, judge whether the time parameter is 0. If yes, the system returns timeout. If not, set a timer and start it, then re-schedule the thread and determine whether a new and qualified event has arrived based on whether the error value of the current thread is RT_EOK. If not, the error code is returned. If yes, save the event and Return OK.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.