1.. _semaphores_v2:
2
3Semaphores
4##########
5
6A :dfn:`semaphore` is a kernel object that implements a traditional
7counting semaphore.
8
9.. contents::
10    :local:
11    :depth: 2
12
13Concepts
14********
15
16Any number of semaphores can be defined (limited only by available RAM). Each
17semaphore is referenced by its memory address.
18
19A semaphore has the following key properties:
20
21* A **count** that indicates the number of times the semaphore can be taken.
22  A count of zero indicates that the semaphore is unavailable.
23
24* A **limit** that indicates the maximum value the semaphore's count
25  can reach.
26
27A semaphore must be initialized before it can be used. Its count must be set
28to a non-negative value that is less than or equal to its limit.
29
30A semaphore may be **given** by a thread or an ISR. Giving the semaphore
31increments its count, unless the count is already equal to the limit.
32
33A semaphore may be **taken** by a thread. Taking the semaphore
34decrements its count, unless the semaphore is unavailable (i.e. at zero).
35When a semaphore is unavailable a thread may choose to wait for it to be given.
36Any number of threads may wait on an unavailable semaphore simultaneously.
37When the semaphore is given, it is taken by the highest priority thread
38that has waited longest.
39
40.. note::
41    You may initialize a "full" semaphore (count equal to limit) to limit the number
42    of threads able to execute the critical section at the same time. You may also
43    initialize an empty semaphore (count equal to 0, with a limit greater than 0)
44    to create a gate through which no waiting thread may pass until the semaphore
45    is incremented. All standard use cases of the common semaphore are supported.
46
47.. note::
48    The kernel does allow an ISR to take a semaphore, however the ISR must
49    not attempt to wait if the semaphore is unavailable.
50
51Implementation
52**************
53
54Defining a Semaphore
55====================
56
57A semaphore is defined using a variable of type :c:struct:`k_sem`.
58It must then be initialized by calling :c:func:`k_sem_init`.
59
60The following code defines a semaphore, then configures it as a binary
61semaphore by setting its count to 0 and its limit to 1.
62
63.. code-block:: c
64
65    struct k_sem my_sem;
66
67    k_sem_init(&my_sem, 0, 1);
68
69Alternatively, a semaphore can be defined and initialized at compile time
70by calling :c:macro:`K_SEM_DEFINE`.
71
72The following code has the same effect as the code segment above.
73
74.. code-block:: c
75
76    K_SEM_DEFINE(my_sem, 0, 1);
77
78Giving a Semaphore
79==================
80
81A semaphore is given by calling :c:func:`k_sem_give`.
82
83The following code builds on the example above, and gives the semaphore to
84indicate that a unit of data is available for processing by a consumer thread.
85
86.. code-block:: c
87
88    void input_data_interrupt_handler(void *arg)
89    {
90        /* notify thread that data is available */
91        k_sem_give(&my_sem);
92
93        ...
94    }
95
96Taking a Semaphore
97==================
98
99A semaphore is taken by calling :c:func:`k_sem_take`.
100
101The following code builds on the example above, and waits up to 50 milliseconds
102for the semaphore to be given.
103A warning is issued if the semaphore is not obtained in time.
104
105.. code-block:: c
106
107    void consumer_thread(void)
108    {
109        ...
110
111        if (k_sem_take(&my_sem, K_MSEC(50)) != 0) {
112            printk("Input data not available!");
113        } else {
114            /* fetch available data */
115            ...
116        }
117        ...
118    }
119
120Suggested Uses
121**************
122
123Use a semaphore to control access to a set of resources by multiple threads.
124
125Use a semaphore to synchronize processing between a producing and consuming
126threads or ISRs.
127
128Configuration Options
129*********************
130
131Related configuration options:
132
133* None.
134
135API Reference
136**************
137
138.. doxygengroup:: semaphore_apis
139
140User Mode Semaphore API Reference
141*********************************
142
143The sys_sem exists in user memory working as counter semaphore for user mode
144thread when user mode enabled. When user mode isn't enabled, sys_sem behaves
145like k_sem.
146
147.. doxygengroup:: user_semaphore_apis
148