rtx_mutex.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  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: Mutex functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // OS Runtime Object Memory Usage
  27. #ifdef RTX_OBJ_MEM_USAGE
  28. osRtxObjectMemUsage_t osRtxMutexMemUsage \
  29. __attribute__((section(".data.os.mutex.obj"))) =
  30. { 0U, 0U, 0U };
  31. #endif
  32. // ==== Helper functions ====
  33. /// Verify that Mutex object pointer is valid.
  34. /// \param[in] mutex mutex object.
  35. /// \return true - valid, false - invalid.
  36. static bool_t IsMutexPtrValid (const os_mutex_t *mutex) {
  37. #ifdef RTX_OBJ_PTR_CHECK
  38. //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
  39. uint32_t cb_start = (uint32_t)&__os_mutex_cb_start__;
  40. uint32_t cb_length = (uint32_t)&__os_mutex_cb_length__;
  41. // Check the section boundaries
  42. if (((uint32_t)mutex - cb_start) >= cb_length) {
  43. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  44. return FALSE;
  45. }
  46. // Check the object alignment
  47. if ((((uint32_t)mutex - cb_start) % sizeof(os_mutex_t)) != 0U) {
  48. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  49. return FALSE;
  50. }
  51. #else
  52. // Check NULL pointer
  53. if (mutex == NULL) {
  54. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  55. return FALSE;
  56. }
  57. #endif
  58. return TRUE;
  59. }
  60. // ==== Library functions ====
  61. /// Release Mutex list when owner Thread terminates.
  62. /// \param[in] mutex_list mutex list.
  63. void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) {
  64. os_mutex_t *mutex;
  65. os_mutex_t *mutex_next;
  66. os_thread_t *thread;
  67. mutex = mutex_list;
  68. while (mutex != NULL) {
  69. mutex_next = mutex->owner_next;
  70. // Check if Mutex is Robust
  71. if ((mutex->attr & osMutexRobust) != 0U) {
  72. // Clear Lock counter
  73. mutex->lock = 0U;
  74. EvrRtxMutexReleased(mutex, 0U);
  75. // Check if Thread is waiting for a Mutex
  76. if (mutex->thread_list != NULL) {
  77. // Wakeup waiting Thread with highest Priority
  78. thread = osRtxThreadListGet(osRtxObject(mutex));
  79. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  80. // Thread is the new Mutex owner
  81. mutex->owner_thread = thread;
  82. mutex->owner_prev = NULL;
  83. mutex->owner_next = thread->mutex_list;
  84. if (thread->mutex_list != NULL) {
  85. thread->mutex_list->owner_prev = mutex;
  86. }
  87. thread->mutex_list = mutex;
  88. mutex->lock = 1U;
  89. EvrRtxMutexAcquired(mutex, 1U);
  90. }
  91. }
  92. mutex = mutex_next;
  93. }
  94. }
  95. /// Restore Mutex owner Thread priority.
  96. /// \param[in] mutex mutex object.
  97. /// \param[in] thread_wakeup thread wakeup object.
  98. void osRtxMutexOwnerRestore (const os_mutex_t *mutex, const os_thread_t *thread_wakeup) {
  99. const os_mutex_t *mutex0;
  100. os_thread_t *thread;
  101. const os_thread_t *thread0;
  102. int8_t priority;
  103. // Restore owner Thread priority
  104. if ((mutex->attr & osMutexPrioInherit) != 0U) {
  105. thread = mutex->owner_thread;
  106. priority = thread->priority_base;
  107. mutex0 = thread->mutex_list;
  108. // Check Mutexes owned by Thread
  109. do {
  110. if ((mutex0->attr & osMutexPrioInherit) != 0U) {
  111. // Check Threads waiting for Mutex
  112. thread0 = mutex0->thread_list;
  113. if (thread0 == thread_wakeup) {
  114. // Skip thread that is waken-up
  115. thread0 = thread0->thread_next;
  116. }
  117. if ((thread0 != NULL) && (thread0->priority > priority)) {
  118. // Higher priority Thread is waiting for Mutex
  119. priority = thread0->priority;
  120. }
  121. }
  122. mutex0 = mutex0->owner_next;
  123. } while (mutex0 != NULL);
  124. if (thread->priority != priority) {
  125. thread->priority = priority;
  126. osRtxThreadListSort(thread);
  127. }
  128. }
  129. }
  130. /// Unlock Mutex owner when mutex is deleted.
  131. /// \param[in] mutex mutex object.
  132. /// \return true - successful, false - not locked.
  133. static bool_t osRtxMutexOwnerUnlock (os_mutex_t *mutex) {
  134. const os_mutex_t *mutex0;
  135. os_thread_t *thread;
  136. int8_t priority;
  137. // Check if Mutex is locked
  138. if (mutex->lock == 0U) {
  139. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  140. return FALSE;
  141. }
  142. thread = mutex->owner_thread;
  143. // Remove Mutex from Thread owner list
  144. if (mutex->owner_next != NULL) {
  145. mutex->owner_next->owner_prev = mutex->owner_prev;
  146. }
  147. if (mutex->owner_prev != NULL) {
  148. mutex->owner_prev->owner_next = mutex->owner_next;
  149. } else {
  150. thread->mutex_list = mutex->owner_next;
  151. }
  152. // Restore owner Thread priority
  153. priority = thread->priority_base;
  154. mutex0 = thread->mutex_list;
  155. // Check Mutexes owned by Thread
  156. while (mutex0 != NULL) {
  157. if ((mutex0->attr & osMutexPrioInherit) != 0U) {
  158. if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
  159. // Higher priority Thread is waiting for Mutex
  160. priority = mutex0->thread_list->priority;
  161. }
  162. }
  163. mutex0 = mutex0->owner_next;
  164. }
  165. if (thread->priority != priority) {
  166. thread->priority = priority;
  167. osRtxThreadListSort(thread);
  168. }
  169. // Unblock waiting threads
  170. while (mutex->thread_list != NULL) {
  171. thread = osRtxThreadListGet(osRtxObject(mutex));
  172. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
  173. }
  174. mutex->lock = 0U;
  175. return TRUE;
  176. }
  177. /// Destroy a Mutex object.
  178. /// \param[in] mutex mutex object.
  179. static void osRtxMutexDestroy (os_mutex_t *mutex) {
  180. // Mark object as invalid
  181. mutex->id = osRtxIdInvalid;
  182. // Free object memory
  183. if ((mutex->flags & osRtxFlagSystemObject) != 0U) {
  184. #ifdef RTX_OBJ_PTR_CHECK
  185. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.mutex, mutex);
  186. #else
  187. if (osRtxInfo.mpi.mutex != NULL) {
  188. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.mutex, mutex);
  189. } else {
  190. (void)osRtxMemoryFree(osRtxInfo.mem.common, mutex);
  191. }
  192. #endif
  193. #ifdef RTX_OBJ_MEM_USAGE
  194. osRtxMutexMemUsage.cnt_free++;
  195. #endif
  196. }
  197. EvrRtxMutexDestroyed(mutex);
  198. }
  199. #ifdef RTX_SAFETY_CLASS
  200. /// Delete a Mutex safety class.
  201. /// \param[in] safety_class safety class.
  202. /// \param[in] mode safety mode.
  203. void osRtxMutexDeleteClass (uint32_t safety_class, uint32_t mode) {
  204. os_mutex_t *mutex;
  205. uint32_t length;
  206. //lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
  207. mutex = (os_mutex_t *)(uint32_t)&__os_mutex_cb_start__;
  208. length = (uint32_t)&__os_mutex_cb_length__;
  209. while (length >= sizeof(os_mutex_t)) {
  210. if ( (mutex->id == osRtxIdMutex) &&
  211. ((((mode & osSafetyWithSameClass) != 0U) &&
  212. ((mutex->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  213. (((mode & osSafetyWithLowerClass) != 0U) &&
  214. ((mutex->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)))) {
  215. (void)osRtxMutexOwnerUnlock(mutex);
  216. osRtxMutexDestroy(mutex);
  217. }
  218. length -= sizeof(os_mutex_t);
  219. mutex++;
  220. }
  221. }
  222. #endif
  223. // ==== Service Calls ====
  224. /// Create and Initialize a Mutex object.
  225. /// \note API identical to osMutexNew
  226. static osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) {
  227. os_mutex_t *mutex;
  228. #ifdef RTX_SAFETY_CLASS
  229. const os_thread_t *thread = osRtxThreadGetRunning();
  230. #endif
  231. uint32_t attr_bits;
  232. uint8_t flags;
  233. const char *name;
  234. // Process attributes
  235. if (attr != NULL) {
  236. name = attr->name;
  237. attr_bits = attr->attr_bits;
  238. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  239. mutex = attr->cb_mem;
  240. #ifdef RTX_SAFETY_CLASS
  241. if ((attr_bits & osSafetyClass_Valid) != 0U) {
  242. if ((thread != NULL) &&
  243. ((thread->attr >> osRtxAttrClass_Pos) <
  244. (uint8_t)((attr_bits & osSafetyClass_Msk) >> osSafetyClass_Pos))) {
  245. EvrRtxMutexError(NULL, (int32_t)osErrorSafetyClass);
  246. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  247. return NULL;
  248. }
  249. }
  250. #endif
  251. if (mutex != NULL) {
  252. if (!IsMutexPtrValid(mutex) || (attr->cb_size != sizeof(os_mutex_t))) {
  253. EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
  254. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  255. return NULL;
  256. }
  257. } else {
  258. if (attr->cb_size != 0U) {
  259. EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
  260. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  261. return NULL;
  262. }
  263. }
  264. } else {
  265. name = NULL;
  266. attr_bits = 0U;
  267. mutex = NULL;
  268. }
  269. // Allocate object memory if not provided
  270. if (mutex == NULL) {
  271. if (osRtxInfo.mpi.mutex != NULL) {
  272. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  273. mutex = osRtxMemoryPoolAlloc(osRtxInfo.mpi.mutex);
  274. #ifndef RTX_OBJ_PTR_CHECK
  275. } else {
  276. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  277. mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U);
  278. #endif
  279. }
  280. #ifdef RTX_OBJ_MEM_USAGE
  281. if (mutex != NULL) {
  282. uint32_t used;
  283. osRtxMutexMemUsage.cnt_alloc++;
  284. used = osRtxMutexMemUsage.cnt_alloc - osRtxMutexMemUsage.cnt_free;
  285. if (osRtxMutexMemUsage.max_used < used) {
  286. osRtxMutexMemUsage.max_used = used;
  287. }
  288. }
  289. #endif
  290. flags = osRtxFlagSystemObject;
  291. } else {
  292. flags = 0U;
  293. }
  294. if (mutex != NULL) {
  295. // Initialize control block
  296. mutex->id = osRtxIdMutex;
  297. mutex->flags = flags;
  298. mutex->attr = (uint8_t)(attr_bits & ~osRtxAttrClass_Msk);
  299. mutex->name = name;
  300. mutex->thread_list = NULL;
  301. mutex->owner_thread = NULL;
  302. mutex->owner_prev = NULL;
  303. mutex->owner_next = NULL;
  304. mutex->lock = 0U;
  305. #ifdef RTX_SAFETY_CLASS
  306. if ((attr_bits & osSafetyClass_Valid) != 0U) {
  307. mutex->attr |= (uint8_t)((attr_bits & osSafetyClass_Msk) >>
  308. (osSafetyClass_Pos - osRtxAttrClass_Pos));
  309. } else {
  310. // Inherit safety class from the running thread
  311. if (thread != NULL) {
  312. mutex->attr |= (uint8_t)(thread->attr & osRtxAttrClass_Msk);
  313. }
  314. }
  315. #endif
  316. EvrRtxMutexCreated(mutex, mutex->name);
  317. } else {
  318. EvrRtxMutexError(NULL, (int32_t)osErrorNoMemory);
  319. }
  320. return mutex;
  321. }
  322. /// Get name of a Mutex object.
  323. /// \note API identical to osMutexGetName
  324. static const char *svcRtxMutexGetName (osMutexId_t mutex_id) {
  325. os_mutex_t *mutex = osRtxMutexId(mutex_id);
  326. // Check parameters
  327. if (!IsMutexPtrValid(mutex) || (mutex->id != osRtxIdMutex)) {
  328. EvrRtxMutexGetName(mutex, NULL);
  329. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  330. return NULL;
  331. }
  332. EvrRtxMutexGetName(mutex, mutex->name);
  333. return mutex->name;
  334. }
  335. /// Acquire a Mutex or timeout if it is locked.
  336. /// \note API identical to osMutexAcquire
  337. static osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  338. os_mutex_t *mutex = osRtxMutexId(mutex_id);
  339. os_thread_t *thread;
  340. osStatus_t status;
  341. // Check running thread
  342. thread = osRtxThreadGetRunning();
  343. if (thread == NULL) {
  344. EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
  345. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  346. return osError;
  347. }
  348. // Check parameters
  349. if (!IsMutexPtrValid(mutex) || (mutex->id != osRtxIdMutex)) {
  350. EvrRtxMutexError(mutex, (int32_t)osErrorParameter);
  351. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  352. return osErrorParameter;
  353. }
  354. #ifdef RTX_SAFETY_CLASS
  355. // Check running thread safety class
  356. if ((thread->attr >> osRtxAttrClass_Pos) < (mutex->attr >> osRtxAttrClass_Pos)) {
  357. EvrRtxMutexError(mutex, (int32_t)osErrorSafetyClass);
  358. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  359. return osErrorSafetyClass;
  360. }
  361. #endif
  362. // Check if Mutex is not locked
  363. if (mutex->lock == 0U) {
  364. // Acquire Mutex
  365. mutex->owner_thread = thread;
  366. mutex->owner_prev = NULL;
  367. mutex->owner_next = thread->mutex_list;
  368. if (thread->mutex_list != NULL) {
  369. thread->mutex_list->owner_prev = mutex;
  370. }
  371. thread->mutex_list = mutex;
  372. mutex->lock = 1U;
  373. EvrRtxMutexAcquired(mutex, mutex->lock);
  374. status = osOK;
  375. } else {
  376. // Check if Mutex is recursive and running Thread is the owner
  377. if (((mutex->attr & osMutexRecursive) != 0U) && (mutex->owner_thread == thread)) {
  378. // Try to increment lock counter
  379. if (mutex->lock == osRtxMutexLockLimit) {
  380. EvrRtxMutexError(mutex, osRtxErrorMutexLockLimit);
  381. status = osErrorResource;
  382. } else {
  383. mutex->lock++;
  384. EvrRtxMutexAcquired(mutex, mutex->lock);
  385. status = osOK;
  386. }
  387. } else {
  388. // Check if timeout is specified
  389. if (timeout != 0U) {
  390. // Check if Priority inheritance protocol is enabled
  391. if ((mutex->attr & osMutexPrioInherit) != 0U) {
  392. // Raise priority of owner Thread if lower than priority of running Thread
  393. if (mutex->owner_thread->priority < thread->priority) {
  394. mutex->owner_thread->priority = thread->priority;
  395. osRtxThreadListSort(mutex->owner_thread);
  396. }
  397. }
  398. EvrRtxMutexAcquirePending(mutex, timeout);
  399. // Suspend current Thread
  400. if (osRtxThreadWaitEnter(osRtxThreadWaitingMutex, timeout)) {
  401. osRtxThreadListPut(osRtxObject(mutex), thread);
  402. } else {
  403. EvrRtxMutexAcquireTimeout(mutex);
  404. }
  405. status = osErrorTimeout;
  406. } else {
  407. EvrRtxMutexNotAcquired(mutex);
  408. status = osErrorResource;
  409. }
  410. }
  411. }
  412. return status;
  413. }
  414. /// Release a Mutex that was acquired by osMutexAcquire.
  415. /// \note API identical to osMutexRelease
  416. static osStatus_t svcRtxMutexRelease (osMutexId_t mutex_id) {
  417. os_mutex_t *mutex = osRtxMutexId(mutex_id);
  418. const os_mutex_t *mutex0;
  419. os_thread_t *thread;
  420. int8_t priority;
  421. // Check running thread
  422. thread = osRtxThreadGetRunning();
  423. if (thread == NULL) {
  424. EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
  425. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  426. return osError;
  427. }
  428. // Check parameters
  429. if (!IsMutexPtrValid(mutex) || (mutex->id != osRtxIdMutex)) {
  430. EvrRtxMutexError(mutex, (int32_t)osErrorParameter);
  431. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  432. return osErrorParameter;
  433. }
  434. // Check if Mutex is not locked
  435. if (mutex->lock == 0U) {
  436. EvrRtxMutexError(mutex, osRtxErrorMutexNotLocked);
  437. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  438. return osErrorResource;
  439. }
  440. // Check if running Thread is not the owner
  441. if (mutex->owner_thread != thread) {
  442. EvrRtxMutexError(mutex, osRtxErrorMutexNotOwned);
  443. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  444. return osErrorResource;
  445. }
  446. // Decrement Lock counter
  447. mutex->lock--;
  448. EvrRtxMutexReleased(mutex, mutex->lock);
  449. // Check Lock counter
  450. if (mutex->lock == 0U) {
  451. // Remove Mutex from Thread owner list
  452. if (mutex->owner_next != NULL) {
  453. mutex->owner_next->owner_prev = mutex->owner_prev;
  454. }
  455. if (mutex->owner_prev != NULL) {
  456. mutex->owner_prev->owner_next = mutex->owner_next;
  457. } else {
  458. thread->mutex_list = mutex->owner_next;
  459. }
  460. // Restore running Thread priority
  461. priority = thread->priority_base;
  462. mutex0 = thread->mutex_list;
  463. // Check mutexes owned by running Thread
  464. while (mutex0 != NULL) {
  465. if ((mutex0->attr & osMutexPrioInherit) != 0U) {
  466. if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
  467. // Higher priority Thread is waiting for Mutex
  468. priority = mutex0->thread_list->priority;
  469. }
  470. }
  471. mutex0 = mutex0->owner_next;
  472. }
  473. thread->priority = priority;
  474. // Check if Thread is waiting for a Mutex
  475. if (mutex->thread_list != NULL) {
  476. // Wakeup waiting Thread with highest Priority
  477. thread = osRtxThreadListGet(osRtxObject(mutex));
  478. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  479. // Thread is the new Mutex owner
  480. mutex->owner_thread = thread;
  481. mutex->owner_prev = NULL;
  482. mutex->owner_next = thread->mutex_list;
  483. if (thread->mutex_list != NULL) {
  484. thread->mutex_list->owner_prev = mutex;
  485. }
  486. thread->mutex_list = mutex;
  487. mutex->lock = 1U;
  488. EvrRtxMutexAcquired(mutex, 1U);
  489. }
  490. osRtxThreadDispatch(NULL);
  491. }
  492. return osOK;
  493. }
  494. /// Get Thread which owns a Mutex object.
  495. /// \note API identical to osMutexGetOwner
  496. static osThreadId_t svcRtxMutexGetOwner (osMutexId_t mutex_id) {
  497. os_mutex_t *mutex = osRtxMutexId(mutex_id);
  498. // Check parameters
  499. if (!IsMutexPtrValid(mutex) || (mutex->id != osRtxIdMutex)) {
  500. EvrRtxMutexGetOwner(mutex, NULL);
  501. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  502. return NULL;
  503. }
  504. // Check if Mutex is not locked
  505. if (mutex->lock == 0U) {
  506. EvrRtxMutexGetOwner(mutex, NULL);
  507. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  508. return NULL;
  509. }
  510. EvrRtxMutexGetOwner(mutex, mutex->owner_thread);
  511. return mutex->owner_thread;
  512. }
  513. /// Delete a Mutex object.
  514. /// \note API identical to osMutexDelete
  515. static osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id) {
  516. os_mutex_t *mutex = osRtxMutexId(mutex_id);
  517. #ifdef RTX_SAFETY_CLASS
  518. const os_thread_t *thread;
  519. #endif
  520. // Check parameters
  521. if (!IsMutexPtrValid(mutex) || (mutex->id != osRtxIdMutex)) {
  522. EvrRtxMutexError(mutex, (int32_t)osErrorParameter);
  523. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  524. return osErrorParameter;
  525. }
  526. #ifdef RTX_SAFETY_CLASS
  527. // Check running thread safety class
  528. thread = osRtxThreadGetRunning();
  529. if ((thread != NULL) &&
  530. ((thread->attr >> osRtxAttrClass_Pos) < (mutex->attr >> osRtxAttrClass_Pos))) {
  531. EvrRtxMutexError(mutex, (int32_t)osErrorSafetyClass);
  532. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  533. return osErrorSafetyClass;
  534. }
  535. #endif
  536. // Unlock the mutex owner
  537. if (osRtxMutexOwnerUnlock(mutex)) {
  538. osRtxThreadDispatch(NULL);
  539. }
  540. osRtxMutexDestroy(mutex);
  541. return osOK;
  542. }
  543. // Service Calls definitions
  544. //lint ++flb "Library Begin" [MISRA Note 11]
  545. SVC0_1(MutexNew, osMutexId_t, const osMutexAttr_t *)
  546. SVC0_1(MutexGetName, const char *, osMutexId_t)
  547. SVC0_2(MutexAcquire, osStatus_t, osMutexId_t, uint32_t)
  548. SVC0_1(MutexRelease, osStatus_t, osMutexId_t)
  549. SVC0_1(MutexGetOwner, osThreadId_t, osMutexId_t)
  550. SVC0_1(MutexDelete, osStatus_t, osMutexId_t)
  551. //lint --flb "Library End"
  552. // ==== Public API ====
  553. /// Create and Initialize a Mutex object.
  554. osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
  555. osMutexId_t mutex_id;
  556. EvrRtxMutexNew(attr);
  557. if (IsException() || IsIrqMasked()) {
  558. EvrRtxMutexError(NULL, (int32_t)osErrorISR);
  559. mutex_id = NULL;
  560. } else {
  561. mutex_id = __svcMutexNew(attr);
  562. }
  563. return mutex_id;
  564. }
  565. /// Get name of a Mutex object.
  566. const char *osMutexGetName (osMutexId_t mutex_id) {
  567. const char *name;
  568. if (IsException() || IsIrqMasked()) {
  569. name = svcRtxMutexGetName(mutex_id);
  570. } else {
  571. name = __svcMutexGetName(mutex_id);
  572. }
  573. return name;
  574. }
  575. /// Acquire a Mutex or timeout if it is locked.
  576. osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  577. osStatus_t status;
  578. EvrRtxMutexAcquire(mutex_id, timeout);
  579. if (IsException() || IsIrqMasked()) {
  580. EvrRtxMutexError(mutex_id, (int32_t)osErrorISR);
  581. status = osErrorISR;
  582. } else {
  583. status = __svcMutexAcquire(mutex_id, timeout);
  584. }
  585. return status;
  586. }
  587. /// Release a Mutex that was acquired by \ref osMutexAcquire.
  588. osStatus_t osMutexRelease (osMutexId_t mutex_id) {
  589. osStatus_t status;
  590. EvrRtxMutexRelease(mutex_id);
  591. if (IsException() || IsIrqMasked()) {
  592. EvrRtxMutexError(mutex_id, (int32_t)osErrorISR);
  593. status = osErrorISR;
  594. } else {
  595. status = __svcMutexRelease(mutex_id);
  596. }
  597. return status;
  598. }
  599. /// Get Thread which owns a Mutex object.
  600. osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
  601. osThreadId_t thread;
  602. if (IsException() || IsIrqMasked()) {
  603. EvrRtxMutexGetOwner(mutex_id, NULL);
  604. thread = NULL;
  605. } else {
  606. thread = __svcMutexGetOwner(mutex_id);
  607. }
  608. return thread;
  609. }
  610. /// Delete a Mutex object.
  611. osStatus_t osMutexDelete (osMutexId_t mutex_id) {
  612. osStatus_t status;
  613. EvrRtxMutexDelete(mutex_id);
  614. if (IsException() || IsIrqMasked()) {
  615. EvrRtxMutexError(mutex_id, (int32_t)osErrorISR);
  616. status = osErrorISR;
  617. } else {
  618. status = __svcMutexDelete(mutex_id);
  619. }
  620. return status;
  621. }