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

📄 kernel-mutexes.html

📁 有关ecos2。0介绍了实时嵌入式的结构以及线程调度的实现和内存的管理等
💻 HTML
📖 第 1 页 / 共 2 页
字号:
levels. However this may not always be possible even at theapplication level. In addition mutexes may be used internally byunderlying code, for example the memory allocation package, so carefulanalysis of the whole system would be needed to be sure that priorityinversion cannot occur. Instead it is common practice to use one oftwo techniques: priority ceilings and priority inheritance.      </P><P>Priority ceilings involve associating a priority with each mutex.Usually this will match the highest priority thread that will everlock the mutex. When a thread running at a lower priority makes asuccessful call to <TTCLASS="FUNCTION">cyg_mutex_lock</TT> or<TTCLASS="FUNCTION">cyg_mutex_trylock</TT> its priority will be boosted tothat of the mutex. For example, given the previous example thepriority associated with the mutex would be that of thread A, so foras long as it owns the mutex thread C will run in preference to threadB. When C releases the mutex its priority drops to the normal valueagain, allowing A to run and claim the mutex. Setting thepriority for a mutex involves a call to<TTCLASS="FUNCTION">cyg_mutex_set_ceiling</TT>, which is typically calledduring initialization. It is possible to change the ceilingdynamically but this will only affect subsequent lock operations, notthe current owner of the mutex.      </P><P>Priority ceilings are very suitable for simple applications, where forevery thread in the system it is possible to work out which mutexeswill be accessed. For more complicated applications this may provedifficult, especially if thread priorities change at run-time. Anadditional problem occurs for any mutexes outside the application, forexample used internally within eCos packages. A typical eCos packagewill be unaware of the details of the various threads in the system,so it will have no way of setting suitable ceilings for its internalmutexes. If those mutexes are not exported to application code then using priority ceilings may not be viable. The kernel does provide aconfiguration option<TTCLASS="VARNAME">CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY</TT>that can be used to set the default priority ceiling for all mutexes,which may prove sufficient.      </P><P>The alternative approach is to use priority inheritance: if a threadcalls <TTCLASS="FUNCTION">cyg_mutex_lock</TT> for a mutex that itcurrently owned by a lower-priority thread, then the owner will haveits priority raised to that of the current thread. Often this is moreefficient than priority ceilings because priority boosting onlyhappens when necessary, not for every lock operation, and the requiredpriority is determined at run-time rather than by static analysis.However there are complications when multiple threads running atdifferent priorities try to lock a single mutex, or when the currentowner of a mutex then tries to lock additional mutexes, and this makesthe implementation significantly more complicated than priorityceilings.       </P><P>There are a number of configuration options associated with priorityinversion. First, if after careful analysis it is known that priorityinversion cannot arise then the component<TTCLASS="FUNCTION">CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL</TT>can be disabled. More commonly this component will be enabled, and oneof either<TTCLASS="VARNAME">CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT</TT>or<TTCLASS="VARNAME">CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING</TT>will be selected, so that one of the two protocols is available forall mutexes. It is possible to select multiple protocols, so that somemutexes can have priority ceilings while others use priorityinheritance or no priority inversion protection at all. Obviously thisflexibility will add to the code size and to the cost of mutexoperations. The default for all mutexes will be controlled by<TTCLASS="VARNAME">CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT</TT>,and can be changed at run-time using<TTCLASS="FUNCTION">cyg_mutex_set_protocol</TT>.       </P><P>Priority inversion problems can also occur with other synchronizationprimitives such as semaphores. For example there could be a situationwhere a high-priority thread A is waiting on a semaphore, alow-priority thread C needs to do just a little bit more work beforeposting the semaphore, but a medium priority thread B is running andpreventing C from making progress. However a semaphore does not havethe concept of an owner, so there is no way for the system to knowthat it is thread C which would next post to the semaphore. Hencethere is no way for the system to boost the priority of Cautomatically and prevent the priority inversion. Instead situationslike this have to be detected by application developers andappropriate precautions have to be taken, for example making sure thatall the threads run at suitable priorities at all times.      </P><DIVCLASS="WARNING"><P></P><TABLECLASS="WARNING"BORDER="1"WIDTH="100%"><TR><TDALIGN="CENTER"><B>Warning</B></TD></TR><TR><TDALIGN="LEFT"><P>The current implementation of priority inheritance within the eCoskernel does not handle certain exceptional circumstances completelycorrectly. Problems will only arise if a thread owns one mutex,then attempts to claim another mutex, and there are other threadsattempting to lock these same mutexes. Although the system willcontinue running, the current owners of the various mutexes involvedmay not run at the priority they should. This situation never arisesin typical code because a mutex will only be locked for a smallcritical region, and there is no need to manipulate other shared resourcesinside this region. A more complicated implementation of priorityinheritance is possible but would add significant overhead and certainoperations would no longer be deterministic.      </P></TD></TR></TABLE></DIV><DIVCLASS="WARNING"><P></P><TABLECLASS="WARNING"BORDER="1"WIDTH="100%"><TR><TDALIGN="CENTER"><B>Warning</B></TD></TR><TR><TDALIGN="LEFT"><P>Support for priority ceilings and priority inheritance is notimplemented for all schedulers. In particular neither priorityceilings nor priority inheritance are currently available for thebitmap scheduler.      </P></TD></TR></TABLE></DIV></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-MUTEXES-ALTERNATIVES"></A><H2>Alternatives</H2><P>In nearly all circumstances, if two or more threads need to share somedata then protecting this data with a mutex is the correct thing todo. Mutexes are the only primitive that combine a locking mechanismand protection against priority inversion problems. However thisfunctionality is achieved at a cost, and in exceptional circumstancessuch as an application's most critical inner loop it may be desirableto use some other means of locking.      </P><P>When a critical region is very very small it is possible to lock thescheduler, thus ensuring that no other thread can run until thescheduler is unlocked again. This is achieved with calls to <AHREF="kernel-schedcontrol.html"><TTCLASS="FUNCTION">cyg_scheduler_lock</TT></A>and <TTCLASS="FUNCTION">cyg_scheduler_unlock</TT>. If the critical regionis sufficiently small then this can actually improve both performanceand dispatch latency because <TTCLASS="FUNCTION">cyg_mutex_lock</TT> alsolocks the scheduler for a brief period of time. This approach will notwork on SMP systems because another thread may already be running on adifferent processor and accessing the critical region.      </P><P>Another way of avoiding the use of mutexes is to make sure that allthreads that access a particular critical region run at the samepriority and configure the system with timeslicing disabled(<TTCLASS="VARNAME">CYGSEM_KERNEL_SCHED_TIMESLICE</TT>). Withouttimeslicing a thread can only be preempted by a higher-priority one,or if it performs some operation that can block. This approachrequires that none of the operations in the critical region can block,so for example it is not legal to call<TTCLASS="FUNCTION">cyg_semaphore_wait</TT>. It is also vulnerable toany changes in the configuration or to the various thread priorities:any such changes may now have unexpected side effects. It will notwork on SMP systems.      </P></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-MUTEXES-RECURSIVE"></A><H2>Recursive Mutexes</H2><P>The implementation of mutexes within the eCos kernel does not supportrecursive locks. If a thread has locked a mutex and then attempts tolock the mutex again, typically as a result of some recursive call ina complicated call graph, then either an assertion failure will bereported or the thread will deadlock. This behaviour is deliberate.When a thread has just locked a mutex associated with some datastructure, it can assume that that data structure is in a consistentstate. Before unlocking the mutex again it must ensure that the datastructure is again in a consistent state. Recursive mutexes allow athread to make arbitrary changes to a data structure, then in arecursive call lock the mutex again while the data structure is stillinconsistent. The net result is that code can no longer make anyassumptions about data structure consistency, which defeats thepurpose of using mutexes.      </P></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-MUTEXES-CONTEXT"></A><H2>Valid contexts</H2><P><TTCLASS="FUNCTION">cyg_mutex_init</TT>,<TTCLASS="FUNCTION">cyg_mutex_set_ceiling</TT> and<TTCLASS="FUNCTION">cyg_mutex_set_protocol</TT> are normally called duringinitialization but may also be called from thread context. Theremaining functions should only be called from thread context. Mutexesserve as a mutual exclusion mechanism between threads, and cannot beused to synchronize between threads and the interrupt handlingsubsystem. If a critical region is shared between a thread and a DSRthen it must be protected using <AHREF="kernel-schedcontrol.html"><TTCLASS="FUNCTION">cyg_scheduler_lock</TT></A>and <TTCLASS="FUNCTION">cyg_scheduler_unlock</TT>. If a critical region isshared between a thread and an ISR, it must be protected by disablingor masking interrupts. Obviously these operations must be used withcare because they can affect dispatch and interrupt latencies.      </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-alarms.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-condition-variables.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Alarms</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="kernel.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Condition Variables</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

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