<p>Waking up a thread after an hardware event is one of the most common tasks that an RTOS must be able to perform efficiently. In ChibiOS/RT there are several mechanisms that can be used, often each mechanism is best suited in a specific scenario.</p>
<h2>Synchronously waking up a specific thread</h2>
<p>A common situation is to have to synchronously wake up a specific thread. This can be accomplished without the use of any specific synchronization primitive, it uses the very efficient low level scheduler APIs, note that you can also optionally send a simple message from the IRQ handler to the thread. </p>
<divclass="fragment"><preclass="fragment"><spanclass="keyword">static</span><aclass="code"href="struct_thread.html"title="Structure representing a thread.">Thread</a> *tp = NULL;
<aclass="code"href="group__types.html#ga35bcb0c321cd7bc45bf1a11fa17ebdd3"title="Message, use signed pointer equivalent.">msg_t</a> msg;
<spanclass="comment">// Waiting for the IRQ to happen.</span>
<aclass="code"href="group__system.html#ga9f6573c0763d1e4e97c63c62edad6e42"title="Enters the kernel lock mode.">chSysLock</a>();
tp = <aclass="code"href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5"title="Returns a pointer to the current Thread.">chThdSelf</a>();
<aclass="code"href="group__scheduler.html#ga97c1c514b755a1e71caf2f19c1ccf986"title="Puts the current thread to sleep into the specified state.">chSchGoSleepS</a>(PRSUSPENDED);
msg = <aclass="code"href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5"title="Returns a pointer to the current Thread.">chThdSelf</a>()->p_rdymsg; <spanclass="comment">// Retrieving the message, optional</span>
<aclass="code"href="group__system.html#ga5a257fa58a09815eb64a45e2dfbdc22e"title="Leaves the kernel lock mode.">chSysUnlock</a>();
<aclass="code"href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9"title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<aclass="code"href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494"title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<spanclass="comment">// Wakes up the thread.</span>
<aclass="code"href="group__system.html#gab826c6d946aa1eb839751246ea158a72"title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<aclass="code"href="group__scheduler.html#ga535d58cfb3436c8d4e4586c31c062298"title="Inserts a thread in the Ready List.">chSchReadyI</a>(tp);
tp = NULL;
}
<aclass="code"href="group__system.html#ga984fb4af1420b6a217714ed317224ec0"title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
</pre></div><h2>Synchronously waking up one of the waiting threads</h2>
<p>Lets assume you have a queue of waiting threads, you want to wake up the threads one by one in FIFO order, if there are no waiting threads then nothing happens.<br/>
This can be accomplished using a <code><aclass="el"href="struct_semaphore.html"title="Semaphore structure.">Semaphore</a></code> object initialized to zero: </p>
<divclass="fragment"><preclass="fragment"><aclass="code"href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9"title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<aclass="code"href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494"title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<spanclass="comment">// If there is at least one waiting thread then signal it.</span>
<aclass="code"href="group__system.html#gab826c6d946aa1eb839751246ea158a72"title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<spanclass="keywordflow">if</span> (<aclass="code"href="group__semaphores.html#gadab3ccf8a34988ef6d410354b2648327"title="Returns the semaphore counter current value.">chSemGetCounterI</a>(&mysem) < 0)
<aclass="code"href="group__semaphores.html#gaca0b70cf495a9cb7569e1cf5b07e2b3d"title="Performs a signal operation on a semaphore.">chSemSignalI</a>(&mysem);
<aclass="code"href="group__system.html#ga984fb4af1420b6a217714ed317224ec0"title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
</pre></div><h2>Synchronously waking up all the waiting threads</h2>
<p>In this scenario you want to synchronously wake up all the waiting threads, if there are no waiting threads then nothing happens.<br/>
This can be accomplished using a <code><aclass="el"href="struct_semaphore.html"title="Semaphore structure.">Semaphore</a></code> object initialized to zero: </p>
<divclass="fragment"><preclass="fragment"><aclass="code"href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9"title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<aclass="code"href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494"title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<spanclass="comment">// Wakes up all the threads waiting on the semaphore.</span>
<aclass="code"href="group__system.html#gab826c6d946aa1eb839751246ea158a72"title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<aclass="code"href="group__semaphores.html#gae7972b6b22b80ac09bac5a186277ab81"title="Performs a reset operation on the semaphore.">chSemResetI</a>(&mysem);
<aclass="code"href="group__system.html#ga984fb4af1420b6a217714ed317224ec0"title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
</pre></div><h2>Asynchronously waking up a specific thread</h2>
<p>If you have to asynchronously wake up a specific thread then a simple event flags can be used. </p>
<divclass="fragment"><preclass="fragment"><spanclass="keyword">static</span><aclass="code"href="struct_thread.html"title="Structure representing a thread.">Thread</a> *tp;
tp = <aclass="code"href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5"title="Returns a pointer to the current Thread.">chThdSelf</a>();
<spanclass="keywordflow">while</span> (TRUE) {
<spanclass="comment">// Checks if an IRQ happened else wait.</span>
<aclass="code"href="group__events.html#gabd731d3ed2f037b2409e370676575f8d"title="Waits for any of the specified events.">chEvtWaitAny</a>((<aclass="code"href="group__types.html#gabff0c32475baf20ea8c5c710d6e8b708"title="Event Mask, recommended fastest unsigned.">eventmask_t</a>)1);
<aclass="code"href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9"title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<aclass="code"href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494"title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<spanclass="comment">// Wakes up the thread.</span>
<aclass="code"href="group__system.html#gab826c6d946aa1eb839751246ea158a72"title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<aclass="code"href="group__events.html#ga6c219038c3e618e2142c6e1601997907"title="Pends a set of event flags on the specified Thread.">chEvtSignalI</a>(tp, (<aclass="code"href="group__types.html#gabff0c32475baf20ea8c5c710d6e8b708"title="Event Mask, recommended fastest unsigned.">eventmask_t</a>)1);
<aclass="code"href="group__system.html#ga984fb4af1420b6a217714ed317224ec0"title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
</pre></div><h2>Asynchronously waking up one or more threads</h2>
<p>By using event sources it is possible to asynchronously wake up one or more listener threads. The mechanism requires a single initialized <code><aclass="el"href="struct_event_source.html"title="Event Source structure.">EventSource</a></code> object, all the threads registered as listeners on the event source will be broadcasted. </p>
<divclass="fragment"><preclass="fragment"><aclass="code"href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9"title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<aclass="code"href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494"title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<spanclass="comment">// Pends an event flag on all the listening threads.</span>
<aclass="code"href="group__system.html#gab826c6d946aa1eb839751246ea158a72"title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<aclass="code"href="group__events.html#gaa24d9bed5b676b577200c4a8ebe3b8a3"title="Signals all the Event Listeners registered on the specified Event Source.">chEvtBroadcastI</a>(&my_event_source);
<aclass="code"href="group__system.html#ga984fb4af1420b6a217714ed317224ec0"title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
Generated on Sun Oct 24 2010 09:40:45 for ChibiOS/RT by <ahref="http://www.doxygen.org/index.html"><imgsrc="doxygen.png"alt="doxygen"align="middle"border="0"></a> 1.7.1</small></address>