doc: Edit microkernel_mutexes.rst; add ReST syntax, clarifications.
Making all the files in this section consistent with :dfn: in the intro paragraph, API headings, present-tense verbs in APIs. Clarified paragraphs on priorty-bazed waiting and priority inheritance. Change-Id: I26cc49926bc49c9c68300b6249aeb52c1be33625 Signed-off-by: L.S. Cook <leonax.cook@intel.com>
This commit is contained in:
parent
b3dcd612da
commit
fd2c760593
1 changed files with 52 additions and 49 deletions
|
@ -6,7 +6,7 @@ Mutexes
|
||||||
Concepts
|
Concepts
|
||||||
********
|
********
|
||||||
|
|
||||||
The microkernel's mutex objects provide reentrant mutex
|
The microkernel's :dfn:`mutex` objects provide reentrant mutex
|
||||||
capabilities with basic priority inheritance.
|
capabilities with basic priority inheritance.
|
||||||
|
|
||||||
Each mutex allows multiple tasks to safely share an associated
|
Each mutex allows multiple tasks to safely share an associated
|
||||||
|
@ -14,32 +14,33 @@ resource by ensuring mutual exclusivity while the resource is
|
||||||
being accessed by a task.
|
being accessed by a task.
|
||||||
|
|
||||||
Any number of mutexes can be defined in a microkernel system.
|
Any number of mutexes can be defined in a microkernel system.
|
||||||
Each mutex has a name that uniquely identifies it. Typically,
|
Each mutex needs a **name** that uniquely identifies it. Typically,
|
||||||
the name should relate to the resource being shared, but this is
|
the name should relate to the resource being shared, although this
|
||||||
not a requirement.
|
is not a requirement.
|
||||||
|
|
||||||
A task that needs to use a shared resource must first gain
|
A task that needs to use a shared resource must first gain exclusive
|
||||||
exclusive access by locking the associated mutex. When the mutex
|
access by locking the associated mutex. If the mutex is already locked
|
||||||
is already locked by another task, the requesting task may
|
by another task, the requesting task can wait for the mutex to be
|
||||||
choose to wait for the mutex to be unlocked. After obtaining the lock,
|
unlocked.
|
||||||
a task can safely use the shared resource for as long as needed.
|
|
||||||
When the task no longer needs the resource, it must unlock the
|
|
||||||
associated mutex to allow other tasks to use the resource.
|
|
||||||
|
|
||||||
Any number of tasks may wait on a locked mutex simultaneously.
|
After obtaining the mutex, the task may safely use the shared
|
||||||
When there is more than one waiting task, the mutex locks the
|
resource for as long as needed. And when the task no longer needs
|
||||||
resource for the highest priority task that has waited the longest
|
the resource, it must release the associated mutex to allow
|
||||||
first.
|
other tasks to use the resource.
|
||||||
|
|
||||||
Priority inheritance occurs whenever a high priority task waits
|
Any number of tasks may wait on a locked mutex. When more than one
|
||||||
on a mutex that is locked by a lower priority task. The priority
|
task is waiting, the mutex locks the resource for the highest-priority
|
||||||
of the lower priority task increases temporarily to the priority
|
task that has waited the longest first; this is known as
|
||||||
of the highest priority task that is waiting on a mutex held by
|
:dfn:`priority-based waiting`. The order is decided when a task decides
|
||||||
the lower priority task. This allows the lower priority
|
to wait on the object: it is queued in priority order.
|
||||||
task to complete its work and unlock the mutex as quickly as
|
|
||||||
possible. Once the mutex has been unlocked, the lower priority task
|
The task currently owning the mutex is also eligible for :dfn:`priority inheritance`.
|
||||||
sets its task priority to the priority it had prior to locking that
|
Priority inheritance is the concept by which a task of lower priority gets its
|
||||||
mutex.
|
priority *temporarily* elevated to the priority of the highest-priority
|
||||||
|
task that is waiting on a mutex held by the lower priority task. Thus, the
|
||||||
|
lower-priority task can complete its work and release the mutex as quickly
|
||||||
|
as possible. Once the mutex has been released, the lower-priority task resets
|
||||||
|
its task priority to the priority it had before locking that mutex.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -49,29 +50,26 @@ mutex.
|
||||||
|
|
||||||
When two or more tasks wait on a mutex held by a lower priority task, the
|
When two or more tasks wait on a mutex held by a lower priority task, the
|
||||||
kernel adjusts the owning task's priority each time a task begins waiting
|
kernel adjusts the owning task's priority each time a task begins waiting
|
||||||
(or gives up waiting). When the mutex is eventually released the owning
|
(or gives up waiting). When the mutex is eventually released, the owning
|
||||||
task's priority correctly reverts to its original non-elevated priority.
|
task's priority correctly reverts to its original non-elevated priority.
|
||||||
|
|
||||||
.. note::
|
The kernel does *not* fully support priority inheritance when a task holds
|
||||||
|
two or more mutexes simultaneously. This situation can result in the task's
|
||||||
|
priority not reverting to its original non-elevated priority when all mutexes
|
||||||
|
have been released. Preferably, a task holds only a single mutex when multiple
|
||||||
|
mutexes are shared between tasks of different priorities.
|
||||||
|
|
||||||
The kernel does *not* fully support priority inheritance when a task
|
The microkernel also allows a task to repeatedly lock a mutex it has already
|
||||||
holds two or more mutexes simultaneously. This situation can result
|
locked. This ensures that the task can access the resource at a point in its
|
||||||
in the task's priority not reverting to its original non-elevated
|
execution when the resource may or may not already be locked. A mutex that is
|
||||||
priority when all mutexes have been released. It is recommended that
|
repeatedly locked must be unlocked an equal number of times before the mutex
|
||||||
a task hold only a single mutex at a time when multiple mutexes are
|
can release the resource completely.
|
||||||
shared between tasks of different priorities.
|
|
||||||
|
|
||||||
The microkernel also allows a task to repeatedly lock a mutex it
|
|
||||||
already locked. This ensures that the task can access the resource
|
|
||||||
at a point in its execution when the resource may or may not
|
|
||||||
already be locked. A mutex that is repeatedly locked must be unlocked
|
|
||||||
an equal number of times before the mutex releases the resource
|
|
||||||
completely.
|
|
||||||
|
|
||||||
Purpose
|
Purpose
|
||||||
*******
|
*******
|
||||||
Use mutexes to provide exclusive access to a resource,
|
|
||||||
such as a physical device.
|
Use mutexes to provide exclusive access to a resource, such as a physical
|
||||||
|
device.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
*****
|
*****
|
||||||
|
@ -87,7 +85,7 @@ The following parameters must be defined:
|
||||||
Public Mutex
|
Public Mutex
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Define the mutex in the application's MDEF using the following syntax:
|
Define the mutex in the application's MDEF file with the following syntax:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
@ -119,12 +117,14 @@ For example, the following code defines a private mutex named ``XYZ``.
|
||||||
|
|
||||||
DEFINE_MUTEX(XYZ);
|
DEFINE_MUTEX(XYZ);
|
||||||
|
|
||||||
To utilize this mutex from a different source file use the following syntax:
|
The following syntax allows this mutex to be accessed from a different
|
||||||
|
source file:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
extern const kmutex_t XYZ;
|
extern const kmutex_t XYZ;
|
||||||
|
|
||||||
|
|
||||||
Example: Locking a Mutex with No Conditions
|
Example: Locking a Mutex with No Conditions
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ mutex is in use.
|
||||||
lineto(200,100);
|
lineto(200,100);
|
||||||
task_mutex_unlock(XYZ);
|
task_mutex_unlock(XYZ);
|
||||||
|
|
||||||
|
|
||||||
Example: Locking a Mutex with a Conditional Timeout
|
Example: Locking a Mutex with a Conditional Timeout
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
|
@ -179,13 +180,15 @@ This code gives an immediate warning when a mutex is in use.
|
||||||
APIs
|
APIs
|
||||||
****
|
****
|
||||||
|
|
||||||
The following Mutex APIs are provided by :file:`microkernel.h`:
|
Mutex APIs provided by :file:`microkernel.h`
|
||||||
|
============================================
|
||||||
|
|
||||||
:cpp:func:`task_mutex_lock()`
|
:cpp:func:`task_mutex_lock()`
|
||||||
Waits on a locked mutex for the period of time defined by the timeout
|
Wait on a locked mutex for the period of time defined by the timeout
|
||||||
parameter. If the mutex becomes available during that period, the function
|
parameter. Lock the mutex and increment the lock count if the mutex
|
||||||
locks the mutex, and increments the lock count.
|
becomes available during that period.
|
||||||
|
|
||||||
:c:func:`task_mutex_unlock()`
|
:cpp:func:`task_mutex_unlock()`
|
||||||
Decrements a mutex lock count, and unlocks the mutex when the count
|
Decrement a mutex lock count, and unlock the mutex when the count
|
||||||
reaches zero.
|
reaches zero.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue