summaryrefslogtreecommitdiffstats
path: root/doc/user/sem.t
blob: cd4791adf0f2d92fad992846ac26a9cf4299e5d7 (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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
@c
@c  COPYRIGHT (c) 1988-1998.
@c  On-Line Applications Research Corporation (OAR).
@c  All rights reserved.
@c
@c  $Id$
@c

@chapter Semaphore Manager

@section Introduction

The semaphore manager utilizes standard Dijkstra
counting semaphores to provide synchronization and mutual
exclusion capabilities.  The directives provided by the
semaphore manager are:

@itemize @bullet
@item @code{@value{DIRPREFIX}semaphore_create} -  Create a semaphore
@item @code{@value{DIRPREFIX}semaphore_ident} - Get ID of a semaphore
@item @code{@value{DIRPREFIX}semaphore_delete} - Delete a semaphore
@item @code{@value{DIRPREFIX}semaphore_obtain} - Acquire a semaphore
@item @code{@value{DIRPREFIX}semaphore_release} - Release a semaphore
@end itemize

@section Background

A semaphore can be viewed as a protected variable
whose value can be modified only with the
@code{@value{DIRPREFIX}semaphore_create},
@code{@value{DIRPREFIX}semaphore_obtain}, and
@code{@value{DIRPREFIX}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 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.  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 @code{@value{DIRPREFIX}semaphore_obtain}
directive to prevent other tasks from entering the critical section.  
Upon exit from the critical section, the task must issue the
@code{@value{DIRPREFIX}semaphore_release} directive to
allow another task to execute the critical section.

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 @code{@value{DIRPREFIX}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 @code{@value{DIRPREFIX}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 @code{@value{DIRPREFIX}semaphore_obtain}
directive when it reaches a synchronization point.  The other task
performs a corresponding @code{@value{DIRPREFIX}semaphore_release}
operation when it reaches its synchronization point, thus unblocking
the pending task.

@subsection 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
@code{@value{DIRPREFIX}semaphore_obtain} must be accompanied with a
@code{@value{DIRPREFIX}semaphore_release}.  The semaphore will
only be made available for acquisition by other tasks when the
outermost @code{@value{DIRPREFIX}semaphore_obtain} is matched with
a @code{@value{DIRPREFIX}semaphore_release}.


@subsection Priority Inversion

Priority inversion is a form of indefinite
postponement which is common in multitasking, preemptive
executives with shared resources.  Priority inversion occurs
when a high priority tasks requests access to shared resource
which is currently allocated to low priority task.  The high
priority task must block until the low priority task releases
the resource.  This problem is exacerbated when the low priority
task is prevented from executing by one or more medium priority
tasks.  Because the low priority task is not executing, it
cannot complete its interaction with the resource and release
that resource.  The high priority task is effectively prevented
from executing by lower priority tasks.

@subsection Priority Inheritance

Priority inheritance is an algorithm that calls for
the lower priority task holding a resource to have its priority
increased to that of the highest priority task blocked waiting
for that resource.  Each time a task blocks attempting to obtain
the resource, the task holding the resource may have its
priority increased.

RTEMS supports priority inheritance for local, binary
semaphores that use the priority task wait queue blocking
discipline.   When a task of higher priority than the task
holding the semaphore blocks, the priority of the task holding
the semaphore is increased to that of the blocking task.  When
the task holding the task completely releases the binary
semaphore (i.e. not for a nested release), the holder's priority
is restored to the value it had before any higher priority was
inherited.

The RTEMS implementation of the priority inheritance
algorithm takes into account the scenario in which a task holds
more than one binary semaphore.  The holding task will execute
at the priority of the higher of the highest ceiling priority or
at the priority of the highest priority task blocked waiting for
any of the semaphores the task holds.  Only when the task
releases ALL of the binary semaphores it holds will its priority
be restored to the normal value.

@subsection Priority Ceiling

Priority ceiling is an algorithm that calls for the
lower priority task holding a resource to have its priority
increased to that of the highest priority task which will EVER
block waiting for that resource.  This algorithm addresses the
problem of priority inversion although it avoids the possibility
of changing the priority of the task holding the resource
multiple times.  The priority ceiling algorithm will only change
the priority of the task holding the resource a maximum of one
time.  The ceiling priority is set at creation time and must be
the priority of the highest priority task which will ever
attempt to acquire that semaphore.

RTEMS supports priority ceiling for local, binary
semaphores that use the priority task wait queue blocking
discipline.   When a task of lower priority than the ceiling
priority successfully obtains the semaphore, its priority is
raised to the ceiling priority.  When the task holding the task
completely releases the binary semaphore (i.e. not for a nested
release), the holder's priority is restored to the value it had
before any higher priority was put into effect.

The need to identify the highest priority task which
will attempt to obtain a particular semaphore can be a difficult
task in a large, complicated system.  Although the priority
ceiling algorithm is more efficient than the priority
inheritance algorithm with respect to the maximum number of task
priority changes which may occur while a task holds a particular
semaphore, the priority inheritance algorithm is more forgiving
in that it does not require this apriori information.

The RTEMS implementation of the priority ceiling
algorithm takes into account the scenario in which a task holds
more than one binary semaphore.  The holding task will execute
at the priority of the higher of the highest ceiling priority or
at the priority of the highest priority task blocked waiting for
any of the semaphores the task holds.  Only when the task
releases ALL of the binary semaphores it holds will its priority
be restored to the normal value.

@subsection 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:

@itemize @bullet
@item @code{@value{RPREFIX}FIFO} - tasks wait by FIFO (default)

@item @code{@value{RPREFIX}PRIORITY} - tasks wait by priority

@item @code{@value{RPREFIX}BINARY_SEMAPHORE} - restrict values to
0 and 1 (default)

@item @code{@value{RPREFIX}COUNTING_SEMAPHORE} - no restriction on values

@item @code{@value{RPREFIX}NO_INHERIT_PRIORITY} - do not use priority
inheritance (default)

@item @code{@value{RPREFIX}INHERIT_PRIORITY} - use priority inheritance

@item @code{@value{RPREFIX}PRIORITY_CEILING} - use priority ceiling

@item @code{@value{RPREFIX}NO_PRIORITY_CEILING} - do not use priority
ceiling (default)

@item @code{@value{RPREFIX}LOCAL} - local task (default)

@item @code{@value{RPREFIX}GLOBAL} - global task
@end itemize

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
@code{@value{RPREFIX}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 @code{@value{DIRPREFIX}semaphore_create} directive could be either
@code{@value{RPREFIX}PRIORITY} or
@code{@value{RPREFIX}LOCAL @value{OR} @value{RPREFIX}PRIORITY}.  
The attribute_set parameter can be set to @code{@value{RPREFIX}PRIORITY}
because @code{@value{RPREFIX}LOCAL} is the default for all created tasks.  If a
similar semaphore were to be known globally, then the
attribute_set parameter would be
@code{@value{RPREFIX}GLOBAL @value{OR} @value{RPREFIX}PRIORITY}.

@subsection 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
@code{@value{DIRPREFIX}semaphore_obtain} directive are listed
in the following table:

@itemize @bullet
@item @code{@value{RPREFIX}WAIT} - task will wait for semaphore (default)
@item @code{@value{RPREFIX}NO_WAIT} - task should not wait
@end itemize

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 @code{@value{RPREFIX}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
@code{@value{DIRPREFIX}semaphore_obtain}
directive should be @code{@value{RPREFIX}NO_WAIT}.

@section Operations

@subsection Creating a Semaphore

The @code{@value{DIRPREFIX}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.

@subsection 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
@code{@value{DIRPREFIX}semaphore_create} directive, the
semaphore ID is stored in a user provided location.  Second,
the semaphore ID may be obtained later using the
@code{@value{DIRPREFIX}semaphore_ident} directive.  The semaphore ID is
used by other semaphore manager directives to access this
semaphore.

@subsection Acquiring a Semaphore

The @code{@value{DIRPREFIX}semaphore_obtain} directive is used to acquire the
specified semaphore.  A simplified version of the
@code{@value{DIRPREFIX}semaphore_obtain} directive can be described as follows:

@example
if semaphore's count is greater than zero
   then decrement semaphore's count
   else wait for release of semaphore

return SUCCESSFUL
@end example

When the semaphore cannot be immediately acquired,
one of the following situations applies:

@itemize @bullet
@item By default, the calling task will wait forever to
acquire the semaphore.

@item Specifying @code{@value{RPREFIX}NO_WAIT} forces an immediate return with an
error status code.

@item Specifying a timeout limits the interval the task will
wait before returning with an error status code.
@end itemize

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.

@subsection Releasing a Semaphore

The @code{@value{DIRPREFIX}semaphore_release} directive is used to release
the specified semaphore.  A simplified version of the
@code{@value{DIRPREFIX}semaphore_release} directive can be described as follows:

@example
if no tasks are waiting on this semaphore
   then increment semaphore's count
   else assign semaphore to a waiting task

return SUCCESSFUL
@end example

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 @code{@value{DIRPREFIX}semaphore_release}
will have its priority restored to its normal value.

@subsection Deleting a Semaphore

The @code{@value{DIRPREFIX}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.

@section 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.

@page
@subsection SEMAPHORE_CREATE - Create a semaphore

@subheading CALLING SEQUENCE:

@ifset is-C
@c @findex rtems_semaphore_create
@example
rtems_status_code rtems_semaphore_create(
  rtems_name           name,
  rtems_unsigned32     count,
  rtems_attribute      attribute_set,
  rtems_task_priority  priority_ceiling,
  rtems_id            *id
);
@end example
@end ifset

@ifset is-Ada
@example
procedure Semaphore_Create (
   Name          : in     RTEMS.Name;
   Count         : in     RTEMS.Unsigned32;
   Attribute_Set : in     RTEMS.Attribute;
   ID            :    out RTEMS.ID;
   Result        :    out RTEMS.Status_Codes
);
@end example
@end ifset

@subheading DIRECTIVE STATUS CODES:
@code{@value{RPREFIX}SUCCESSFUL} - semaphore created successfully@*
@code{@value{RPREFIX}INVALID_NAME} - invalid task name@*
@code{@value{RPREFIX}TOO_MANY} - too many semaphores created@*
@code{@value{RPREFIX}NOT_DEFINED} - invalid attribute set@*
@code{@value{RPREFIX}INVALID_NUMBER} - invalid starting count for binary semaphore@*
@code{@value{RPREFIX}MP_NOT_CONFIGURED} - multiprocessing not configured@*
@code{@value{RPREFIX}TOO_MANY} - too many global objects

@subheading 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.

@subheading NOTES:

This directive will not cause the calling task to be
preempted.

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:

@itemize @bullet
@item @code{@value{RPREFIX}FIFO} - tasks wait by FIFO (default)

@item @code{@value{RPREFIX}PRIORITY} - tasks wait by priority

@item @code{@value{RPREFIX}BINARY_SEMAPHORE} - restrict values to
0 and 1 (default)

@item @code{@value{RPREFIX}COUNTING_SEMAPHORE} - no restriction on values

@item @code{@value{RPREFIX}NO_INHERIT_PRIORITY} - do not use priority
inheritance (default)

@item @code{@value{RPREFIX}INHERIT_PRIORITY} - use priority inheritance

@item @code{@value{RPREFIX}PRIORITY_CEILING} - use priority ceiling

@item @code{@value{RPREFIX}NO_PRIORITY_CEILING} - do not use priority
ceiling (default)

@item @code{@value{RPREFIX}LOCAL} - local task (default)

@item @code{@value{RPREFIX}GLOBAL} - global task
@end itemize

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.

The total number of global objects, including
semaphores, is limited by the maximum_global_objects field in
the Configuration Table.

@page
@subsection SEMAPHORE_IDENT - Get ID of a semaphore

@subheading CALLING SEQUENCE:

@ifset is-C
@c @findex rtems_semaphore_ident
@example
rtems_status_code rtems_semaphore_ident(
  rtems_name        name,
  rtems_unsigned32  node,
  rtems_id         *id
);
@end example
@end ifset

@ifset is-Ada
@example
procedure Semaphore_Ident (
   Name   : in     RTEMS.Name;
   Node   : in     RTEMS.Unsigned32;
   ID     :    out RTEMS.ID;
   Result :    out RTEMS.Status_Codes
);
@end example
@end ifset

@subheading DIRECTIVE STATUS CODES:
@code{@value{RPREFIX}SUCCESSFUL} - semaphore identified successfully@*
@code{@value{RPREFIX}INVALID_NAME} - semaphore name not found@*
@code{@value{RPREFIX}INVALID_NODE} - invalid node id

@subheading 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.

@subheading NOTES:

This directive will not cause the running task to be
preempted.

If node is @code{@value{RPREFIX}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.

@page
@subsection SEMAPHORE_DELETE - Delete a semaphore

@subheading CALLING SEQUENCE:

@ifset is-C
@c @findex rtems_semaphore_delete
@example
rtems_status_code rtems_semaphore_delete(
  rtems_id id
);
@end example
@end ifset

@ifset is-Ada
@example
procedure Semaphore_Delete (
   ID     : in     RTEMS.ID;
   Result :    out RTEMS.Status_Codes
);
@end example
@end ifset

@subheading DIRECTIVE STATUS CODES:
@code{@value{RPREFIX}SUCCESSFUL} -  semaphore deleted successfully@*
@code{@value{RPREFIX}INVALID_ID} - invalid semaphore id@*
@code{@value{RPREFIX}ILLEGAL_ON_REMOTE_OBJECT} - cannot delete remote semaphore@*
@code{@value{RPREFIX}RESOURCE_IN_USE} - binary semaphore is in use

@subheading DESCRIPTION:

This directive deletes the semaphore specified by @code{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.

@subheading NOTES:

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 @code{@value{RPREFIX}GLOBAL} option.

Proxies, used to represent remote tasks, are
reclaimed when the semaphore is deleted.

@page
@subsection SEMAPHORE_OBTAIN - Acquire a semaphore

@subheading CALLING SEQUENCE:

@ifset is-C
@c @findex rtems_semaphore_obtain
@example
rtems_status_code rtems_semaphore_obtain(
  rtems_id         id,
  rtems_unsigned32 option_set,
  rtems_interval   timeout
);
@end example
@end ifset

@ifset is-Ada
@example
procedure Semaphore_Obtain (
   ID         : in     RTEMS.ID;
   Option_Set : in     RTEMS.Option;
   Timeout    : in     RTEMS.Interval;
   Result     :    out RTEMS.Status_Codes
);
@end example
@end ifset

@subheading DIRECTIVE STATUS CODES:
@code{@value{RPREFIX}SUCCESSFUL} - semaphore obtained successfully@*
@code{@value{RPREFIX}UNSATISFIED} - semaphore not available@*
@code{@value{RPREFIX}TIMEOUT} - timed out waiting for semaphore@*
@code{@value{RPREFIX}OBJECT_WAS_DELETED} - semaphore deleted while waiting@*
@code{@value{RPREFIX}INVALID_ID} - invalid semaphore id

@subheading DESCRIPTION:

This directive acquires the semaphore specified by
id.  The @code{@value{RPREFIX}WAIT} and @code{@value{RPREFIX}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 @code{@value{RPREFIX}WAIT} or
@code{@value{RPREFIX}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 @code{@value{RPREFIX}PRIORITY} attribute, then the calling task is
inserted into the queue according to its priority.  However, if
the semaphore was created with the @code{@value{RPREFIX}FIFO} attribute, then the
calling task is placed at the rear of the wait queue.  If the
binary semaphore was created with the @code{@value{RPREFIX}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 @code{@value{RPREFIX}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 @code{@value{RPREFIX}NO_TIMEOUT}, then the calling task
will wait forever.  If the semaphore is available or the @code{@value{RPREFIX}NO_WAIT}
option component is set, then timeout is ignored.

@subheading NOTES:
The following semaphore acquisition option constants
are defined by RTEMS:

@itemize @bullet
@item @code{@value{RPREFIX}WAIT} - task will wait for semaphore (default)
@item @code{@value{RPREFIX}NO_WAIT} - task should not wait
@end itemize

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
@code{@value{RPREFIX}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.

@page
@subsection SEMAPHORE_RELEASE - Release a semaphore

@subheading CALLING SEQUENCE:

@ifset is-C
@c @findex rtems_semaphore_release
@example
rtems_status_code rtems_semaphore_release(
  rtems_id id
);
@end example
@end ifset

@ifset is-Ada
@example
procedure Semaphore_Release (
   ID     : in     RTEMS.ID;
   Result :    out RTEMS.Status_Codes
);
@end example
@end ifset

@subheading DIRECTIVE STATUS CODES:
@code{@value{RPREFIX}SUCCESSFUL} - semaphore released successfully@*
@code{@value{RPREFIX}INVALID_ID} - invalid semaphore id@*
@code{@value{RPREFIX}NOT_OWNER_OF_RESOURCE} - calling task does not own semaphore

@subheading 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.

@subheading 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.