⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel-condition-variables.html

📁 有关ecos2。0介绍了实时嵌入式的结构以及线程调度的实现和内存的管理等
💻 HTML
字号:
<!-- Copyright (C) 2003 Red Hat, Inc.                                --><!-- This material may be distributed only subject to the terms      --><!-- and conditions set forth in the Open Publication License, v1.0  --><!-- or later (the latest version is presently available at          --><!-- http://www.opencontent.org/openpub/).                           --><!-- Distribution of the work or derivative of the work in any       --><!-- standard (paper) book form is prohibited unless prior           --><!-- permission is obtained from the copyright holder.               --><HTML><HEAD><TITLE>Condition Variables</TITLE><meta name="MSSmartTagsPreventParsing" content="TRUE"><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="eCos Reference Manual"HREF="ecos-ref.html"><LINKREL="UP"TITLE="The eCos Kernel"HREF="kernel.html"><LINKREL="PREVIOUS"TITLE="Mutexes"HREF="kernel-mutexes.html"><LINKREL="NEXT"TITLE="Semaphores"HREF="kernel-semaphores.html"></HEAD><BODYCLASS="REFENTRY"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">eCos Reference Manual</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="kernel-mutexes.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="kernel-semaphores.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><H1><ANAME="KERNEL-CONDITION-VARIABLES">Condition Variables</H1><DIVCLASS="REFNAMEDIV"><ANAME="AEN1232"></A><H2>Name</H2>cyg_cond_init, cyg_cond_destroy, cyg_cond_wait, cyg_cond_timed_wait, cyg_cond_signal, cyg_cond_broadcast&nbsp;--&nbsp;Synchronization primitive</DIV><DIVCLASS="REFSYNOPSISDIV"><ANAME="AEN1240"><H2>Synopsis</H2><DIVCLASS="FUNCSYNOPSIS"><ANAME="AEN1241"><P></P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="FUNCSYNOPSISINFO">#include &lt;cyg/kernel/kapi.h&gt;        </PRE></TD></TR></TABLE><P><CODE><CODECLASS="FUNCDEF">void cyg_cond_init</CODE>(cyg_cond_t* cond, cyg_mutex_t* mutex);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_cond_destroy</CODE>(cyg_cond_t* cond);</CODE></P><P><CODE><CODECLASS="FUNCDEF">cyg_bool_t cyg_cond_wait</CODE>(cyg_cond_t* cond);</CODE></P><P><CODE><CODECLASS="FUNCDEF">cyg_bool_t cyg_cond_timed_wait</CODE>(cyg_cond_t* cond, cyg_tick_count_t abstime);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_cond_signal</CODE>(cyg_cond_t* cond);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_cond_broadcast</CODE>(cyg_cond_t* cond);</CODE></P><P></P></DIV></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-CONDITION-VARIABLES-DESCRIPTION"></A><H2>Description</H2><P>Condition variables are used in conjunction with mutexes to implementlong-term waits for some condition to become true. For exampleconsider a set of functions that control access to a pool ofresources:      </P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">&#13;cyg_mutex_t res_lock;res_t res_pool[RES_MAX];int res_count = RES_MAX;void res_init(void){    cyg_mutex_init(&amp;res_lock);    &lt;fill pool with resources&gt;}res_t res_allocate(void){    res_t res;    cyg_mutex_lock(&amp;res_lock);               // lock the mutex    if( res_count == 0 )                     // check for free resource        res = RES_NONE;                      // return RES_NONE if none    else    {        res_count--;                         // allocate a resources        res = res_pool[res_count];    }    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex    return res;}void res_free(res_t res){    cyg_mutex_lock(&amp;res_lock);               // lock the mutex    res_pool[res_count] = res;               // free the resource    res_count++;    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex}      </PRE></TD></TR></TABLE><P>These routines use the variable <TTCLASS="VARNAME">res_count</TT> to keeptrack of the resources available. If there are none then<TTCLASS="FUNCTION">res_allocate</TT> returns <TTCLASS="LITERAL">RES_NONE</TT>,which the caller must check for and take appropriate error handlingactions.      </P><P>Now suppose that we do not want to return<TTCLASS="LITERAL">RES_NONE</TT> when there are no resources, but want towait for one to become available. This is where a condition variablecan be used:      </P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">&#13;cyg_mutex_t res_lock;cyg_cond_t res_wait;res_t res_pool[RES_MAX];int res_count = RES_MAX;void res_init(void){    cyg_mutex_init(&amp;res_lock);    cyg_cond_init(&amp;res_wait, &amp;res_lock);    &lt;fill pool with resources&gt;}res_t res_allocate(void){    res_t res;    cyg_mutex_lock(&amp;res_lock);               // lock the mutex    while( res_count == 0 )                  // wait for a resources        cyg_cond_wait(&amp;res_wait);    res_count--;                             // allocate a resource    res = res_pool[res_count];    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex    return res;}void res_free(res_t res){    cyg_mutex_lock(&amp;res_lock);               // lock the mutex    res_pool[res_count] = res;               // free the resource    res_count++;    cyg_cond_signal(&amp;res_wait);              // wake up any waiting allocators    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex}      </PRE></TD></TR></TABLE><P>In this version of the code, when <TTCLASS="FUNCTION">res_allocate</TT>detects that there are no resources it calls<TTCLASS="FUNCTION">cyg_cond_wait</TT>. This does two things: it unlocksthe mutex, and puts the calling thread to sleep on the conditionvariable. When <TTCLASS="FUNCTION">res_free</TT> is eventually called, itputs a resource back into the pool and calls<TTCLASS="FUNCTION">cyg_cond_signal</TT> to wake up any thread waiting onthe condition variable. When the waiting thread eventually gets to run again,it will re-lock the mutex before returning from<TTCLASS="FUNCTION">cyg_cond_wait</TT>.      </P><P>There are two important things to note about the way in which thiscode works. The first is that the mutex unlock and wait in<TTCLASS="FUNCTION">cyg_cond_wait</TT> are atomic: no other thread can runbetween the unlock and the wait. If this were not the case then a callto <TTCLASS="FUNCTION">res_free</TT> by that thread would release theresource but the call to <TTCLASS="FUNCTION">cyg_cond_signal</TT> would belost, and the first thread would end up waiting when there wereresources available.      </P><P>The second feature is that the call to<TTCLASS="FUNCTION">cyg_cond_wait</TT> is in a <TTCLASS="LITERAL">while</TT>loop and not a simple <TTCLASS="LITERAL">if</TT> statement. This is becauseof the need to re-lock the mutex in <TTCLASS="FUNCTION">cyg_cond_wait</TT>when the signalled thread reawakens. If there are other threadsalready queued to claim the lock then this thread must wait. Dependingon the scheduler and the queue order, many other threads may haveentered the critical section before this one gets to run. So thecondition that it was waiting for may have been rendered false. Usinga loop around all condition variable wait operations is the only wayto guarantee that the condition being waited for is still true afterwaiting.      </P><P>Before a condition variable can be used it must be initialized with acall to <TTCLASS="FUNCTION">cyg_cond_init</TT>. This requires twoarguments, memory for the data structure and a pointer to an existingmutex. This mutex will not be initialized by<TTCLASS="FUNCTION">cyg_cond_init</TT>, instead a separate call to<TTCLASS="FUNCTION">cyg_mutex_init</TT> is required. If a conditionvariable is no longer required and there are no threads waiting on itthen <TTCLASS="FUNCTION">cyg_cond_destroy</TT> can be used.      </P><P>When a thread needs to wait for a condition to be satisfied it cancall <TTCLASS="FUNCTION">cyg_cond_wait</TT>. The thread must have alreadylocked the mutex that was specified in the<TTCLASS="FUNCTION">cyg_cond_init</TT> call. This mutex will be unlockedand the current thread will be suspended in an atomic operation. Whensome other thread performs a signal or broadcast operation the currentthread will be woken up and automatically reclaim ownership of the mutexagain, allowing it to examine global state and determine whether ornot the condition is now satisfied. The kernel supplies a variant ofthis function, <TTCLASS="FUNCTION">cyg_cond_timed_wait</TT>, which can beused to wait on the condition variable or until some number of clockticks have occurred. The mutex will always be reclaimed before<TTCLASS="FUNCTION">cyg_cond_timed_wait</TT> returns, regardless ofwhether it was a result of a signal operation or a timeout.      </P><P>There is no <TTCLASS="FUNCTION">cyg_cond_trywait</TT> function becausethis would not serve any purpose. If a thread has locked the mutex anddetermined that the condition is satisfied, it can just release themutex and return. There is no need to perform any operation on thecondition variable.      </P><P>When a thread changes shared state that may affect some other threadblocked on a condition variable, it should call either<TTCLASS="FUNCTION">cyg_cond_signal</TT> or<TTCLASS="FUNCTION">cyg_cond_broadcast</TT>. These calls do not requireownership of the mutex, but usually the mutex will have been claimedbefore updating the shared state. A signal operation only wakes up thefirst thread that is waiting on the condition variable, while abroadcast wakes up all the threads. If there are no threads waiting onthe condition variable at the time, then the signal or broadcast willhave no effect: past signals are not counted up or remembered in anyway. Typically a signal should be used when all threads will check thesame condition and at most one thread can continue running. Abroadcast should be used if threads check slightly differentconditions, or if the change to the global state might allow multiplethreads to proceed.      </P></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-CONDITION-VARIABLES-CONTEXT"></A><H2>Valid contexts</H2><P><TTCLASS="FUNCTION">cyg_cond_init</TT> is typically called during systeminitialization but may also be called in thread context. The sameapplies to <TTCLASS="FUNCTION">cyg_cond_delete</TT>.<TTCLASS="FUNCTION">cyg_cond_wait</TT> and<TTCLASS="FUNCTION">cyg_cond_timedwait</TT> may only be called from threadcontext since they may block. <TTCLASS="FUNCTION">cyg_cond_signal</TT> and<TTCLASS="FUNCTION">cyg_cond_broadcast</TT> may be called from thread orDSR context.      </P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="kernel-mutexes.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="ecos-ref.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="kernel-semaphores.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Mutexes</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="kernel.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Semaphores</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -