summaryrefslogtreecommitdiffstats
path: root/c-user/semaphore/background.rst
blob: 9d9b151cf9e56fe726755903e3bce38f359957a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
.. SPDX-License-Identifier: CC-BY-SA-4.0

.. Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR)

Background
==========

A semaphore can be viewed as a protected variable whose value can be modified
only with the ``rtems_semaphore_create``, ``rtems_semaphore_obtain``, and
``rtems_semaphore_release`` directives.  RTEMS supports both binary and
counting semaphores. A binary semaphore is restricted to values of zero or one,
while a counting semaphore can assume any non-negative integer value.

A binary semaphore (not a simple binary semaphore) can be used to control
access to a single resource.  In particular, it can be used to enforce mutual
exclusion for a critical section in user code (mutex).  In this instance, the
semaphore would be created with an initial count of one to indicate that no
task is executing the critical section of code.  Upon entry to the critical
section, a task must issue the ``rtems_semaphore_obtain`` directive to prevent
other tasks from entering the critical section.  Upon exit from the critical
section, the task that obtained the binary semaphore must issue the
``rtems_semaphore_release`` directive to allow another task to execute the
critical section.  A binary semaphore must be released by the task that
obtained it.

A counting semaphore can be used to control access to a pool of two or more
resources.  For example, access to three printers could be administered by a
semaphore created with an initial count of three.  When a task requires access
to one of the printers, it issues the ``rtems_semaphore_obtain`` directive to
obtain access to a printer.  If a printer is not currently available, the task
can wait for a printer to become available or return immediately.  When the
task has completed printing, it should issue the ``rtems_semaphore_release``
directive to allow other tasks access to the printer.

Task synchronization may be achieved by creating a semaphore with an initial
count of zero.  One task waits for the arrival of another task by issuing a
``rtems_semaphore_obtain`` directive when it reaches a synchronization point.
The other task performs a corresponding ``rtems_semaphore_release`` operation
when it reaches its synchronization point, thus unblocking the pending task.

.. _Nested Resource Access:

Nested Resource Access
----------------------

Deadlock occurs when a task owning a binary semaphore attempts to acquire that
same semaphore and blocks as result.  Since the semaphore is allocated to a
task, it cannot be deleted.  Therefore, the task that currently holds the
semaphore and is also blocked waiting for that semaphore will never execute
again.

RTEMS addresses this problem by allowing the task holding the binary semaphore
to obtain the same binary semaphore multiple times in a nested manner.  Each
``rtems_semaphore_obtain`` must be accompanied with a
``rtems_semaphore_release``.  The semaphore will only be made available for
acquisition by other tasks when the outermost ``rtems_semaphore_obtain`` is
matched with a ``rtems_semaphore_release``.

Simple binary semaphores do not allow nested access and so can be used for task
synchronization.

.. _Priority Inheritance:

Priority Inheritance
--------------------

RTEMS supports :ref:`priority inheritance <PriorityInheritance>` for local,
binary semaphores that use the priority task wait queue blocking discipline.
In SMP configurations, the :ref:`OMIP` is used instead.

.. _Priority Ceiling:

Priority Ceiling
----------------

RTEMS supports :ref:`priority ceiling <PriorityCeiling>` for local, binary
semaphores that use the priority task wait queue blocking discipline.

.. _Multiprocessor Resource Sharing Protocol:

Multiprocessor Resource Sharing Protocol
----------------------------------------

RTEMS supports the :ref:`MrsP` for local, binary semaphores that use the
priority task wait queue blocking discipline.  In uniprocessor configurations,
the :ref:`PriorityCeiling` is used instead.

.. _Building a Semaphore Attribute Set:

Building a Semaphore Attribute Set
----------------------------------

In general, an attribute set is built by a bitwise OR of the desired attribute
components.  The following table lists the set of valid semaphore attributes:

.. list-table::
 :class: rtems-table

 * - ``RTEMS_FIFO``
   - tasks wait by FIFO (default)
 * - ``RTEMS_PRIORITY``
   - tasks wait by priority
 * - ``RTEMS_BINARY_SEMAPHORE``
   - restrict values to 0 and 1
 * - ``RTEMS_COUNTING_SEMAPHORE``
   - no restriction on values (default)
 * - ``RTEMS_SIMPLE_BINARY_SEMAPHORE``
   - restrict values to 0 and 1, do not allow nested access, allow deletion of
     locked semaphore.
 * - ``RTEMS_NO_INHERIT_PRIORITY``
   - do not use priority inheritance (default)
 * - ``RTEMS_INHERIT_PRIORITY``
   - use priority inheritance
 * - ``RTEMS_NO_PRIORITY_CEILING``
   - do not use priority ceiling (default)
 * - ``RTEMS_PRIORITY_CEILING``
   - use priority ceiling
 * - ``RTEMS_NO_MULTIPROCESSOR_RESOURCE_SHARING``
   - do not use Multiprocessor Resource Sharing Protocol (default)
 * - ``RTEMS_MULTIPROCESSOR_RESOURCE_SHARING``
   - use Multiprocessor Resource Sharing Protocol
 * - ``RTEMS_LOCAL``
   - local semaphore (default)
 * - ``RTEMS_GLOBAL``
   - global semaphore

Attribute values are specifically designed to be mutually exclusive, therefore
bitwise OR and addition operations are equivalent as long as each attribute
appears exactly once in the component list.  An attribute listed as a default
is not required to appear in the attribute list, although it is a good
programming practice to specify default attributes.  If all defaults are
desired, the attribute ``RTEMS_DEFAULT_ATTRIBUTES`` should be specified on this
call.

This example demonstrates the attribute_set parameter needed to create a local
semaphore with the task priority waiting queue discipline.  The attribute_set
parameter passed to the ``rtems_semaphore_create`` directive could be either
``RTEMS_PRIORITY`` or ``RTEMS_LOCAL | RTEMS_PRIORITY``.  The attribute_set
parameter can be set to ``RTEMS_PRIORITY`` because ``RTEMS_LOCAL`` is the
default for all created tasks.  If a similar semaphore were to be known
globally, then the attribute_set parameter would be ``RTEMS_GLOBAL |
RTEMS_PRIORITY``.

Some combinatinos of these attributes are invalid.  For example, priority
ordered blocking discipline must be applied to a binary semaphore in order to
use either the priority inheritance or priority ceiling functionality.  The
following tree figure illustrates the valid combinations.

.. figure:: ../../images/c_user/semaphore_attributes.png
         :width: 90%
         :align: center
         :alt: Semaphore Attributes

.. _Building a SEMAPHORE_OBTAIN Option Set:

Building a SEMAPHORE_OBTAIN Option Set
--------------------------------------

In general, an option is built by a bitwise OR of the desired option
components.  The set of valid options for the ``rtems_semaphore_obtain``
directive are listed in the following table:

.. list-table::
 :class: rtems-table

 * - ``RTEMS_WAIT``
   - task will wait for semaphore (default)
 * - ``RTEMS_NO_WAIT``
   - task should not wait

Option values are specifically designed to be mutually exclusive, therefore
bitwise OR and addition operations are equivalent as long as each attribute
appears exactly once in the component list.  An option listed as a default is
not required to appear in the list, although it is a good programming practice
to specify default options.  If all defaults are desired, the option
``RTEMS_DEFAULT_OPTIONS`` should be specified on this call.

This example demonstrates the option parameter needed to poll for a semaphore.
The option parameter passed to the ``rtems_semaphore_obtain`` directive should
be ``RTEMS_NO_WAIT``.