From 16ee8cf45bfd2c02ec2bd5d2fcabc6876cb2de65 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 16 Jun 2020 14:16:09 +0200 Subject: c-user: Split up semaphore manager This makes it easier to automatically generate parts of the manager documentation in the future. Update #3993. --- c-user/semaphore/background.rst | 180 +++++++++++ c-user/semaphore/directives.rst | 650 ++++++++++++++++++++++++++++++++++++++ c-user/semaphore/index.rst | 18 ++ c-user/semaphore/introduction.rst | 25 ++ c-user/semaphore/operations.rst | 105 ++++++ 5 files changed, 978 insertions(+) create mode 100644 c-user/semaphore/background.rst create mode 100644 c-user/semaphore/directives.rst create mode 100644 c-user/semaphore/index.rst create mode 100644 c-user/semaphore/introduction.rst create mode 100644 c-user/semaphore/operations.rst (limited to 'c-user/semaphore') diff --git a/c-user/semaphore/background.rst b/c-user/semaphore/background.rst new file mode 100644 index 0000000..9d9b151 --- /dev/null +++ b/c-user/semaphore/background.rst @@ -0,0 +1,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 ` 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 ` 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``. diff --git a/c-user/semaphore/directives.rst b/c-user/semaphore/directives.rst new file mode 100644 index 0000000..460947d --- /dev/null +++ b/c-user/semaphore/directives.rst @@ -0,0 +1,650 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR) + +Directives +========== + +This section details the semaphore manager's directives. A subsection is +dedicated to each of this manager's directives and describes the calling +sequence, related constants, usage, and status codes. + +.. raw:: latex + + \clearpage + +.. index:: create a semaphore +.. index:: rtems_semaphore_create + +.. _rtems_semaphore_create: + +SEMAPHORE_CREATE - Create a semaphore +------------------------------------- + + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_create( + rtems_name name, + uint32_t count, + rtems_attribute attribute_set, + rtems_task_priority priority_ceiling, + rtems_id *id + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore created successfully + * - ``RTEMS_INVALID_NAME`` + - invalid semaphore name + * - ``RTEMS_INVALID_ADDRESS`` + - ``id`` is NULL + * - ``RTEMS_TOO_MANY`` + - too many semaphores created + * - ``RTEMS_NOT_DEFINED`` + - invalid attribute set + * - ``RTEMS_INVALID_NUMBER`` + - invalid starting count for binary semaphore + * - ``RTEMS_TOO_MANY`` + - too many global objects + +DESCRIPTION: + This directive creates a semaphore which resides on the local node. The + created semaphore has the user-defined name specified in name and the + initial count specified in count. For control and maintenance of the + semaphore, RTEMS allocates and initializes a SMCB. The RTEMS-assigned + semaphore id is returned in id. This semaphore id is used with other + semaphore related directives to access the semaphore. + + Specifying PRIORITY in attribute_set causes tasks waiting for a semaphore + to be serviced according to task priority. When FIFO is selected, tasks + are serviced in First In-First Out order. + +NOTES: + This directive may cause the calling task to be preempted due to an + obtain and release of the object allocator mutex. + + The priority inheritance and priority ceiling algorithms are only supported + for local, binary semaphores that use the priority task wait queue blocking + discipline. + + The following semaphore attribute constants are defined by RTEMS: + + .. 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, block on 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 + + Semaphores should not be made global unless remote tasks must interact with + the created semaphore. This is to avoid the system overhead incurred by + the creation of a global semaphore. When a global semaphore is created, + the semaphore's name and id must be transmitted to every node in the system + for insertion in the local copy of the global object table. + + *Note*, some combinations of attributes are not valid. See the earlier + discussion on this. + + The total number of global objects, including semaphores, is limited by the + maximum_global_objects field in the Configuration Table. + + It is not allowed to create an initially locked MrsP semaphore and the + ``RTEMS_INVALID_NUMBER`` status code will be returned in SMP configurations + in this case. This prevents lock order reversal problems with the + allocator mutex. + +.. raw:: latex + + \clearpage + +.. index:: get ID of a semaphore +.. index:: obtain ID of a semaphore +.. index:: rtems_semaphore_ident + +.. _rtems_semaphore_ident: + +SEMAPHORE_IDENT - Get ID of a semaphore +--------------------------------------- + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_ident( + rtems_name name, + uint32_t node, + rtems_id *id + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore identified successfully + * - ``RTEMS_INVALID_NAME`` + - semaphore name not found + * - ``RTEMS_INVALID_NODE`` + - invalid node id + +DESCRIPTION: + This directive obtains the semaphore id associated with the semaphore name. + If the semaphore name is not unique, then the semaphore id will match one + of the semaphores with that name. However, this semaphore id is not + guaranteed to correspond to the desired semaphore. The semaphore id is + used by other semaphore related directives to access the semaphore. + +NOTES: + This directive will not cause the running task to be preempted. + + If node is ``RTEMS_SEARCH_ALL_NODES``, all nodes are searched with the + local node being searched first. All other nodes are searched with the + lowest numbered node searched first. + + If node is a valid node number which does not represent the local node, + then only the semaphores exported by the designated node are searched. + + This directive does not generate activity on remote nodes. It accesses + only the local copy of the global object table. + +.. raw:: latex + + \clearpage + +.. index:: delete a semaphore +.. index:: rtems_semaphore_delete + +.. _rtems_semaphore_delete: + +SEMAPHORE_DELETE - Delete a semaphore +------------------------------------- + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_delete( + rtems_id id + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore deleted successfully + * - ``RTEMS_INVALID_ID`` + - invalid semaphore id + * - ``RTEMS_RESOURCE_IN_USE`` + - binary semaphore is in use + * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT`` + - cannot delete remote semaphore + +DESCRIPTION: + This directive deletes the semaphore specified by ``id``. All tasks + blocked waiting to acquire the semaphore will be readied and returned a + status code which indicates that the semaphore was deleted. The SMCB for + this semaphore is reclaimed by RTEMS. + +NOTES: + This directive may cause the calling task to be preempted due to an + obtain and release of the object allocator mutex. + + The calling task will be preempted if it is enabled by the task's execution + mode and a higher priority local task is waiting on the deleted semaphore. + The calling task will NOT be preempted if all of the tasks that are waiting + on the semaphore are remote tasks. + + The calling task does not have to be the task that created the semaphore. Any + local task that knows the semaphore id can delete the semaphore. + + When a global semaphore is deleted, the semaphore id must be transmitted to + every node in the system for deletion from the local copy of the global + object table. + + The semaphore must reside on the local node, even if the semaphore was + created with the ``RTEMS_GLOBAL`` option. + + Proxies, used to represent remote tasks, are reclaimed when the semaphore + is deleted. + +.. raw:: latex + + \clearpage + +.. index:: obtain a semaphore +.. index:: lock a semaphore +.. index:: rtems_semaphore_obtain + +.. _rtems_semaphore_obtain: + +SEMAPHORE_OBTAIN - Acquire a semaphore +-------------------------------------- + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_obtain( + rtems_id id, + rtems_option option_set, + rtems_interval timeout + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore obtained successfully + * - ``RTEMS_UNSATISFIED`` + - semaphore not available + * - ``RTEMS_TIMEOUT`` + - timed out waiting for semaphore + * - ``RTEMS_OBJECT_WAS_DELETED`` + - semaphore deleted while waiting + * - ``RTEMS_INVALID_ID`` + - invalid semaphore id + +DESCRIPTION: + This directive acquires the semaphore specified by id. The ``RTEMS_WAIT`` + and ``RTEMS_NO_WAIT`` components of the options parameter indicate whether + the calling task wants to wait for the semaphore to become available or + return immediately if the semaphore is not currently available. With + either ``RTEMS_WAIT`` or ``RTEMS_NO_WAIT``, if the current semaphore count + is positive, then it is decremented by one and the semaphore is + successfully acquired by returning immediately with a successful return + code. + + If the calling task chooses to return immediately and the current semaphore + count is zero or negative, then a status code is returned indicating that + the semaphore is not available. If the calling task chooses to wait for a + semaphore and the current semaphore count is zero or negative, then it is + decremented by one and the calling task is placed on the semaphore's wait + queue and blocked. If the semaphore was created with the + ``RTEMS_PRIORITY`` attribute, then the calling task is inserted into the + queue according to its priority. However, if the semaphore was created + with the ``RTEMS_FIFO`` attribute, then the calling task is placed at the + rear of the wait queue. If the binary semaphore was created with the + ``RTEMS_INHERIT_PRIORITY`` attribute, then the priority of the task + currently holding the binary semaphore is guaranteed to be greater than or + equal to that of the blocking task. If the binary semaphore was created + with the ``RTEMS_PRIORITY_CEILING`` attribute, a task successfully obtains + the semaphore, and the priority of that task is greater than the ceiling + priority for this semaphore, then the priority of the task obtaining the + semaphore is elevated to that of the ceiling. + + The timeout parameter specifies the maximum interval the calling task is + willing to be blocked waiting for the semaphore. If it is set to + ``RTEMS_NO_TIMEOUT``, then the calling task will wait forever. If the + semaphore is available or the ``RTEMS_NO_WAIT`` option component is set, + then timeout is ignored. + + In case a semaphore is not available, then ``RTEMS_UNSATISFIED`` will be + returned. This happens immediately in case ``RTEMS_NO_WAIT`` is specified, + or as a result of another task invoking the ``rtems_semaphore_flush`` + directive in case ``RTEMS_WAIT`` is specified. + + Deadlock situations are detected for MrsP semaphores and the + ``RTEMS_UNSATISFIED`` status code will be returned in SMP configurations in + this case. + +NOTES: + The following semaphore acquisition option constants are defined by RTEMS: + + .. list-table:: + :class: rtems-table + + * - ``RTEMS_WAIT`` + - task will wait for semaphore (default) + * - ``RTEMS_NO_WAIT`` + - task should not wait + + Attempting to obtain a global semaphore which does not reside on the local + node will generate a request to the remote node to access the semaphore. + If the semaphore is not available and ``RTEMS_NO_WAIT`` was not specified, + then the task must be blocked until the semaphore is released. A proxy is + allocated on the remote node to represent the task until the semaphore is + released. + + A clock tick is required to support the timeout functionality of this + directive. + + It is not allowed to obtain a MrsP semaphore more than once by one task at + a time (nested access) and the ``RTEMS_UNSATISFIED`` status code will be + returned in SMP configurations in this case. + +.. raw:: latex + + \clearpage + +.. index:: release a semaphore +.. index:: unlock a semaphore +.. index:: rtems_semaphore_release + +.. _rtems_semaphore_release: + +SEMAPHORE_RELEASE - Release a semaphore +--------------------------------------- + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_release( + rtems_id id + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore released successfully + * - ``RTEMS_INVALID_ID`` + - invalid semaphore id + * - ``RTEMS_NOT_OWNER_OF_RESOURCE`` + - calling task does not own semaphore + * - ``RTEMS_INCORRECT_STATE`` + - invalid unlock order + +DESCRIPTION: + This directive releases the semaphore specified by id. The semaphore count + is incremented by one. If the count is zero or negative, then the first + task on this semaphore's wait queue is removed and unblocked. The + unblocked task may preempt the running task if the running task's + preemption mode is enabled and the unblocked task has a higher priority + than the running task. + +NOTES: + The calling task may be preempted if it causes a higher priority task to be + made ready for execution. + + Releasing a global semaphore which does not reside on the local node will + generate a request telling the remote node to release the semaphore. + + If the task to be unblocked resides on a different node from the semaphore, + then the semaphore allocation is forwarded to the appropriate node, the + waiting task is unblocked, and the proxy used to represent the task is + reclaimed. + + The outermost release of a local, binary, priority inheritance or priority + ceiling semaphore may result in the calling task having its priority + lowered. This will occur if the calling task holds no other binary + semaphores and it has inherited a higher priority. + + The MrsP semaphores must be released in the reversed obtain order, + otherwise the ``RTEMS_INCORRECT_STATE`` status code will be returned in SMP + configurations in this case. + +.. raw:: latex + + \clearpage + +.. index:: flush a semaphore +.. index:: unblock all tasks waiting on a semaphore +.. index:: rtems_semaphore_flush + +.. _rtems_semaphore_flush: + +SEMAPHORE_FLUSH - Unblock all tasks waiting on a semaphore +---------------------------------------------------------- + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_flush( + rtems_id id + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - semaphore released successfully + * - ``RTEMS_INVALID_ID`` + - invalid semaphore id + * - ``RTEMS_NOT_DEFINED`` + - operation not defined for the protocol of the semaphore + * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT`` + - not supported for remote semaphores + +DESCRIPTION: + This directive unblocks all tasks waiting on the semaphore specified by id. + Since there are tasks blocked on the semaphore, the semaphore's count is + not changed by this directive and thus is zero before and after this + directive is executed. Tasks which are unblocked as the result of this + directive will return from the ``rtems_semaphore_obtain`` directive with a + status code of ``RTEMS_UNSATISFIED`` to indicate that the semaphore was not + obtained. + + This directive may unblock any number of tasks. Any of the unblocked tasks + may preempt the running task if the running task's preemption mode is + enabled and an unblocked task has a higher priority than the running task. + +NOTES: + The calling task may be preempted if it causes a higher priority task to be + made ready for execution. + + If the task to be unblocked resides on a different node from the semaphore, + then the waiting task is unblocked, and the proxy used to represent the + task is reclaimed. + + It is not allowed to flush a MrsP semaphore and the ``RTEMS_NOT_DEFINED`` + status code will be returned in SMP configurations in this case. + + Using the ``rtems_semaphore_flush`` directive for condition synchronization + in concert with another semaphore may be subject to the lost wake-up + problem. The following attempt to implement a condition variable is + broken. + + .. code-block:: c + + #include + #include + + void cnd_wait( rtems_id cnd, rtems_id mtx ) + { + rtems_status_code sc; + + sc = rtems_semaphore_release( mtx ); + assert( sc == RTEMS_SUCCESSFUL ); + + /* + * Here, a higher priority task may run and satisfy the condition. We + * may never wake up from the next semaphore obtain. + */ + + sc = rtems_semaphore_obtain( cnd, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + assert( sc == RTEMS_UNSATISFIED ); + + sc = rtems_semaphore_obtain( mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + assert( sc == RTEMS_SUCCESSFUL ); + } + + void cnd_broadcast( rtems_id cnd ) + { + rtems_status_code sc; + + sc = rtems_semaphore_flush( cnd ); + assert( sc == RTEMS_SUCCESSFUL ); + } + + For barrier synchronization, the :ref:`barrier_manager` offers a cleaner + alternative to using the `rtems_semaphore_flush` directive. Unlike POSIX + barriers, they have a manual release option. + +.. raw:: latex + + \clearpage + +.. index:: set priority by scheduler for a semaphore +.. index:: rtems_semaphore_set_priority + +.. _rtems_semaphore_set_priority: + +SEMAPHORE_SET_PRIORITY - Set priority by scheduler for a semaphore +------------------------------------------------------------------ + +CALLING SEQUENCE: + .. code-block:: c + + rtems_status_code rtems_semaphore_set_priority( + rtems_id semaphore_id, + rtems_id scheduler_id, + rtems_task_priority new_priority, + rtems_task_priority *old_priority + ); + +DIRECTIVE STATUS CODES: + .. list-table:: + :class: rtems-table + + * - ``RTEMS_SUCCESSFUL`` + - successful operation + * - ``RTEMS_INVALID_ID`` + - invalid semaphore or scheduler id + * - ``RTEMS_INVALID_ADDRESS`` + - ``old_priority`` is NULL + * - ``RTEMS_INVALID_PRIORITY`` + - invalid new priority value + * - ``RTEMS_NOT_DEFINED`` + - operation not defined for the protocol ofthe semaphore + * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT`` + - not supported for remote semaphores + +DESCRIPTION: + This directive sets the priority value with respect to the specified + scheduler of a semaphore. + + The special priority value ``RTEMS_CURRENT_PRIORITY`` can be used to get + the current priority value without changing it. + + The interpretation of the priority value depends on the protocol of the + semaphore object. + + - The Multiprocessor Resource Sharing Protocol needs a ceiling priority per + scheduler instance. This operation can be used to specify these priority + values. + + - For the Priority Ceiling Protocol the ceiling priority is used with this + operation. + + - For other protocols this operation is not defined. + +EXAMPLE: + .. code-block:: c + :linenos: + + #include + #include + #include + + #define SCHED_A rtems_build_name(' ', ' ', ' ', 'A') + #define SCHED_B rtems_build_name(' ', ' ', ' ', 'B') + + static void Init(rtems_task_argument arg) + { + rtems_status_code sc; + rtems_id semaphore_id; + rtems_id scheduler_a_id; + rtems_id scheduler_b_id; + rtems_task_priority prio; + + /* Get the scheduler identifiers */ + sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id); + assert(sc == RTEMS_SUCCESSFUL); + sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id); + assert(sc == RTEMS_SUCCESSFUL); + + /* Create a MrsP semaphore object */ + sc = rtems_semaphore_create( + rtems_build_name('M', 'R', 'S', 'P'), + 1, + RTEMS_MULTIPROCESSOR_RESOURCE_SHARING | RTEMS_BINARY_SEMAPHORE, + 1, + &semaphore_id + ); + assert(sc == RTEMS_SUCCESSFUL); + + /* + * The ceiling priority values per scheduler are equal to the value specified + * for object creation. + */ + prio = RTEMS_CURRENT_PRIORITY; + sc = rtems_semaphore_set_priority(semaphore_id, scheduler_a_id, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); + assert(prio == 1); + + /* Check the old value and set a new ceiling priority for scheduler B */ + prio = 2; + sc = rtems_semaphore_set_priority(semaphore_id, scheduler_b_id, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); + assert(prio == 1); + + /* Check the ceiling priority values */ + prio = RTEMS_CURRENT_PRIORITY; + sc = rtems_semaphore_set_priority(semaphore_id, scheduler_a_id, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); + assert(prio == 1); + prio = RTEMS_CURRENT_PRIORITY; + sc = rtems_semaphore_set_priority(semaphore_id, scheduler_b_id, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); + assert(prio == 2); + + sc = rtems_semaphore_delete(semaphore_id); + assert(sc == RTEMS_SUCCESSFUL); + + exit(0); + } + + #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_MAXIMUM_TASKS 1 + #define CONFIGURE_MAXIMUM_SEMAPHORES 1 + #define CONFIGURE_MAXIMUM_PROCESSORS 2 + + #define CONFIGURE_SCHEDULER_SIMPLE_SMP + + #include + + RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a); + RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b); + + #define CONFIGURE_SCHEDULER_TABLE_ENTRIES \ + RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(a, SCHED_A), \ + RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(b, SCHED_B) + + #define CONFIGURE_SCHEDULER_ASSIGNMENTS \ + RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \ + RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) + + #define CONFIGURE_RTEMS_INIT_TASKS_TABLE + #define CONFIGURE_INIT + + #include diff --git a/c-user/semaphore/index.rst b/c-user/semaphore/index.rst new file mode 100644 index 0000000..2110744 --- /dev/null +++ b/c-user/semaphore/index.rst @@ -0,0 +1,18 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de) + +.. index:: semaphores +.. index:: binary semaphores +.. index:: counting semaphores +.. index:: mutual exclusion + +Semaphore Manager +***************** + +.. toctree:: + + introduction + background + operations + directives diff --git a/c-user/semaphore/introduction.rst b/c-user/semaphore/introduction.rst new file mode 100644 index 0000000..dee298b --- /dev/null +++ b/c-user/semaphore/introduction.rst @@ -0,0 +1,25 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR) + +Introduction +============ + +The semaphore manager utilizes standard Dijkstra +counting semaphores to provide synchronization and mutual +exclusion capabilities. The directives provided by the +semaphore manager are: + +- :ref:`rtems_semaphore_create` + +- :ref:`rtems_semaphore_ident` + +- :ref:`rtems_semaphore_delete` + +- :ref:`rtems_semaphore_obtain` + +- :ref:`rtems_semaphore_release` + +- :ref:`rtems_semaphore_flush` + +- :ref:`rtems_semaphore_set_priority` diff --git a/c-user/semaphore/operations.rst b/c-user/semaphore/operations.rst new file mode 100644 index 0000000..19c4be2 --- /dev/null +++ b/c-user/semaphore/operations.rst @@ -0,0 +1,105 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR) + +Operations +========== + +.. _Creating a Semaphore: + +Creating a Semaphore +-------------------- + +The ``rtems_semaphore_create`` directive creates a binary or counting semaphore +with a user-specified name as well as an initial count. If a binary semaphore +is created with a count of zero (0) to indicate that it has been allocated, +then the task creating the semaphore is considered the current holder of the +semaphore. At create time the method for ordering waiting tasks in the +semaphore's task wait queue (by FIFO or task priority) is specified. +Additionally, the priority inheritance or priority ceiling algorithm may be +selected for local, binary semaphores that use the priority task wait queue +blocking discipline. If the priority ceiling algorithm is selected, then the +highest priority of any task which will attempt to obtain this semaphore must +be specified. RTEMS allocates a Semaphore Control Block (SMCB) from the SMCB +free list. This data structure is used by RTEMS to manage the newly created +semaphore. Also, a unique semaphore ID is generated and returned to the +calling task. + +.. _Obtaining Semaphore IDs: + +Obtaining Semaphore IDs +----------------------- + +When a semaphore is created, RTEMS generates a unique semaphore ID and assigns +it to the created semaphore until it is deleted. The semaphore ID may be +obtained by either of two methods. First, as the result of an invocation of +the ``rtems_semaphore_create`` directive, the semaphore ID is stored in a user +provided location. Second, the semaphore ID may be obtained later using the +``rtems_semaphore_ident`` directive. The semaphore ID is used by other +semaphore manager directives to access this semaphore. + +.. _Acquiring a Semaphore: + +Acquiring a Semaphore +--------------------- + +The ``rtems_semaphore_obtain`` directive is used to acquire the +specified semaphore. A simplified version of the ``rtems_semaphore_obtain`` +directive can be described as follows: + + If the semaphore's count is greater than zero then decrement the + semaphore's count else wait for release of semaphore then return + SUCCESSFUL. + +When the semaphore cannot be immediately acquired, one of the following +situations applies: + +- By default, the calling task will wait forever to acquire the semaphore. + +- Specifying ``RTEMS_NO_WAIT`` forces an immediate return with an error status + code. + +- Specifying a timeout limits the interval the task will wait before returning + with an error status code. + +If the task waits to acquire the semaphore, then it is placed in the +semaphore's task wait queue in either FIFO or task priority order. If the task +blocked waiting for a binary semaphore using priority inheritance and the +task's priority is greater than that of the task currently holding the +semaphore, then the holding task will inherit the priority of the blocking +task. All tasks waiting on a semaphore are returned an error code when the +semaphore is deleted. + +When a task successfully obtains a semaphore using priority ceiling and the +priority ceiling for this semaphore is greater than that of the holder, then +the holder's priority will be elevated. + +.. _Releasing a Semaphore: + +Releasing a Semaphore +--------------------- + +The ``rtems_semaphore_release`` directive is used to release the specified +semaphore. A simplified version of the ``rtems_semaphore_release`` directive +can be described as follows: + + If there are no tasks are waiting on this semaphore then increment the + semaphore's count else assign semaphore to a waiting task and return + SUCCESSFUL. + +If this is the outermost release of a binary semaphore that uses priority +inheritance or priority ceiling and the task does not currently hold any other +binary semaphores, then the task performing the ``rtems_semaphore_release`` +will have its priority restored to its normal value. + +.. _Deleting a Semaphore: + +Deleting a Semaphore +-------------------- + +The ``rtems_semaphore_delete`` directive removes a semaphore from the system +and frees its control block. A semaphore can be deleted by any local task that +knows the semaphore's ID. As a result of this directive, all tasks blocked +waiting to acquire the semaphore will be readied and returned a status code +which indicates that the semaphore was deleted. Any subsequent references to +the semaphore's name and ID are invalid. -- cgit v1.2.3