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