source: rtems-docs/c_user/semaphore_manager.rst @ 9aafb39

4.115
Last change on this file since 9aafb39 was 9aafb39, checked in by Chris Johns <chrisj@…>, on 10/28/16 at 12:56:02

c_user: Remove errors and warnings.

  • Property mode set to 100644
File size: 36.3 KB
Line 
1.. comment SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. COMMENT: COPYRIGHT (c) 1988-2008.
4.. COMMENT: On-Line Applications Research Corporation (OAR).
5.. COMMENT: All rights reserved.
6
7Semaphore Manager
8#################
9
10.. index:: semaphores
11.. index:: binary semaphores
12.. index:: counting semaphores
13.. index:: mutual exclusion
14
15Introduction
16============
17
18The semaphore manager utilizes standard Dijkstra
19counting semaphores to provide synchronization and mutual
20exclusion capabilities.  The directives provided by the
21semaphore manager are:
22
23- rtems_semaphore_create_ - Create a semaphore
24
25- rtems_semaphore_ident_ - Get ID of a semaphore
26
27- rtems_semaphore_delete_ - Delete a semaphore
28
29- rtems_semaphore_obtain_ - Acquire a semaphore
30
31- rtems_semaphore_release_ - Release a semaphore
32
33- rtems_semaphore_flush_ - Unblock all tasks waiting on a semaphore
34
35- rtems_semaphore_set_priority_ - Set priority by scheduler for a semaphore
36
37Background
38==========
39
40A semaphore can be viewed as a protected variable whose value can be modified
41only with the ``rtems_semaphore_create``, ``rtems_semaphore_obtain``, and
42``rtems_semaphore_release`` directives.  RTEMS supports both binary and
43counting semaphores. A binary semaphore is restricted to values of zero or one,
44while a counting semaphore can assume any non-negative integer value.
45
46A binary semaphore can be used to control access to a single resource.  In
47particular, it can be used to enforce mutual exclusion for a critical section
48in user code.  In this instance, the semaphore would be created with an initial
49count of one to indicate that no task is executing the critical section of
50code.  Upon entry to the critical section, a task must issue the
51``rtems_semaphore_obtain`` directive to prevent other tasks from entering the
52critical section.  Upon exit from the critical section, the task must issue the
53``rtems_semaphore_release`` directive to allow another task to execute the
54critical section.
55
56A counting semaphore can be used to control access to a pool of two or more
57resources.  For example, access to three printers could be administered by a
58semaphore created with an initial count of three.  When a task requires access
59to one of the printers, it issues the ``rtems_semaphore_obtain`` directive to
60obtain access to a printer.  If a printer is not currently available, the task
61can wait for a printer to become available or return immediately.  When the
62task has completed printing, it should issue the ``rtems_semaphore_release``
63directive to allow other tasks access to the printer.
64
65Task synchronization may be achieved by creating a semaphore with an initial
66count of zero.  One task waits for the arrival of another task by issuing a
67``rtems_semaphore_obtain`` directive when it reaches a synchronization point.
68The other task performs a corresponding ``rtems_semaphore_release`` operation
69when it reaches its synchronization point, thus unblocking the pending task.
70
71.. _Nested Resource Access:
72
73Nested Resource Access
74----------------------
75
76Deadlock occurs when a task owning a binary semaphore attempts to acquire that
77same semaphore and blocks as result.  Since the semaphore is allocated to a
78task, it cannot be deleted.  Therefore, the task that currently holds the
79semaphore and is also blocked waiting for that semaphore will never execute
80again.
81
82RTEMS addresses this problem by allowing the task holding the binary semaphore
83to obtain the same binary semaphore multiple times in a nested manner.  Each
84``rtems_semaphore_obtain`` must be accompanied with a
85``rtems_semaphore_release``.  The semaphore will only be made available for
86acquisition by other tasks when the outermost ``rtems_semaphore_obtain`` is
87matched with a ``rtems_semaphore_release``.
88
89Simple binary semaphores do not allow nested access and so can be used for task
90synchronization.
91
92.. _Priority Inversion:
93
94Priority Inversion
95------------------
96
97Priority inversion is a form of indefinite postponement which is common in
98multitasking, preemptive executives with shared resources.  Priority inversion
99occurs when a high priority tasks requests access to shared resource which is
100currently allocated to low priority task.  The high priority task must block
101until the low priority task releases the resource.  This problem is exacerbated
102when the low priority task is prevented from executing by one or more medium
103priority tasks.  Because the low priority task is not executing, it cannot
104complete its interaction with the resource and release that resource.  The high
105priority task is effectively prevented from executing by lower priority tasks.
106
107.. _Priority Inheritance:
108
109Priority Inheritance
110--------------------
111
112Priority inheritance is an algorithm that calls for the lower priority task
113holding a resource to have its priority increased to that of the highest
114priority task blocked waiting for that resource.  Each time a task blocks
115attempting to obtain the resource, the task holding the resource may have its
116priority increased.
117
118On SMP configurations, in case the task holding the resource and the task that
119blocks attempting to obtain the resource are in different scheduler instances,
120the priority of the holder is raised to the pseudo-interrupt priority (priority
121boosting).  The pseudo-interrupt priority is the highest priority.
122
123RTEMS supports priority inheritance for local, binary semaphores that use the
124priority task wait queue blocking discipline.  When a task of higher priority
125than the task holding the semaphore blocks, the priority of the task holding
126the semaphore is increased to that of the blocking task.  When the task holding
127the task completely releases the binary semaphore (i.e. not for a nested
128release), the holder's priority is restored to the value it had before any
129higher priority was inherited.
130
131The RTEMS implementation of the priority inheritance algorithm takes into
132account the scenario in which a task holds more than one binary semaphore.  The
133holding task will execute at the priority of the higher of the highest ceiling
134priority or at the priority of the highest priority task blocked waiting for
135any of the semaphores the task holds.  Only when the task releases ALL of the
136binary semaphores it holds will its priority be restored to the normal value.
137
138.. _Priority Ceiling:
139
140Priority Ceiling
141----------------
142
143Priority ceiling is an algorithm that calls for the lower priority task holding
144a resource to have its priority increased to that of the highest priority task
145which will EVER block waiting for that resource.  This algorithm addresses the
146problem of priority inversion although it avoids the possibility of changing
147the priority of the task holding the resource multiple times.  The priority
148ceiling algorithm will only change the priority of the task holding the
149resource a maximum of one time.  The ceiling priority is set at creation time
150and must be the priority of the highest priority task which will ever attempt
151to acquire that semaphore.
152
153RTEMS supports priority ceiling for local, binary semaphores that use the
154priority task wait queue blocking discipline.  When a task of lower priority
155than the ceiling priority successfully obtains the semaphore, its priority is
156raised to the ceiling priority.  When the task holding the task completely
157releases the binary semaphore (i.e. not for a nested release), the holder's
158priority is restored to the value it had before any higher priority was put
159into effect.
160
161The need to identify the highest priority task which will attempt to obtain a
162particular semaphore can be a difficult task in a large, complicated system.
163Although the priority ceiling algorithm is more efficient than the priority
164inheritance algorithm with respect to the maximum number of task priority
165changes which may occur while a task holds a particular semaphore, the priority
166inheritance algorithm is more forgiving in that it does not require this
167apriori information.
168
169The RTEMS implementation of the priority ceiling algorithm takes into account
170the scenario in which a task holds more than one binary semaphore.  The holding
171task will execute at the priority of the higher of the highest ceiling priority
172or at the priority of the highest priority task blocked waiting for any of the
173semaphores the task holds.  Only when the task releases ALL of the binary
174semaphores it holds will its priority be restored to the normal value.
175
176.. _Multiprocessor Resource Sharing Protocol:
177
178Multiprocessor Resource Sharing Protocol
179----------------------------------------
180
181The Multiprocessor Resource Sharing Protocol (MrsP) is defined in *A.  Burns
182and A.J.  Wellings, A Schedulability Compatible Multiprocessor Resource Sharing
183Protocol - MrsP, Proceedings of the 25th Euromicro Conference on Real-Time
184Systems (ECRTS 2013), July 2013*.  It is a generalization of the Priority
185Ceiling Protocol to SMP systems.  Each MrsP semaphore uses a ceiling priority
186per scheduler instance.  These ceiling priorities can be specified with
187``rtems_semaphore_set_priority()``.  A task obtaining or owning a MrsP
188semaphore will execute with the ceiling priority for its scheduler instance as
189specified by the MrsP semaphore object.  Tasks waiting to get ownership of a
190MrsP semaphore will not relinquish the processor voluntarily.  In case the
191owner of a MrsP semaphore gets preempted it can ask all tasks waiting for this
192semaphore to help out and temporarily borrow the right to execute on one of
193their assigned processors.
194
195.. _Building a Semaphore Attribute Set:
196
197Building a Semaphore Attribute Set
198----------------------------------
199
200In general, an attribute set is built by a bitwise OR of the desired attribute
201components.  The following table lists the set of valid semaphore attributes:
202
203.. list-table::
204 :class: rtems-table
205
206 * - ``RTEMS_FIFO``
207   - tasks wait by FIFO (default)
208 * - ``RTEMS_PRIORITY``
209   - tasks wait by priority
210 * - ``RTEMS_BINARY_SEMAPHORE``
211   - restrict values to 0 and 1
212 * - ``RTEMS_COUNTING_SEMAPHORE``
213   - no restriction on values (default)
214 * - ``RTEMS_SIMPLE_BINARY_SEMAPHORE``
215   - restrict values to 0 and 1, do not allow nested access, allow deletion of
216     locked semaphore.
217 * - ``RTEMS_NO_INHERIT_PRIORITY``
218   - do not use priority inheritance (default)
219 * - ``RTEMS_INHERIT_PRIORITY``
220   - use priority inheritance
221 * - ``RTEMS_NO_PRIORITY_CEILING``
222   - do not use priority ceiling (default)
223 * - ``RTEMS_PRIORITY_CEILING``
224   - use priority ceiling
225 * - ``RTEMS_NO_MULTIPROCESSOR_RESOURCE_SHARING``
226   - do not use Multiprocessor Resource Sharing Protocol (default)
227 * - ``RTEMS_MULTIPROCESSOR_RESOURCE_SHARING``
228   - use Multiprocessor Resource Sharing Protocol
229 * - ``RTEMS_LOCAL``
230   - local semaphore (default)
231 * - ``RTEMS_GLOBAL``
232   - global semaphore
233
234Attribute values are specifically designed to be mutually exclusive, therefore
235bitwise OR and addition operations are equivalent as long as each attribute
236appears exactly once in the component list.  An attribute listed as a default
237is not required to appear in the attribute list, although it is a good
238programming practice to specify default attributes.  If all defaults are
239desired, the attribute ``RTEMS_DEFAULT_ATTRIBUTES`` should be specified on this
240call.
241
242This example demonstrates the attribute_set parameter needed to create a local
243semaphore with the task priority waiting queue discipline.  The attribute_set
244parameter passed to the ``rtems_semaphore_create`` directive could be either
245``RTEMS_PRIORITY`` or ``RTEMS_LOCAL | RTEMS_PRIORITY``.  The attribute_set
246parameter can be set to ``RTEMS_PRIORITY`` because ``RTEMS_LOCAL`` is the
247default for all created tasks.  If a similar semaphore were to be known
248globally, then the attribute_set parameter would be ``RTEMS_GLOBAL |
249RTEMS_PRIORITY``.
250
251Some combinatinos of these attributes are invalid.  For example, priority
252ordered blocking discipline must be applied to a binary semaphore in order to
253use either the priority inheritance or priority ceiling functionality.  The
254following tree figure illustrates the valid combinations.
255
256.. figure:: ../images/c_user/semaphore_attributes.png
257         :width: 90%
258         :align: center
259         :alt: Semaphore Attributes
260
261.. _Building a SEMAPHORE_OBTAIN Option Set:
262
263Building a SEMAPHORE_OBTAIN Option Set
264--------------------------------------
265
266In general, an option is built by a bitwise OR of the desired option
267components.  The set of valid options for the ``rtems_semaphore_obtain``
268directive are listed in the following table:
269
270.. list-table::
271 :class: rtems-table
272
273 * - ``RTEMS_WAIT``
274   - task will wait for semaphore (default)
275 * - ``RTEMS_NO_WAIT``
276   - task should not wait
277
278Option values are specifically designed to be mutually exclusive, therefore
279bitwise OR and addition operations are equivalent as long as each attribute
280appears exactly once in the component list.  An option listed as a default is
281not required to appear in the list, although it is a good programming practice
282to specify default options.  If all defaults are desired, the option
283``RTEMS_DEFAULT_OPTIONS`` should be specified on this call.
284
285This example demonstrates the option parameter needed to poll for a semaphore.
286The option parameter passed to the ``rtems_semaphore_obtain`` directive should
287be ``RTEMS_NO_WAIT``.
288
289Operations
290==========
291
292.. _Creating a Semaphore:
293
294Creating a Semaphore
295--------------------
296
297The ``rtems_semaphore_create`` directive creates a binary or counting semaphore
298with a user-specified name as well as an initial count.  If a binary semaphore
299is created with a count of zero (0) to indicate that it has been allocated,
300then the task creating the semaphore is considered the current holder of the
301semaphore.  At create time the method for ordering waiting tasks in the
302semaphore's task wait queue (by FIFO or task priority) is specified.
303Additionally, the priority inheritance or priority ceiling algorithm may be
304selected for local, binary semaphores that use the priority task wait queue
305blocking discipline.  If the priority ceiling algorithm is selected, then the
306highest priority of any task which will attempt to obtain this semaphore must
307be specified.  RTEMS allocates a Semaphore Control Block (SMCB) from the SMCB
308free list.  This data structure is used by RTEMS to manage the newly created
309semaphore.  Also, a unique semaphore ID is generated and returned to the
310calling task.
311
312.. _Obtaining Semaphore IDs:
313
314Obtaining Semaphore IDs
315-----------------------
316
317When a semaphore is created, RTEMS generates a unique semaphore ID and assigns
318it to the created semaphore until it is deleted.  The semaphore ID may be
319obtained by either of two methods.  First, as the result of an invocation of
320the ``rtems_semaphore_create`` directive, the semaphore ID is stored in a user
321provided location.  Second, the semaphore ID may be obtained later using the
322``rtems_semaphore_ident`` directive.  The semaphore ID is used by other
323semaphore manager directives to access this semaphore.
324
325.. _Acquiring a Semaphore:
326
327Acquiring a Semaphore
328---------------------
329
330The ``rtems_semaphore_obtain`` directive is used to acquire the
331specified semaphore.  A simplified version of the ``rtems_semaphore_obtain``
332directive can be described as follows:
333
334    If the semaphore's count is greater than zero then decrement the
335    semaphore's count else wait for release of semaphore then return
336    SUCCESSFUL.
337
338When the semaphore cannot be immediately acquired, one of the following
339situations applies:
340
341- By default, the calling task will wait forever to acquire the semaphore.
342
343- Specifying ``RTEMS_NO_WAIT`` forces an immediate return with an error status
344  code.
345
346- Specifying a timeout limits the interval the task will wait before returning
347  with an error status code.
348
349If the task waits to acquire the semaphore, then it is placed in the
350semaphore's task wait queue in either FIFO or task priority order.  If the task
351blocked waiting for a binary semaphore using priority inheritance and the
352task's priority is greater than that of the task currently holding the
353semaphore, then the holding task will inherit the priority of the blocking
354task.  All tasks waiting on a semaphore are returned an error code when the
355semaphore is deleted.
356
357When a task successfully obtains a semaphore using priority ceiling and the
358priority ceiling for this semaphore is greater than that of the holder, then
359the holder's priority will be elevated.
360
361.. _Releasing a Semaphore:
362
363Releasing a Semaphore
364---------------------
365
366The ``rtems_semaphore_release`` directive is used to release the specified
367semaphore.  A simplified version of the ``rtems_semaphore_release`` directive
368can be described as follows:
369
370    If there sre no tasks are waiting on this semaphore then increment the
371    semaphore's count else assign semaphore to a waiting task and return
372    SUCCESSFUL.
373
374If this is the outermost release of a binary semaphore that uses priority
375inheritance or priority ceiling and the task does not currently hold any other
376binary semaphores, then the task performing the ``rtems_semaphore_release``
377will have its priority restored to its normal value.
378
379.. _Deleting a Semaphore:
380
381Deleting a Semaphore
382--------------------
383
384The ``rtems_semaphore_delete`` directive removes a semaphore from the system
385and frees its control block.  A semaphore can be deleted by any local task that
386knows the semaphore's ID.  As a result of this directive, all tasks blocked
387waiting to acquire the semaphore will be readied and returned a status code
388which indicates that the semaphore was deleted.  Any subsequent references to
389the semaphore's name and ID are invalid.
390
391Directives
392==========
393
394This section details the semaphore manager's directives.  A subsection is
395dedicated to each of this manager's directives and describes the calling
396sequence, related constants, usage, and status codes.
397
398.. _rtems_semaphore_create:
399
400SEMAPHORE_CREATE - Create a semaphore
401-------------------------------------
402.. index:: create a semaphore
403
404**CALLING SEQUENCE:**
405
406.. index:: rtems_semaphore_create
407
408.. code-block:: c
409
410    rtems_status_code rtems_semaphore_create(
411        rtems_name           name,
412        uint32_t             count,
413        rtems_attribute      attribute_set,
414        rtems_task_priority  priority_ceiling,
415        rtems_id            *id
416    );
417
418**DIRECTIVE STATUS CODES:**
419
420.. list-table::
421 :class: rtems-table
422
423 * - ``RTEMS_SUCCESSFUL``
424   - semaphore created successfully
425 * - ``RTEMS_INVALID_NAME``
426   - invalid semaphore name
427 * - ``RTEMS_INVALID_ADDRESS``
428   - ``id`` is NULL
429 * - ``RTEMS_TOO_MANY``
430   - too many semaphores created
431 * - ``RTEMS_NOT_DEFINED``
432   - invalid attribute set
433 * - ``RTEMS_INVALID_NUMBER``
434   - invalid starting count for binary semaphore
435 * - ``RTEMS_MP_NOT_CONFIGURED``
436   - multiprocessing not configured
437 * - ``RTEMS_TOO_MANY``
438   - too many global objects
439
440**DESCRIPTION:**
441
442This directive creates a semaphore which resides on the local node. The created
443semaphore has the user-defined name specified in name and the initial count
444specified in count.  For control and maintenance of the semaphore, RTEMS
445allocates and initializes a SMCB.  The RTEMS-assigned semaphore id is returned
446in id.  This semaphore id is used with other semaphore related directives to
447access the semaphore.
448
449Specifying PRIORITY in attribute_set causes tasks waiting for a semaphore to be
450serviced according to task priority.  When FIFO is selected, tasks are serviced
451in First In-First Out order.
452
453**NOTES:**
454
455This directive will not cause the calling task to be preempted.
456
457The priority inheritance and priority ceiling algorithms are only supported for
458local, binary semaphores that use the priority task wait queue blocking
459discipline.
460
461The following semaphore attribute constants are
462defined by RTEMS:
463
464.. list-table::
465 :class: rtems-table
466
467 * - ``RTEMS_FIFO``
468   - tasks wait by FIFO (default)
469 * - ``RTEMS_PRIORITY``
470   - tasks wait by priority
471 * - ``RTEMS_BINARY_SEMAPHORE``
472   - restrict values to 0 and 1
473 * - ``RTEMS_COUNTING_SEMAPHORE``
474   - no restriction on values (default)
475 * - ``RTEMS_SIMPLE_BINARY_SEMAPHORE``
476   - restrict values to 0 and 1, block on nested access, allow deletion of locked semaphore.
477 * - ``RTEMS_NO_INHERIT_PRIORITY``
478   - do not use priority inheritance (default)
479 * - ``RTEMS_INHERIT_PRIORITY``
480   - use priority inheritance
481 * - ``RTEMS_NO_PRIORITY_CEILING``
482   - do not use priority ceiling (default)
483 * - ``RTEMS_PRIORITY_CEILING``
484   - use priority ceiling
485 * - ``RTEMS_NO_MULTIPROCESSOR_RESOURCE_SHARING``
486   - do not use Multiprocessor Resource Sharing Protocol (default)
487 * - ``RTEMS_MULTIPROCESSOR_RESOURCE_SHARING``
488   - use Multiprocessor Resource Sharing Protocol
489 * - ``RTEMS_LOCAL``
490   - local semaphore (default)
491 * - ``RTEMS_GLOBAL``
492   - global semaphore
493
494Semaphores should not be made global unless remote tasks must interact with the
495created semaphore.  This is to avoid the system overhead incurred by the
496creation of a global semaphore.  When a global semaphore is created, the
497semaphore's name and id must be transmitted to every node in the system for
498insertion in the local copy of the global object table.
499
500Note that some combinations of attributes are not valid.  See the earlier
501discussion on this.
502
503The total number of global objects, including semaphores, is limited by the
504maximum_global_objects field in the Configuration Table.
505
506It is not allowed to create an initially locked MrsP semaphore and the
507``RTEMS_INVALID_NUMBER`` status code will be returned on SMP configurations in
508this case.  This prevents lock order reversal problems with the allocator
509mutex.
510
511.. _rtems_semaphore_ident:
512
513SEMAPHORE_IDENT - Get ID of a semaphore
514---------------------------------------
515.. index:: get ID of a semaphore
516.. index:: obtain ID of a semaphore
517
518**CALLING SEQUENCE:**
519
520.. index:: rtems_semaphore_ident
521
522.. code-block:: c
523
524    rtems_status_code rtems_semaphore_ident(
525        rtems_name  name,
526        uint32_t    node,
527        rtems_id   *id
528    );
529
530**DIRECTIVE STATUS CODES:**
531
532.. list-table::
533 :class: rtems-table
534
535 * - ``RTEMS_SUCCESSFUL``
536   - semaphore identified successfully
537 * - ``RTEMS_INVALID_NAME``
538   - semaphore name not found
539 * - ``RTEMS_INVALID_NODE``
540   - invalid node id
541
542**DESCRIPTION:**
543
544This directive obtains the semaphore id associated with the semaphore name.  If
545the semaphore name is not unique, then the semaphore id will match one of the
546semaphores with that name.  However, this semaphore id is not guaranteed to
547correspond to the desired semaphore.  The semaphore id is used by other
548semaphore related directives to access the semaphore.
549
550**NOTES:**
551
552This directive will not cause the running task to be preempted.
553
554If node is ``RTEMS_SEARCH_ALL_NODES``, all nodes are searched with the local
555node being searched first.  All other nodes are searched with the lowest
556numbered node searched first.
557
558If node is a valid node number which does not represent the local node, then
559only the semaphores exported by the designated node are searched.
560
561This directive does not generate activity on remote nodes.  It accesses only
562the local copy of the global object table.
563
564.. _rtems_semaphore_delete:
565
566SEMAPHORE_DELETE - Delete a semaphore
567-------------------------------------
568.. index:: delete a semaphore
569
570**CALLING SEQUENCE:**
571
572.. index:: rtems_semaphore_delete
573
574.. code-block:: c
575
576    rtems_status_code rtems_semaphore_delete(
577    rtems_id id
578    );
579
580**DIRECTIVE STATUS CODES:**
581
582.. list-table::
583 :class: rtems-table
584
585 * - ``RTEMS_SUCCESSFUL``
586   - semaphore deleted successfully
587 * - ``RTEMS_INVALID_ID``
588   - invalid semaphore id
589 * - ``RTEMS_RESOURCE_IN_USE``
590   - binary semaphore is in use
591 * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT``
592   - cannot delete remote semaphore
593
594**DESCRIPTION:**
595
596This directive deletes the semaphore specified by ``id``.  All tasks blocked
597waiting to acquire the semaphore will be readied and returned a status code
598which indicates that the semaphore was deleted.  The SMCB for this semaphore is
599reclaimed by RTEMS.
600
601**NOTES:**
602
603The calling task will be preempted if it is enabled by the task's execution
604mode and a higher priority local task is waiting on the deleted semaphore.  The
605calling task will NOT be preempted if all of the tasks that are waiting on the
606semaphore are remote tasks.
607
608The calling task does not have to be the task that created the semaphore.  Any
609local task that knows the semaphore id can delete the semaphore.
610
611When a global semaphore is deleted, the semaphore id must be transmitted to
612every node in the system for deletion from the local copy of the global object
613table.
614
615The semaphore must reside on the local node, even if the semaphore was created
616with the ``RTEMS_GLOBAL`` option.
617
618Proxies, used to represent remote tasks, are reclaimed when the semaphore is
619deleted.
620
621.. _rtems_semaphore_obtain:
622
623SEMAPHORE_OBTAIN - Acquire a semaphore
624--------------------------------------
625.. index:: obtain a semaphore
626.. index:: lock a semaphore
627
628**CALLING SEQUENCE:**
629
630.. index:: rtems_semaphore_obtain
631
632.. code-block:: c
633
634    rtems_status_code rtems_semaphore_obtain(
635        rtems_id        id,
636        rtems_option    option_set,
637        rtems_interval  timeout
638    );
639
640**DIRECTIVE STATUS CODES:**
641
642.. list-table::
643 :class: rtems-table
644
645 * - ``RTEMS_SUCCESSFUL``
646   - semaphore obtained successfully
647 * - ``RTEMS_UNSATISFIED``
648   - semaphore not available
649 * - ``RTEMS_TIMEOUT``
650   - timed out waiting for semaphore
651 * - ``RTEMS_OBJECT_WAS_DELETED``
652   - semaphore deleted while waiting
653 * - ``RTEMS_INVALID_ID``
654   - invalid semaphore id
655
656**DESCRIPTION:**
657
658This directive acquires the semaphore specified by id.  The ``RTEMS_WAIT`` and
659``RTEMS_NO_WAIT`` components of the options parameter indicate whether the
660calling task wants to wait for the semaphore to become available or return
661immediately if the semaphore is not currently available.  With either
662``RTEMS_WAIT`` or ``RTEMS_NO_WAIT``, if the current semaphore count is
663positive, then it is decremented by one and the semaphore is successfully
664acquired by returning immediately with a successful return code.
665
666If the calling task chooses to return immediately and the current semaphore
667count is zero or negative, then a status code is returned indicating that the
668semaphore is not available. If the calling task chooses to wait for a semaphore
669and the current semaphore count is zero or negative, then it is decremented by
670one and the calling task is placed on the semaphore's wait queue and blocked.
671If the semaphore was created with the ``RTEMS_PRIORITY`` attribute, then the
672calling task is inserted into the queue according to its priority.  However, if
673the semaphore was created with the ``RTEMS_FIFO`` attribute, then the calling
674task is placed at the rear of the wait queue.  If the binary semaphore was
675created with the ``RTEMS_INHERIT_PRIORITY`` attribute, then the priority of the
676task currently holding the binary semaphore is guaranteed to be greater than or
677equal to that of the blocking task.  If the binary semaphore was created with
678the ``RTEMS_PRIORITY_CEILING`` attribute, a task successfully obtains the
679semaphore, and the priority of that task is greater than the ceiling priority
680for this semaphore, then the priority of the task obtaining the semaphore is
681elevated to that of the ceiling.
682
683The timeout parameter specifies the maximum interval the calling task is
684willing to be blocked waiting for the semaphore.  If it is set to
685``RTEMS_NO_TIMEOUT``, then the calling task will wait forever.  If the
686semaphore is available or the ``RTEMS_NO_WAIT`` option component is set, then
687timeout is ignored.
688
689Deadlock situations are detected for MrsP semaphores and the
690``RTEMS_UNSATISFIED`` status code will be returned on SMP configurations in
691this case.
692
693**NOTES:**
694
695The following semaphore acquisition option constants are defined by RTEMS:
696
697.. list-table::
698 :class: rtems-table
699
700 * - ``RTEMS_WAIT``
701   - task will wait for semaphore (default)
702 * - ``RTEMS_NO_WAIT``
703   - task should not wait
704
705Attempting to obtain a global semaphore which does not reside on the local node
706will generate a request to the remote node to access the semaphore.  If the
707semaphore is not available and ``RTEMS_NO_WAIT`` was not specified, then the
708task must be blocked until the semaphore is released.  A proxy is allocated on
709the remote node to represent the task until the semaphore is released.
710
711A clock tick is required to support the timeout functionality of this
712directive.
713
714It is not allowed to obtain a MrsP semaphore more than once by one task at a
715time (nested access) and the ``RTEMS_UNSATISFIED`` status code will be returned
716on SMP configurations in this case.
717
718.. _rtems_semaphore_release:
719
720SEMAPHORE_RELEASE - Release a semaphore
721---------------------------------------
722.. index:: release a semaphore
723.. index:: unlock a semaphore
724
725**CALLING SEQUENCE:**
726
727.. index:: rtems_semaphore_release
728
729.. code-block:: c
730
731    rtems_status_code rtems_semaphore_release(
732        rtems_id id
733    );
734
735**DIRECTIVE STATUS CODES:**
736
737.. list-table::
738 :class: rtems-table
739
740 * - ``RTEMS_SUCCESSFUL``
741   - semaphore released successfully
742 * - ``RTEMS_INVALID_ID``
743   - invalid semaphore id
744 * - ``RTEMS_NOT_OWNER_OF_RESOURCE``
745   - calling task does not own semaphore
746 * - ``RTEMS_INCORRECT_STATE``
747   - invalid unlock order
748
749**DESCRIPTION:**
750
751This directive releases the semaphore specified by id.  The semaphore count is
752incremented by one.  If the count is zero or negative, then the first task on
753this semaphore's wait queue is removed and unblocked.  The unblocked task may
754preempt the running task if the running task's preemption mode is enabled and
755the unblocked task has a higher priority than the running task.
756
757**NOTES:**
758
759The calling task may be preempted if it causes a higher priority task to be
760made ready for execution.
761
762Releasing a global semaphore which does not reside on the local node will
763generate a request telling the remote node to release the semaphore.
764
765If the task to be unblocked resides on a different node from the semaphore,
766then the semaphore allocation is forwarded to the appropriate node, the waiting
767task is unblocked, and the proxy used to represent the task is reclaimed.
768
769The outermost release of a local, binary, priority inheritance or priority
770ceiling semaphore may result in the calling task having its priority lowered.
771This will occur if the calling task holds no other binary semaphores and it has
772inherited a higher priority.
773
774The MrsP semaphores must be released in the reversed obtain order, otherwise
775the ``RTEMS_INCORRECT_STATE`` status code will be returned on SMP
776configurations in this case.
777
778.. _rtems_semaphore_flush:
779
780SEMAPHORE_FLUSH - Unblock all tasks waiting on a semaphore
781----------------------------------------------------------
782.. index:: flush a semaphore
783.. index:: unblock all tasks waiting on a semaphore
784
785**CALLING SEQUENCE:**
786
787.. index:: rtems_semaphore_flush
788
789.. code-block:: c
790
791    rtems_status_code rtems_semaphore_flush(
792        rtems_id id
793    );
794
795**DIRECTIVE STATUS CODES:**
796
797.. list-table::
798 :class: rtems-table
799
800 * - ``RTEMS_SUCCESSFUL``
801   - semaphore released successfully
802 * - ``RTEMS_INVALID_ID``
803   - invalid semaphore id
804 * - ``RTEMS_NOT_DEFINED``
805   - operation not defined for the protocol ofthe semaphore
806 * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT``
807   - not supported for remote semaphores
808
809**DESCRIPTION:**
810
811This directive unblocks all tasks waiting on the semaphore specified by id.
812Since there are tasks blocked on the semaphore, the semaphore's count is not
813changed by this directive and thus is zero before and after this directive is
814executed.  Tasks which are unblocked as the result of this directive will
815return from the ``rtems_semaphore_obtain`` directive with a status code of
816``RTEMS_UNSATISFIED`` to indicate that the semaphore was not obtained.
817
818This directive may unblock any number of tasks.  Any of the unblocked tasks may
819preempt the running task if the running task's preemption mode is enabled and
820an unblocked task has a higher priority than the running task.
821
822**NOTES:**
823
824The calling task may be preempted if it causes a higher priority task to be
825made ready for execution.
826
827If the task to be unblocked resides on a different node from the semaphore,
828then the waiting task is unblocked, and the proxy used to represent the task is
829reclaimed.
830
831It is not allowed to flush a MrsP semaphore and the ``RTEMS_NOT_DEFINED``
832status code will be returned on SMP configurations in this case.
833
834.. _rtems_semaphore_set_priority:
835
836SEMAPHORE_SET_PRIORITY - Set priority by scheduler for a semaphore
837------------------------------------------------------------------
838.. index:: set priority by scheduler for a semaphore
839
840**CALLING SEQUENCE:**
841
842.. index:: rtems_semaphore_set_priority
843
844.. code-block:: c
845
846    rtems_status_code rtems_semaphore_set_priority(
847        rtems_id             semaphore_id,
848        rtems_id             scheduler_id,
849        rtems_task_priority  new_priority,
850        rtems_task_priority *old_priority
851    );
852
853**DIRECTIVE STATUS CODES:**
854
855.. list-table::
856 :class: rtems-table
857
858 * - ``RTEMS_SUCCESSFUL``
859   - successful operation
860 * - ``RTEMS_INVALID_ID``
861   - invalid semaphore or scheduler id
862 * - ``RTEMS_INVALID_ADDRESS``
863   - ``old_priority`` is NULL
864 * - ``RTEMS_INVALID_PRIORITY``
865   - invalid new priority value
866 * - ``RTEMS_NOT_DEFINED``
867   - operation not defined for the protocol ofthe semaphore
868 * - ``RTEMS_ILLEGAL_ON_REMOTE_OBJECT``
869   - not supported for remote semaphores
870
871**DESCRIPTION:**
872
873This directive sets the priority value with respect to the specified scheduler
874of a semaphore.
875
876The special priority value ``RTEMS_CURRENT_PRIORITY`` can be used to get the
877current priority value without changing it.
878
879The interpretation of the priority value depends on the protocol of the
880semaphore object.
881
882- The Multiprocessor Resource Sharing Protocol needs a ceiling priority per
883  scheduler instance.  This operation can be used to specify these priority
884  values.
885
886- For the Priority Ceiling Protocol the ceiling priority is used with this
887  operation.
888
889- For other protocols this operation is not defined.
890
891**EXAMPLE:**
892
893.. code-block:: c
894    :linenos:
895
896    #include <assert.h>
897    #include <stdlib.h>
898    #include <rtems.h>
899
900    #define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
901    #define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
902
903    static void Init(rtems_task_argument arg)
904    {
905        rtems_status_code   sc;
906        rtems_id            semaphore_id;
907        rtems_id            scheduler_a_id;
908        rtems_id            scheduler_b_id;
909        rtems_task_priority prio;
910
911        /* Get the scheduler identifiers */
912        sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id);
913        assert(sc == RTEMS_SUCCESSFUL);
914        sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id);
915        assert(sc == RTEMS_SUCCESSFUL);
916
917        /* Create a MrsP semaphore object */
918        sc = rtems_semaphore_create(
919            rtems_build_name('M', 'R', 'S', 'P'),
920            1,
921            RTEMS_MULTIPROCESSOR_RESOURCE_SHARING | RTEMS_BINARY_SEMAPHORE,
922            1,
923            &semaphore_id
924        );
925        assert(sc == RTEMS_SUCCESSFUL);
926
927        /*
928         * The ceiling priority values per scheduler are equal to the value specified
929         * for object creation.
930         */
931        prio = RTEMS_CURRENT_PRIORITY;
932        sc = rtems_semaphore_set_priority(semaphore_id, scheduler_a_id, prio, &prio);
933        assert(sc == RTEMS_SUCCESSFUL);
934        assert(prio == 1);
935
936        /* Check the old value and set a new ceiling priority for scheduler B */
937        prio = 2;
938        sc = rtems_semaphore_set_priority(semaphore_id, scheduler_b_id, prio, &prio);
939        assert(sc == RTEMS_SUCCESSFUL);
940        assert(prio == 1);
941
942        /* Check the ceiling priority values */
943        prio = RTEMS_CURRENT_PRIORITY;
944        sc = rtems_semaphore_set_priority(semaphore_id, scheduler_a_id, prio, &prio);
945        assert(sc == RTEMS_SUCCESSFUL);
946        assert(prio == 1);
947        prio = RTEMS_CURRENT_PRIORITY;
948        sc = rtems_semaphore_set_priority(semaphore_id, scheduler_b_id, prio, &prio);
949        assert(sc == RTEMS_SUCCESSFUL);
950        assert(prio == 2);
951        sc = rtems_semaphore_delete(semaphore_id);
952        assert(sc == RTEMS_SUCCESSFUL);
953        exit(0);
954    }
955
956    #define CONFIGURE_SMP_APPLICATION
957    #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
958    #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
959    #define CONFIGURE_MAXIMUM_TASKS 1
960    #define CONFIGURE_MAXIMUM_SEMAPHORES 1
961    #define CONFIGURE_MAXIMUM_MRSP_SEMAPHORES 1
962    #define CONFIGURE_SMP_MAXIMUM_PROCESSORS 2
963    #define CONFIGURE_SCHEDULER_SIMPLE_SMP
964
965    #include <rtems/scheduler.h>
966
967    RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
968    RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
969
970    #define CONFIGURE_SCHEDULER_CONTROLS \
971              RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHED_A), \
972              RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHED_B)
973    #define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
974              RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
975             RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY)
976    #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
977    #define CONFIGURE_INIT
978    #include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.