1 /* 2 * Copyright (c) 2019 Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * 10 * @brief public sys_sem APIs. 11 */ 12 13 #ifndef ZEPHYR_INCLUDE_SYS_SEM_H_ 14 #define ZEPHYR_INCLUDE_SYS_SEM_H_ 15 16 /* 17 * sys_sem exists in user memory working as counter semaphore for 18 * user mode thread when user mode enabled. When user mode isn't 19 * enabled, sys_sem behaves like k_sem. 20 */ 21 22 #include <zephyr/kernel.h> 23 #include <zephyr/sys/atomic.h> 24 #include <zephyr/types.h> 25 #include <zephyr/sys/iterable_sections.h> 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 /** 32 * sys_sem structure 33 */ 34 struct sys_sem { 35 #ifdef CONFIG_USERSPACE 36 struct k_futex futex; 37 int limit; 38 #else 39 struct k_sem kernel_sem; 40 #endif 41 }; 42 43 /** 44 * @defgroup user_semaphore_apis User mode semaphore APIs 45 * @ingroup kernel_apis 46 * @{ 47 */ 48 49 /** 50 * @brief Statically define and initialize a sys_sem 51 * 52 * The semaphore can be accessed outside the module where it is defined using: 53 * 54 * @code extern struct sys_sem <name>; @endcode 55 * 56 * Route this to memory domains using K_APP_DMEM(). 57 * 58 * @param _name Name of the semaphore. 59 * @param _initial_count Initial semaphore count. 60 * @param _count_limit Maximum permitted semaphore count. 61 */ 62 #ifdef CONFIG_USERSPACE 63 #define SYS_SEM_DEFINE(_name, _initial_count, _count_limit) \ 64 struct sys_sem _name = { \ 65 .futex = { _initial_count }, \ 66 .limit = _count_limit \ 67 }; \ 68 BUILD_ASSERT(((_count_limit) != 0) && \ 69 ((_initial_count) <= (_count_limit))) 70 #else 71 /* Stuff this in the section with the rest of the k_sem objects, since they 72 * are identical and can be treated as a k_sem in the boot initialization code 73 */ 74 #define SYS_SEM_DEFINE(_name, _initial_count, _count_limit) \ 75 STRUCT_SECTION_ITERABLE_ALTERNATE(k_sem, sys_sem, _name) = { \ 76 .kernel_sem = Z_SEM_INITIALIZER(_name.kernel_sem, \ 77 _initial_count, _count_limit) \ 78 }; \ 79 BUILD_ASSERT(((_count_limit) != 0) && \ 80 ((_initial_count) <= (_count_limit))) 81 #endif 82 83 /** 84 * @brief Initialize a semaphore. 85 * 86 * This routine initializes a semaphore instance, prior to its first use. 87 * 88 * @param sem Address of the semaphore. 89 * @param initial_count Initial semaphore count. 90 * @param limit Maximum permitted semaphore count. 91 * 92 * @retval 0 Initial success. 93 * @retval -EINVAL Bad parameters, the value of limit should be located in 94 * (0, INT_MAX] and initial_count shouldn't be greater than limit. 95 */ 96 int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, 97 unsigned int limit); 98 99 /** 100 * @brief Give a semaphore. 101 * 102 * This routine gives @a sem, unless the semaphore is already at its 103 * maximum permitted count. 104 * 105 * @param sem Address of the semaphore. 106 * 107 * @retval 0 Semaphore given. 108 * @retval -EINVAL Parameter address not recognized. 109 * @retval -EACCES Caller does not have enough access. 110 * @retval -EAGAIN Count reached Maximum permitted count and try again. 111 */ 112 int sys_sem_give(struct sys_sem *sem); 113 114 /** 115 * @brief Take a sys_sem. 116 * 117 * This routine takes @a sem. 118 * 119 * @param sem Address of the sys_sem. 120 * @param timeout Waiting period to take the sys_sem, 121 * or one of the special values K_NO_WAIT and K_FOREVER. 122 * 123 * @retval 0 sys_sem taken. 124 * @retval -EINVAL Parameter address not recognized. 125 * @retval -ETIMEDOUT Waiting period timed out. 126 * @retval -EACCES Caller does not have enough access. 127 */ 128 int sys_sem_take(struct sys_sem *sem, k_timeout_t timeout); 129 130 /** 131 * @brief Get sys_sem's value 132 * 133 * This routine returns the current value of @a sem. 134 * 135 * @param sem Address of the sys_sem. 136 * 137 * @return Current value of sys_sem. 138 */ 139 unsigned int sys_sem_count_get(struct sys_sem *sem); 140 141 /** 142 * @} 143 */ 144 145 #ifdef __cplusplus 146 } 147 #endif 148 149 #endif 150