rtx_semaphore.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /*
  2. * Copyright (c) 2013-2023 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: Semaphore functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // OS Runtime Object Memory Usage
  27. #ifdef RTX_OBJ_MEM_USAGE
  28. osRtxObjectMemUsage_t osRtxSemaphoreMemUsage \
  29. __attribute__((section(".data.os.semaphore.obj"))) =
  30. { 0U, 0U, 0U };
  31. #endif
  32. // ==== Helper functions ====
  33. /// Decrement Semaphore tokens.
  34. /// \param[in] semaphore semaphore object.
  35. /// \return 1 - success, 0 - failure.
  36. static uint32_t SemaphoreTokenDecrement (os_semaphore_t *semaphore) {
  37. #if (EXCLUSIVE_ACCESS == 0)
  38. uint32_t primask = __get_PRIMASK();
  39. #endif
  40. uint32_t ret;
  41. #if (EXCLUSIVE_ACCESS == 0)
  42. __disable_irq();
  43. if (semaphore->tokens != 0U) {
  44. semaphore->tokens--;
  45. ret = 1U;
  46. } else {
  47. ret = 0U;
  48. }
  49. if (primask == 0U) {
  50. __enable_irq();
  51. }
  52. #else
  53. if (atomic_dec16_nz(&semaphore->tokens) != 0U) {
  54. ret = 1U;
  55. } else {
  56. ret = 0U;
  57. }
  58. #endif
  59. return ret;
  60. }
  61. /// Increment Semaphore tokens.
  62. /// \param[in] semaphore semaphore object.
  63. /// \return 1 - success, 0 - failure.
  64. static uint32_t SemaphoreTokenIncrement (os_semaphore_t *semaphore) {
  65. #if (EXCLUSIVE_ACCESS == 0)
  66. uint32_t primask = __get_PRIMASK();
  67. #endif
  68. uint32_t ret;
  69. #if (EXCLUSIVE_ACCESS == 0)
  70. __disable_irq();
  71. if (semaphore->tokens < semaphore->max_tokens) {
  72. semaphore->tokens++;
  73. ret = 1U;
  74. } else {
  75. ret = 0U;
  76. }
  77. if (primask == 0U) {
  78. __enable_irq();
  79. }
  80. #else
  81. if (atomic_inc16_lt(&semaphore->tokens, semaphore->max_tokens) < semaphore->max_tokens) {
  82. ret = 1U;
  83. } else {
  84. ret = 0U;
  85. }
  86. #endif
  87. return ret;
  88. }
  89. /// Verify that Semaphore object pointer is valid.
  90. /// \param[in] semaphore semaphore object.
  91. /// \return true - valid, false - invalid.
  92. static bool_t IsSemaphorePtrValid (const os_semaphore_t *semaphore) {
  93. #ifdef RTX_OBJ_PTR_CHECK
  94. //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
  95. uint32_t cb_start = (uint32_t)&__os_semaphore_cb_start__;
  96. uint32_t cb_length = (uint32_t)&__os_semaphore_cb_length__;
  97. // Check the section boundaries
  98. if (((uint32_t)semaphore - cb_start) >= cb_length) {
  99. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  100. return FALSE;
  101. }
  102. // Check the object alignment
  103. if ((((uint32_t)semaphore - cb_start) % sizeof(os_semaphore_t)) != 0U) {
  104. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  105. return FALSE;
  106. }
  107. #else
  108. // Check NULL pointer
  109. if (semaphore == NULL) {
  110. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  111. return FALSE;
  112. }
  113. #endif
  114. return TRUE;
  115. }
  116. // ==== Library functions ====
  117. /// Destroy a Semaphore object.
  118. /// \param[in] semaphore semaphore object.
  119. static void osRtxSemaphoreDestroy (os_semaphore_t *semaphore) {
  120. // Mark object as invalid
  121. semaphore->id = osRtxIdInvalid;
  122. // Free object memory
  123. if ((semaphore->flags & osRtxFlagSystemObject) != 0U) {
  124. #ifdef RTX_OBJ_PTR_CHECK
  125. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.semaphore, semaphore);
  126. #else
  127. if (osRtxInfo.mpi.semaphore != NULL) {
  128. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.semaphore, semaphore);
  129. } else {
  130. (void)osRtxMemoryFree(osRtxInfo.mem.common, semaphore);
  131. }
  132. #endif
  133. #ifdef RTX_OBJ_MEM_USAGE
  134. osRtxSemaphoreMemUsage.cnt_free++;
  135. #endif
  136. }
  137. EvrRtxSemaphoreDestroyed(semaphore);
  138. }
  139. #ifdef RTX_SAFETY_CLASS
  140. /// Delete a Semaphore safety class.
  141. /// \param[in] safety_class safety class.
  142. /// \param[in] mode safety mode.
  143. void osRtxSemaphoreDeleteClass (uint32_t safety_class, uint32_t mode) {
  144. os_semaphore_t *semaphore;
  145. os_thread_t *thread;
  146. uint32_t length;
  147. //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
  148. semaphore = (os_semaphore_t *)(uint32_t)&__os_semaphore_cb_start__;
  149. length = (uint32_t)&__os_semaphore_cb_length__;
  150. while (length >= sizeof(os_semaphore_t)) {
  151. if ( (semaphore->id == osRtxIdSemaphore) &&
  152. ((((mode & osSafetyWithSameClass) != 0U) &&
  153. ((semaphore->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  154. (((mode & osSafetyWithLowerClass) != 0U) &&
  155. ((semaphore->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)))) {
  156. while (semaphore->thread_list != NULL) {
  157. thread = osRtxThreadListGet(osRtxObject(semaphore));
  158. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
  159. }
  160. osRtxSemaphoreDestroy(semaphore);
  161. }
  162. length -= sizeof(os_semaphore_t);
  163. semaphore++;
  164. }
  165. }
  166. #endif
  167. // ==== Post ISR processing ====
  168. /// Semaphore post ISR processing.
  169. /// \param[in] semaphore semaphore object.
  170. static void osRtxSemaphorePostProcess (os_semaphore_t *semaphore) {
  171. os_thread_t *thread;
  172. // Check if Thread is waiting for a token
  173. if (semaphore->thread_list != NULL) {
  174. // Try to acquire token
  175. if (SemaphoreTokenDecrement(semaphore) != 0U) {
  176. // Wakeup waiting Thread with highest Priority
  177. thread = osRtxThreadListGet(osRtxObject(semaphore));
  178. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  179. EvrRtxSemaphoreAcquired(semaphore, semaphore->tokens);
  180. }
  181. }
  182. }
  183. // ==== Service Calls ====
  184. /// Create and Initialize a Semaphore object.
  185. /// \note API identical to osSemaphoreNew
  186. static osSemaphoreId_t svcRtxSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
  187. os_semaphore_t *semaphore;
  188. #ifdef RTX_SAFETY_CLASS
  189. const os_thread_t *thread = osRtxThreadGetRunning();
  190. uint32_t attr_bits;
  191. #endif
  192. uint8_t flags;
  193. const char *name;
  194. // Check parameters
  195. if ((max_count == 0U) || (max_count > osRtxSemaphoreTokenLimit) || (initial_count > max_count)) {
  196. EvrRtxSemaphoreError(NULL, (int32_t)osErrorParameter);
  197. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  198. return NULL;
  199. }
  200. // Process attributes
  201. if (attr != NULL) {
  202. name = attr->name;
  203. #ifdef RTX_SAFETY_CLASS
  204. attr_bits = attr->attr_bits;
  205. #endif
  206. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  207. semaphore = attr->cb_mem;
  208. #ifdef RTX_SAFETY_CLASS
  209. if ((attr_bits & osSafetyClass_Valid) != 0U) {
  210. if ((thread != NULL) &&
  211. ((thread->attr >> osRtxAttrClass_Pos) <
  212. (uint8_t)((attr_bits & osSafetyClass_Msk) >> osSafetyClass_Pos))) {
  213. EvrRtxSemaphoreError(NULL, (int32_t)osErrorSafetyClass);
  214. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  215. return NULL;
  216. }
  217. }
  218. #endif
  219. if (semaphore != NULL) {
  220. if (!IsSemaphorePtrValid(semaphore) || (attr->cb_size != sizeof(os_semaphore_t))) {
  221. EvrRtxSemaphoreError(NULL, osRtxErrorInvalidControlBlock);
  222. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  223. return NULL;
  224. }
  225. } else {
  226. if (attr->cb_size != 0U) {
  227. EvrRtxSemaphoreError(NULL, osRtxErrorInvalidControlBlock);
  228. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  229. return NULL;
  230. }
  231. }
  232. } else {
  233. name = NULL;
  234. #ifdef RTX_SAFETY_CLASS
  235. attr_bits = 0U;
  236. #endif
  237. semaphore = NULL;
  238. }
  239. // Allocate object memory if not provided
  240. if (semaphore == NULL) {
  241. if (osRtxInfo.mpi.semaphore != NULL) {
  242. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  243. semaphore = osRtxMemoryPoolAlloc(osRtxInfo.mpi.semaphore);
  244. #ifndef RTX_OBJ_PTR_CHECK
  245. } else {
  246. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  247. semaphore = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_semaphore_t), 1U);
  248. #endif
  249. }
  250. #ifdef RTX_OBJ_MEM_USAGE
  251. if (semaphore != NULL) {
  252. uint32_t used;
  253. osRtxSemaphoreMemUsage.cnt_alloc++;
  254. used = osRtxSemaphoreMemUsage.cnt_alloc - osRtxSemaphoreMemUsage.cnt_free;
  255. if (osRtxSemaphoreMemUsage.max_used < used) {
  256. osRtxSemaphoreMemUsage.max_used = used;
  257. }
  258. }
  259. #endif
  260. flags = osRtxFlagSystemObject;
  261. } else {
  262. flags = 0U;
  263. }
  264. if (semaphore != NULL) {
  265. // Initialize control block
  266. semaphore->id = osRtxIdSemaphore;
  267. semaphore->flags = flags;
  268. semaphore->attr = 0U;
  269. semaphore->name = name;
  270. semaphore->thread_list = NULL;
  271. semaphore->tokens = (uint16_t)initial_count;
  272. semaphore->max_tokens = (uint16_t)max_count;
  273. #ifdef RTX_SAFETY_CLASS
  274. if ((attr_bits & osSafetyClass_Valid) != 0U) {
  275. semaphore->attr |= (uint8_t)((attr_bits & osSafetyClass_Msk) >>
  276. (osSafetyClass_Pos - osRtxAttrClass_Pos));
  277. } else {
  278. // Inherit safety class from the running thread
  279. if (thread != NULL) {
  280. semaphore->attr |= (uint8_t)(thread->attr & osRtxAttrClass_Msk);
  281. }
  282. }
  283. #endif
  284. // Register post ISR processing function
  285. osRtxInfo.post_process.semaphore = osRtxSemaphorePostProcess;
  286. EvrRtxSemaphoreCreated(semaphore, semaphore->name);
  287. } else {
  288. EvrRtxSemaphoreError(NULL,(int32_t)osErrorNoMemory);
  289. }
  290. return semaphore;
  291. }
  292. /// Get name of a Semaphore object.
  293. /// \note API identical to osSemaphoreGetName
  294. static const char *svcRtxSemaphoreGetName (osSemaphoreId_t semaphore_id) {
  295. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  296. // Check parameters
  297. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  298. EvrRtxSemaphoreGetName(semaphore, NULL);
  299. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  300. return NULL;
  301. }
  302. EvrRtxSemaphoreGetName(semaphore, semaphore->name);
  303. return semaphore->name;
  304. }
  305. /// Acquire a Semaphore token or timeout if no tokens are available.
  306. /// \note API identical to osSemaphoreAcquire
  307. static osStatus_t svcRtxSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
  308. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  309. #ifdef RTX_SAFETY_CLASS
  310. const os_thread_t *thread;
  311. #endif
  312. osStatus_t status;
  313. // Check parameters
  314. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  315. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorParameter);
  316. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  317. return osErrorParameter;
  318. }
  319. #ifdef RTX_SAFETY_CLASS
  320. // Check running thread safety class
  321. thread = osRtxThreadGetRunning();
  322. if ((thread != NULL) &&
  323. ((thread->attr >> osRtxAttrClass_Pos) < (semaphore->attr >> osRtxAttrClass_Pos))) {
  324. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorSafetyClass);
  325. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  326. return osErrorSafetyClass;
  327. }
  328. #endif
  329. // Try to acquire token
  330. if (SemaphoreTokenDecrement(semaphore) != 0U) {
  331. EvrRtxSemaphoreAcquired(semaphore, semaphore->tokens);
  332. status = osOK;
  333. } else {
  334. // No token available
  335. if (timeout != 0U) {
  336. EvrRtxSemaphoreAcquirePending(semaphore, timeout);
  337. // Suspend current Thread
  338. if (osRtxThreadWaitEnter(osRtxThreadWaitingSemaphore, timeout)) {
  339. osRtxThreadListPut(osRtxObject(semaphore), osRtxThreadGetRunning());
  340. } else {
  341. EvrRtxSemaphoreAcquireTimeout(semaphore);
  342. }
  343. status = osErrorTimeout;
  344. } else {
  345. EvrRtxSemaphoreNotAcquired(semaphore);
  346. status = osErrorResource;
  347. }
  348. }
  349. return status;
  350. }
  351. /// Release a Semaphore token that was acquired by osSemaphoreAcquire.
  352. /// \note API identical to osSemaphoreRelease
  353. static osStatus_t svcRtxSemaphoreRelease (osSemaphoreId_t semaphore_id) {
  354. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  355. os_thread_t *thread;
  356. osStatus_t status;
  357. // Check parameters
  358. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  359. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorParameter);
  360. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  361. return osErrorParameter;
  362. }
  363. #ifdef RTX_SAFETY_CLASS
  364. // Check running thread safety class
  365. thread = osRtxThreadGetRunning();
  366. if ((thread != NULL) &&
  367. ((thread->attr >> osRtxAttrClass_Pos) < (semaphore->attr >> osRtxAttrClass_Pos))) {
  368. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorSafetyClass);
  369. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  370. return osErrorSafetyClass;
  371. }
  372. #endif
  373. // Check if Thread is waiting for a token
  374. if (semaphore->thread_list != NULL) {
  375. EvrRtxSemaphoreReleased(semaphore, semaphore->tokens);
  376. // Wakeup waiting Thread with highest Priority
  377. thread = osRtxThreadListGet(osRtxObject(semaphore));
  378. osRtxThreadWaitExit(thread, (uint32_t)osOK, TRUE);
  379. EvrRtxSemaphoreAcquired(semaphore, semaphore->tokens);
  380. status = osOK;
  381. } else {
  382. // Try to release token
  383. if (SemaphoreTokenIncrement(semaphore) != 0U) {
  384. EvrRtxSemaphoreReleased(semaphore, semaphore->tokens);
  385. status = osOK;
  386. } else {
  387. EvrRtxSemaphoreError(semaphore, osRtxErrorSemaphoreCountLimit);
  388. status = osErrorResource;
  389. }
  390. }
  391. return status;
  392. }
  393. /// Get current Semaphore token count.
  394. /// \note API identical to osSemaphoreGetCount
  395. static uint32_t svcRtxSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
  396. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  397. // Check parameters
  398. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  399. EvrRtxSemaphoreGetCount(semaphore, 0U);
  400. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  401. return 0U;
  402. }
  403. EvrRtxSemaphoreGetCount(semaphore, semaphore->tokens);
  404. return semaphore->tokens;
  405. }
  406. /// Delete a Semaphore object.
  407. /// \note API identical to osSemaphoreDelete
  408. static osStatus_t svcRtxSemaphoreDelete (osSemaphoreId_t semaphore_id) {
  409. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  410. os_thread_t *thread;
  411. // Check parameters
  412. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  413. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorParameter);
  414. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  415. return osErrorParameter;
  416. }
  417. #ifdef RTX_SAFETY_CLASS
  418. // Check running thread safety class
  419. thread = osRtxThreadGetRunning();
  420. if ((thread != NULL) &&
  421. ((thread->attr >> osRtxAttrClass_Pos) < (semaphore->attr >> osRtxAttrClass_Pos))) {
  422. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorSafetyClass);
  423. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  424. return osErrorSafetyClass;
  425. }
  426. #endif
  427. // Unblock waiting threads
  428. if (semaphore->thread_list != NULL) {
  429. do {
  430. thread = osRtxThreadListGet(osRtxObject(semaphore));
  431. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
  432. } while (semaphore->thread_list != NULL);
  433. osRtxThreadDispatch(NULL);
  434. }
  435. osRtxSemaphoreDestroy(semaphore);
  436. return osOK;
  437. }
  438. // Service Calls definitions
  439. //lint ++flb "Library Begin" [MISRA Note 11]
  440. SVC0_3(SemaphoreNew, osSemaphoreId_t, uint32_t, uint32_t, const osSemaphoreAttr_t *)
  441. SVC0_1(SemaphoreGetName, const char *, osSemaphoreId_t)
  442. SVC0_2(SemaphoreAcquire, osStatus_t, osSemaphoreId_t, uint32_t)
  443. SVC0_1(SemaphoreRelease, osStatus_t, osSemaphoreId_t)
  444. SVC0_1(SemaphoreGetCount, uint32_t, osSemaphoreId_t)
  445. SVC0_1(SemaphoreDelete, osStatus_t, osSemaphoreId_t)
  446. //lint --flb "Library End"
  447. // ==== ISR Calls ====
  448. /// Acquire a Semaphore token or timeout if no tokens are available.
  449. /// \note API identical to osSemaphoreAcquire
  450. __STATIC_INLINE
  451. osStatus_t isrRtxSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
  452. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  453. osStatus_t status;
  454. // Check parameters
  455. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore) || (timeout != 0U)) {
  456. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorParameter);
  457. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  458. return osErrorParameter;
  459. }
  460. // Try to acquire token
  461. if (SemaphoreTokenDecrement(semaphore) != 0U) {
  462. EvrRtxSemaphoreAcquired(semaphore, semaphore->tokens);
  463. status = osOK;
  464. } else {
  465. // No token available
  466. EvrRtxSemaphoreNotAcquired(semaphore);
  467. status = osErrorResource;
  468. }
  469. return status;
  470. }
  471. /// Release a Semaphore token that was acquired by osSemaphoreAcquire.
  472. /// \note API identical to osSemaphoreRelease
  473. __STATIC_INLINE
  474. osStatus_t isrRtxSemaphoreRelease (osSemaphoreId_t semaphore_id) {
  475. os_semaphore_t *semaphore = osRtxSemaphoreId(semaphore_id);
  476. osStatus_t status;
  477. // Check parameters
  478. if (!IsSemaphorePtrValid(semaphore) || (semaphore->id != osRtxIdSemaphore)) {
  479. EvrRtxSemaphoreError(semaphore, (int32_t)osErrorParameter);
  480. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  481. return osErrorParameter;
  482. }
  483. // Try to release token
  484. if (SemaphoreTokenIncrement(semaphore) != 0U) {
  485. // Register post ISR processing
  486. osRtxPostProcess(osRtxObject(semaphore));
  487. EvrRtxSemaphoreReleased(semaphore, semaphore->tokens);
  488. status = osOK;
  489. } else {
  490. EvrRtxSemaphoreError(semaphore, osRtxErrorSemaphoreCountLimit);
  491. status = osErrorResource;
  492. }
  493. return status;
  494. }
  495. // ==== Public API ====
  496. /// Create and Initialize a Semaphore object.
  497. osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
  498. osSemaphoreId_t semaphore_id;
  499. EvrRtxSemaphoreNew(max_count, initial_count, attr);
  500. if (IsException() || IsIrqMasked()) {
  501. EvrRtxSemaphoreError(NULL, (int32_t)osErrorISR);
  502. semaphore_id = NULL;
  503. } else {
  504. semaphore_id = __svcSemaphoreNew(max_count, initial_count, attr);
  505. }
  506. return semaphore_id;
  507. }
  508. /// Get name of a Semaphore object.
  509. const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id) {
  510. const char *name;
  511. if (IsException() || IsIrqMasked()) {
  512. name = svcRtxSemaphoreGetName(semaphore_id);
  513. } else {
  514. name = __svcSemaphoreGetName(semaphore_id);
  515. }
  516. return name;
  517. }
  518. /// Acquire a Semaphore token or timeout if no tokens are available.
  519. osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
  520. osStatus_t status;
  521. EvrRtxSemaphoreAcquire(semaphore_id, timeout);
  522. if (IsException() || IsIrqMasked()) {
  523. status = isrRtxSemaphoreAcquire(semaphore_id, timeout);
  524. } else {
  525. status = __svcSemaphoreAcquire(semaphore_id, timeout);
  526. }
  527. return status;
  528. }
  529. /// Release a Semaphore token that was acquired by osSemaphoreAcquire.
  530. osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) {
  531. osStatus_t status;
  532. EvrRtxSemaphoreRelease(semaphore_id);
  533. if (IsException() || IsIrqMasked()) {
  534. status = isrRtxSemaphoreRelease(semaphore_id);
  535. } else {
  536. status = __svcSemaphoreRelease(semaphore_id);
  537. }
  538. return status;
  539. }
  540. /// Get current Semaphore token count.
  541. uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
  542. uint32_t count;
  543. if (IsException() || IsIrqMasked()) {
  544. count = svcRtxSemaphoreGetCount(semaphore_id);
  545. } else {
  546. count = __svcSemaphoreGetCount(semaphore_id);
  547. }
  548. return count;
  549. }
  550. /// Delete a Semaphore object.
  551. osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
  552. osStatus_t status;
  553. EvrRtxSemaphoreDelete(semaphore_id);
  554. if (IsException() || IsIrqMasked()) {
  555. EvrRtxSemaphoreError(semaphore_id, (int32_t)osErrorISR);
  556. status = osErrorISR;
  557. } else {
  558. status = __svcSemaphoreDelete(semaphore_id);
  559. }
  560. return status;
  561. }