]> git.karo-electronics.de Git - karo-tx-redboot.git/blobdiff - doc/html/ref/kernel-mutexes.html
Cleanup CVS ipmorted branch
[karo-tx-redboot.git] / doc / html / ref / kernel-mutexes.html
diff --git a/doc/html/ref/kernel-mutexes.html b/doc/html/ref/kernel-mutexes.html
deleted file mode 100644 (file)
index c5f3318..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-<!-- 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
->Mutexes</TITLE
-><meta name="MSSmartTagsPreventParsing" content="TRUE">
-<META
-NAME="GENERATOR"
-CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
-"><LINK
-REL="HOME"
-TITLE="eCos Reference Manual"
-HREF="ecos-ref.html"><LINK
-REL="UP"
-TITLE="The eCos Kernel"
-HREF="kernel.html"><LINK
-REL="PREVIOUS"
-TITLE="Alarms"
-HREF="kernel-alarms.html"><LINK
-REL="NEXT"
-TITLE="Condition Variables"
-HREF="kernel-condition-variables.html"></HEAD
-><BODY
-CLASS="REFENTRY"
-BGCOLOR="#FFFFFF"
-TEXT="#000000"
-LINK="#0000FF"
-VLINK="#840084"
-ALINK="#0000FF"
-><DIV
-CLASS="NAVHEADER"
-><TABLE
-SUMMARY="Header navigation table"
-WIDTH="100%"
-BORDER="0"
-CELLPADDING="0"
-CELLSPACING="0"
-><TR
-><TH
-COLSPAN="3"
-ALIGN="center"
->eCos Reference Manual</TH
-></TR
-><TR
-><TD
-WIDTH="10%"
-ALIGN="left"
-VALIGN="bottom"
-><A
-HREF="kernel-alarms.html"
-ACCESSKEY="P"
->Prev</A
-></TD
-><TD
-WIDTH="80%"
-ALIGN="center"
-VALIGN="bottom"
-></TD
-><TD
-WIDTH="10%"
-ALIGN="right"
-VALIGN="bottom"
-><A
-HREF="kernel-condition-variables.html"
-ACCESSKEY="N"
->Next</A
-></TD
-></TR
-></TABLE
-><HR
-ALIGN="LEFT"
-WIDTH="100%"></DIV
-><H1
-><A
-NAME="KERNEL-MUTEXES">Mutexes</H1
-><DIV
-CLASS="REFNAMEDIV"
-><A
-NAME="AEN1098"
-></A
-><H2
->Name</H2
->cyg_mutex_init, cyg_mutex_destroy, cyg_mutex_lock, cyg_mutex_trylock, cyg_mutex_unlock, cyg_mutex_release, cyg_mutex_set_ceiling, cyg_mutex_set_protocol&nbsp;--&nbsp;Synchronization primitive</DIV
-><DIV
-CLASS="REFSYNOPSISDIV"
-><A
-NAME="AEN1108"><H2
->Synopsis</H2
-><DIV
-CLASS="FUNCSYNOPSIS"
-><A
-NAME="AEN1109"><P
-></P
-><TABLE
-BORDER="5"
-BGCOLOR="#E0E0F0"
-WIDTH="70%"
-><TR
-><TD
-><PRE
-CLASS="FUNCSYNOPSISINFO"
->#include &lt;cyg/kernel/kapi.h&gt;
-        </PRE
-></TD
-></TR
-></TABLE
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_init</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_destroy</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->cyg_bool_t cyg_mutex_lock</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->cyg_bool_t cyg_mutex_trylock</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_unlock</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_release</CODE
->(cyg_mutex_t* mutex);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_set_ceiling</CODE
->(cyg_mutex_t* mutex, cyg_priority_t priority);</CODE
-></P
-><P
-><CODE
-><CODE
-CLASS="FUNCDEF"
->void cyg_mutex_set_protocol</CODE
->(cyg_mutex_t* mutex, enum cyg_mutex_protocol protocol/);</CODE
-></P
-><P
-></P
-></DIV
-></DIV
-><DIV
-CLASS="REFSECT1"
-><A
-NAME="KERNEL-MUTEXES-DESCRIPTION"
-></A
-><H2
->Description</H2
-><P
->The purpose of mutexes is to let threads share resources safely. If
-two or more threads attempt to manipulate a data structure with no
-locking between them then the system may run for quite some time
-without apparent problems, but sooner or later the data structure will
-become inconsistent and the application will start behaving strangely
-and is quite likely to crash. The same can apply even when
-manipulating a single variable or some other resource. For example,
-consider:
-      </P
-><TABLE
-BORDER="5"
-BGCOLOR="#E0E0F0"
-WIDTH="70%"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->static volatile int counter = 0;
-
-void
-process_event(void)
-{
-    &#8230;
-
-    counter++;
-}</PRE
-></TD
-></TR
-></TABLE
-><P
->Assume that after a certain period of time <TT
-CLASS="VARNAME"
->counter</TT
->
-has a value of 42, and two threads A and B running at the same
-priority call <TT
-CLASS="FUNCTION"
->process_event</TT
->. Typically thread A
-will read the value of <TT
-CLASS="VARNAME"
->counter</TT
-> into a register,
-increment this register to 43, and write this updated value back to
-memory. Thread B will do the same, so usually
-<TT
-CLASS="VARNAME"
->counter</TT
-> will end up with a value of 44. However if
-thread A is timesliced after reading the old value 42 but before
-writing back 43, thread B will still read back the old value and will
-also write back 43. The net result is that the counter only gets
-incremented once, not twice, which depending on the application may
-prove disastrous.
-      </P
-><P
->Sections of code like the above which involve manipulating shared data
-are generally known as critical regions. Code should claim a lock
-before entering a critical region and release the lock when leaving.
-Mutexes provide an appropriate synchronization primitive for this.
-      </P
-><TABLE
-BORDER="5"
-BGCOLOR="#E0E0F0"
-WIDTH="70%"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->static volatile int counter = 0;
-static cyg_mutex_t  lock;
-
-void
-process_event(void)
-{
-    &#8230;
-
-    cyg_mutex_lock(&amp;lock);
-    counter++;
-    cyg_mutex_unlock(&amp;lock);
-}
-      </PRE
-></TD
-></TR
-></TABLE
-><P
->A mutex must be initialized before it can be used, by calling
-<TT
-CLASS="FUNCTION"
->cyg_mutex_init</TT
->. This takes a pointer to a
-<SPAN
-CLASS="STRUCTNAME"
->cyg_mutex_t</SPAN
-> data structure which is typically
-statically allocated, and may be part of a larger data structure. If a
-mutex is no longer required and there are no threads waiting on it
-then <TT
-CLASS="FUNCTION"
->cyg_mutex_destroy</TT
-> can be used.
-      </P
-><P
->The main functions for using a mutex are
-<TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> and
-<TT
-CLASS="FUNCTION"
->cyg_mutex_unlock</TT
->. In normal operation
-<TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> will return success after claiming
-the mutex lock, blocking if another thread currently owns the mutex.
-However the lock operation may fail if other code calls
-<TT
-CLASS="FUNCTION"
->cyg_mutex_release</TT
-> or
-<TT
-CLASS="FUNCTION"
->cyg_thread_release</TT
->, so if these functions may get
-used then it is important to check the return value. The current owner
-of a mutex should call <TT
-CLASS="FUNCTION"
->cyg_mutex_unlock</TT
-> when a
-lock is no longer required. This operation must be performed by the
-owner, not by another thread.
-      </P
-><P
-><TT
-CLASS="FUNCTION"
->cyg_mutex_trylock</TT
-> is a variant of
-<TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> that will always return
-immediately, returning success or failure as appropriate. This
-function is rarely useful. Typical code locks a mutex just before
-entering a critical region, so if the lock cannot be claimed then
-there may be nothing else for the current thread to do. Use of this
-function may also cause a form of priority inversion if the owner
-owner runs at a lower priority, because the priority inheritance code
-will not be triggered. Instead the current thread continues running,
-preventing the owner from getting any cpu time, completing the
-critical region, and releasing the mutex.
-      </P
-><P
-><TT
-CLASS="FUNCTION"
->cyg_mutex_release</TT
-> can be used to wake up all
-threads that are currently blocked inside a call to
-<TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> for a specific mutex. These lock
-calls will return failure. The current mutex owner is not affected.
-      </P
-></DIV
-><DIV
-CLASS="REFSECT1"
-><A
-NAME="KERNEL-MUTEXES-PRIORITY-INVERSION"
-></A
-><H2
->Priority Inversion</H2
-><P
->The use of mutexes gives rise to a problem known as priority
-inversion. In a typical scenario this requires three threads A, B, and
-C, running at high, medium and low priority respectively. Thread A and
-thread B are temporarily blocked waiting for some event, so thread C
-gets a chance to run, needs to enter a critical region, and locks
-a mutex. At this point threads A and B are woken up - the exact order
-does not matter. Thread A needs to claim the same mutex but has to
-wait until C has left the critical region and can release the mutex.
-Meanwhile thread B works on something completely different and can
-continue running without problems. Because thread C is running a lower
-priority than B it will not get a chance to run until B blocks for
-some reason, and hence thread A cannot run either. The overall effect
-is that a high-priority thread A cannot proceed because of a lower
-priority thread B, and priority inversion has occurred.
-      </P
-><P
->In simple applications it may be possible to arrange the code such
-that priority inversion cannot occur, for example by ensuring that a
-given mutex is never shared by threads running at different priority
-levels. However this may not always be possible even at the
-application level. In addition mutexes may be used internally by
-underlying code, for example the memory allocation package, so careful
-analysis of the whole system would be needed to be sure that priority
-inversion cannot occur. Instead it is common practice to use one of
-two 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 ever
-lock the mutex. When a thread running at a lower priority makes a
-successful call to <TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> or
-<TT
-CLASS="FUNCTION"
->cyg_mutex_trylock</TT
-> its priority will be boosted to
-that of the mutex. For example, given the previous example the
-priority associated with the mutex would be that of thread A, so for
-as long as it owns the mutex thread C will run in preference to thread
-B. When C releases the mutex its priority drops to the normal value
-again, allowing A to run and claim the mutex. Setting the
-priority for a mutex involves a call to
-<TT
-CLASS="FUNCTION"
->cyg_mutex_set_ceiling</TT
->, which is typically called
-during initialization. It is possible to change the ceiling
-dynamically but this will only affect subsequent lock operations, not
-the current owner of the mutex.
-      </P
-><P
->Priority ceilings are very suitable for simple applications, where for
-every thread in the system it is possible to work out which mutexes
-will be accessed. For more complicated applications this may prove
-difficult, especially if thread priorities change at run-time. An
-additional problem occurs for any mutexes outside the application, for
-example used internally within eCos packages. A typical eCos package
-will be unaware of the details of the various threads in the system,
-so it will have no way of setting suitable ceilings for its internal
-mutexes. If those mutexes are not exported to application code then 
-using priority ceilings may not be viable. The kernel does provide a
-configuration option
-<TT
-CLASS="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 thread
-calls <TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> for a mutex that it
-currently owned by a lower-priority thread, then the owner will have
-its priority raised to that of the current thread. Often this is more
-efficient than priority ceilings because priority boosting only
-happens when necessary, not for every lock operation, and the required
-priority is determined at run-time rather than by static analysis.
-However there are complications when multiple threads running at
-different priorities try to lock a single mutex, or when the current
-owner of a mutex then tries to lock additional mutexes, and this makes
-the implementation significantly more complicated than priority
-ceilings. 
-      </P
-><P
->There are a number of configuration options associated with priority
-inversion. First, if after careful analysis it is known that priority
-inversion cannot arise then the component
-<TT
-CLASS="FUNCTION"
->CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL</TT
->
-can be disabled. More commonly this component will be enabled, and one
-of either
-<TT
-CLASS="VARNAME"
->CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT</TT
->
-or
-<TT
-CLASS="VARNAME"
->CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING</TT
->
-will be selected, so that one of the two protocols is available for
-all mutexes. It is possible to select multiple protocols, so that some
-mutexes can have priority ceilings while others use priority
-inheritance or no priority inversion protection at all. Obviously this
-flexibility will add to the code size and to the cost of mutex
-operations. The default for all mutexes will be controlled by
-<TT
-CLASS="VARNAME"
->CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT</TT
->,
-and can be changed at run-time using
-<TT
-CLASS="FUNCTION"
->cyg_mutex_set_protocol</TT
->. 
-      </P
-><P
->Priority inversion problems can also occur with other synchronization
-primitives such as semaphores. For example there could be a situation
-where a high-priority thread A is waiting on a semaphore, a
-low-priority thread C needs to do just a little bit more work before
-posting the semaphore, but a medium priority thread B is running and
-preventing C from making progress. However a semaphore does not have
-the concept of an owner, so there is no way for the system to know
-that it is thread C which would next post to the semaphore. Hence
-there is no way for the system to boost the priority of C
-automatically and prevent the priority inversion. Instead situations
-like this have to be detected by application developers and
-appropriate precautions have to be taken, for example making sure that
-all the threads run at suitable priorities at all times.
-      </P
-><DIV
-CLASS="WARNING"
-><P
-></P
-><TABLE
-CLASS="WARNING"
-BORDER="1"
-WIDTH="100%"
-><TR
-><TD
-ALIGN="CENTER"
-><B
->Warning</B
-></TD
-></TR
-><TR
-><TD
-ALIGN="LEFT"
-><P
->The current implementation of priority inheritance within the eCos
-kernel does not handle certain exceptional circumstances completely
-correctly. Problems will only arise if a thread owns one mutex,
-then attempts to claim another mutex, and there are other threads
-attempting to lock these same mutexes. Although the system will
-continue running, the current owners of the various mutexes involved
-may not run at the priority they should. This situation never arises
-in typical code because a mutex will only be locked for a small
-critical region, and there is no need to manipulate other shared resources
-inside this region. A more complicated implementation of priority
-inheritance is possible but would add significant overhead and certain
-operations would no longer be deterministic.
-      </P
-></TD
-></TR
-></TABLE
-></DIV
-><DIV
-CLASS="WARNING"
-><P
-></P
-><TABLE
-CLASS="WARNING"
-BORDER="1"
-WIDTH="100%"
-><TR
-><TD
-ALIGN="CENTER"
-><B
->Warning</B
-></TD
-></TR
-><TR
-><TD
-ALIGN="LEFT"
-><P
->Support for priority ceilings and priority inheritance is not
-implemented for all schedulers. In particular neither priority
-ceilings nor priority inheritance are currently available for the
-bitmap scheduler.
-      </P
-></TD
-></TR
-></TABLE
-></DIV
-></DIV
-><DIV
-CLASS="REFSECT1"
-><A
-NAME="KERNEL-MUTEXES-ALTERNATIVES"
-></A
-><H2
->Alternatives</H2
-><P
->In nearly all circumstances, if two or more threads need to share some
-data then protecting this data with a mutex is the correct thing to
-do. Mutexes are the only primitive that combine a locking mechanism
-and protection against priority inversion problems. However this
-functionality is achieved at a cost, and in exceptional circumstances
-such as an application's most critical inner loop it may be desirable
-to use some other means of locking.
-      </P
-><P
->When a critical region is very very small it is possible to lock the
-scheduler, thus ensuring that no other thread can run until the
-scheduler is unlocked again. This is achieved with calls to <A
-HREF="kernel-schedcontrol.html"
-><TT
-CLASS="FUNCTION"
->cyg_scheduler_lock</TT
-></A
->
-and <TT
-CLASS="FUNCTION"
->cyg_scheduler_unlock</TT
->. If the critical region
-is sufficiently small then this can actually improve both performance
-and dispatch latency because <TT
-CLASS="FUNCTION"
->cyg_mutex_lock</TT
-> also
-locks the scheduler for a brief period of time. This approach will not
-work on SMP systems because another thread may already be running on a
-different processor and accessing the critical region.
-      </P
-><P
->Another way of avoiding the use of mutexes is to make sure that all
-threads that access a particular critical region run at the same
-priority and configure the system with timeslicing disabled
-(<TT
-CLASS="VARNAME"
->CYGSEM_KERNEL_SCHED_TIMESLICE</TT
->). Without
-timeslicing a thread can only be preempted by a higher-priority one,
-or if it performs some operation that can block. This approach
-requires that none of the operations in the critical region can block,
-so for example it is not legal to call
-<TT
-CLASS="FUNCTION"
->cyg_semaphore_wait</TT
->. It is also vulnerable to
-any changes in the configuration or to the various thread priorities:
-any such changes may now have unexpected side effects. It will not
-work on SMP systems.
-      </P
-></DIV
-><DIV
-CLASS="REFSECT1"
-><A
-NAME="KERNEL-MUTEXES-RECURSIVE"
-></A
-><H2
->Recursive Mutexes</H2
-><P
->The implementation of mutexes within the eCos kernel does not support
-recursive locks. If a thread has locked a mutex and then attempts to
-lock the mutex again, typically as a result of some recursive call in
-a complicated call graph, then either an assertion failure will be
-reported or the thread will deadlock. This behaviour is deliberate.
-When a thread has just locked a mutex associated with some data
-structure, it can assume that that data structure is in a consistent
-state. Before unlocking the mutex again it must ensure that the data
-structure is again in a consistent state. Recursive mutexes allow a
-thread to make arbitrary changes to a data structure, then in a
-recursive call lock the mutex again while the data structure is still
-inconsistent. The net result is that code can no longer make any
-assumptions about data structure consistency, which defeats the
-purpose of using mutexes.
-      </P
-></DIV
-><DIV
-CLASS="REFSECT1"
-><A
-NAME="KERNEL-MUTEXES-CONTEXT"
-></A
-><H2
->Valid contexts</H2
-><P
-><TT
-CLASS="FUNCTION"
->cyg_mutex_init</TT
->,
-<TT
-CLASS="FUNCTION"
->cyg_mutex_set_ceiling</TT
-> and
-<TT
-CLASS="FUNCTION"
->cyg_mutex_set_protocol</TT
-> are normally called during
-initialization but may also be called from thread context. The
-remaining functions should only be called from thread context. Mutexes
-serve as a mutual exclusion mechanism between threads, and cannot be
-used to synchronize between threads and the interrupt handling
-subsystem. If a critical region is shared between a thread and a DSR
-then it must be protected using <A
-HREF="kernel-schedcontrol.html"
-><TT
-CLASS="FUNCTION"
->cyg_scheduler_lock</TT
-></A
->
-and <TT
-CLASS="FUNCTION"
->cyg_scheduler_unlock</TT
->. If a critical region is
-shared between a thread and an ISR, it must be protected by disabling
-or masking interrupts. Obviously these operations must be used with
-care because they can affect dispatch and interrupt latencies.
-      </P
-></DIV
-><DIV
-CLASS="NAVFOOTER"
-><HR
-ALIGN="LEFT"
-WIDTH="100%"><TABLE
-SUMMARY="Footer navigation table"
-WIDTH="100%"
-BORDER="0"
-CELLPADDING="0"
-CELLSPACING="0"
-><TR
-><TD
-WIDTH="33%"
-ALIGN="left"
-VALIGN="top"
-><A
-HREF="kernel-alarms.html"
-ACCESSKEY="P"
->Prev</A
-></TD
-><TD
-WIDTH="34%"
-ALIGN="center"
-VALIGN="top"
-><A
-HREF="ecos-ref.html"
-ACCESSKEY="H"
->Home</A
-></TD
-><TD
-WIDTH="33%"
-ALIGN="right"
-VALIGN="top"
-><A
-HREF="kernel-condition-variables.html"
-ACCESSKEY="N"
->Next</A
-></TD
-></TR
-><TR
-><TD
-WIDTH="33%"
-ALIGN="left"
-VALIGN="top"
->Alarms</TD
-><TD
-WIDTH="34%"
-ALIGN="center"
-VALIGN="top"
-><A
-HREF="kernel.html"
-ACCESSKEY="U"
->Up</A
-></TD
-><TD
-WIDTH="33%"
-ALIGN="right"
-VALIGN="top"
->Condition Variables</TD
-></TR
-></TABLE
-></DIV
-></BODY
-></HTML
->
\ No newline at end of file