rtx_mutex.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. * Copyright (c) 2013-2017 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. // ==== Library functions ====
  27. /// Release Mutex list when owner Thread terminates.
  28. /// \param[in] mutex mutex object.
  29. /// \return 1 - success, 0 - failure.
  30. void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) {
  31. os_mutex_t *mutex;
  32. os_thread_t *thread;
  33. mutex = mutex_list;
  34. while (mutex) {
  35. mutex_list = mutex->owner_next;
  36. // Check if Mutex is Robust
  37. if (mutex->attr & osMutexRobust) {
  38. // Clear Lock counter
  39. mutex->lock = 0U;
  40. EvrRtxMutexReleased(mutex, 0U);
  41. // Check if Thread is waiting for a Mutex
  42. if (mutex->thread_list != NULL) {
  43. // Wakeup waiting Thread with highest Priority
  44. thread = osRtxThreadListGet((os_object_t*)mutex);
  45. osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
  46. // Thread is the new Mutex owner
  47. mutex->owner_thread = thread;
  48. mutex->owner_next = thread->mutex_list;
  49. mutex->owner_prev = NULL;
  50. thread->mutex_list = mutex;
  51. mutex->lock = 1U;
  52. EvrRtxMutexAcquired(mutex, 1U);
  53. }
  54. }
  55. mutex = mutex_list;
  56. }
  57. }
  58. // ==== Service Calls ====
  59. // Service Calls definitions
  60. SVC0_1M(MutexNew, osMutexId_t, const osMutexAttr_t *)
  61. SVC0_1 (MutexGetName, const char *, osMutexId_t)
  62. SVC0_2 (MutexAcquire, osStatus_t, osMutexId_t, uint32_t)
  63. SVC0_1 (MutexRelease, osStatus_t, osMutexId_t)
  64. SVC0_1 (MutexGetOwner, osThreadId_t, osMutexId_t)
  65. SVC0_1 (MutexDelete, osStatus_t, osMutexId_t)
  66. /// Create and Initialize a Mutex object.
  67. /// \note API identical to osMutexNew
  68. osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) {
  69. os_mutex_t *mutex;
  70. uint32_t attr_bits;
  71. uint8_t flags;
  72. const char *name;
  73. // Process attributes
  74. if (attr != NULL) {
  75. name = attr->name;
  76. attr_bits = attr->attr_bits;
  77. mutex = attr->cb_mem;
  78. if (mutex != NULL) {
  79. if (((uint32_t)mutex & 3U) || (attr->cb_size < sizeof(os_mutex_t))) {
  80. EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
  81. return NULL;
  82. }
  83. } else {
  84. if (attr->cb_size != 0U) {
  85. EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
  86. return NULL;
  87. }
  88. }
  89. } else {
  90. name = NULL;
  91. attr_bits = 0U;
  92. mutex = NULL;
  93. }
  94. // Allocate object memory if not provided
  95. if (mutex == NULL) {
  96. if (osRtxInfo.mpi.mutex != NULL) {
  97. mutex = osRtxMemoryPoolAlloc(osRtxInfo.mpi.mutex);
  98. } else {
  99. mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U);
  100. }
  101. if (mutex == NULL) {
  102. EvrRtxMutexError(NULL, osErrorNoMemory);
  103. return NULL;
  104. }
  105. flags = osRtxFlagSystemObject;
  106. } else {
  107. flags = 0U;
  108. }
  109. // Initialize control block
  110. mutex->id = osRtxIdMutex;
  111. mutex->state = osRtxObjectActive;
  112. mutex->flags = flags;
  113. mutex->attr = (uint8_t)attr_bits;
  114. mutex->name = name;
  115. mutex->thread_list = NULL;
  116. mutex->owner_thread = NULL;
  117. mutex->owner_prev = NULL;
  118. mutex->owner_next = NULL;
  119. mutex->lock = 0U;
  120. EvrRtxMutexCreated(mutex);
  121. return mutex;
  122. }
  123. /// Get name of a Mutex object.
  124. /// \note API identical to osMutexGetName
  125. const char *svcRtxMutexGetName (osMutexId_t mutex_id) {
  126. os_mutex_t *mutex = (os_mutex_t *)mutex_id;
  127. // Check parameters
  128. if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
  129. EvrRtxMutexGetName(mutex, NULL);
  130. return NULL;
  131. }
  132. // Check object state
  133. if (mutex->state == osRtxObjectInactive) {
  134. EvrRtxMutexGetName(mutex, NULL);
  135. return NULL;
  136. }
  137. EvrRtxMutexGetName(mutex, mutex->name);
  138. return mutex->name;
  139. }
  140. /// Acquire a Mutex or timeout if it is locked.
  141. /// \note API identical to osMutexAcquire
  142. osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  143. os_mutex_t *mutex = (os_mutex_t *)mutex_id;
  144. os_thread_t *runnig_thread;
  145. runnig_thread = osRtxThreadGetRunning();
  146. if (runnig_thread == NULL) {
  147. EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
  148. return osError;
  149. }
  150. // Check parameters
  151. if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
  152. EvrRtxMutexError(mutex, osErrorParameter);
  153. return osErrorParameter;
  154. }
  155. // Check object state
  156. if (mutex->state == osRtxObjectInactive) {
  157. EvrRtxMutexError(mutex, osErrorResource);
  158. return osErrorResource;
  159. }
  160. // Check if Mutex is not locked
  161. if (mutex->lock == 0U) {
  162. // Acquire Mutex
  163. mutex->owner_thread = runnig_thread;
  164. mutex->owner_next = runnig_thread->mutex_list;
  165. mutex->owner_prev = NULL;
  166. if (runnig_thread->mutex_list != NULL) {
  167. runnig_thread->mutex_list->owner_prev = mutex;
  168. }
  169. runnig_thread->mutex_list = mutex;
  170. mutex->lock = 1U;
  171. EvrRtxMutexAcquired(mutex, mutex->lock);
  172. return osOK;
  173. }
  174. // Check if Mutex is recursive and running Thread is the owner
  175. if ((mutex->attr & osMutexRecursive) && (mutex->owner_thread == runnig_thread)) {
  176. // Increment lock counter
  177. if (mutex->lock == osRtxMutexLockLimit) {
  178. EvrRtxMutexError(mutex, osRtxErrorMutexLockLimit);
  179. return osErrorResource;
  180. }
  181. mutex->lock++;
  182. EvrRtxMutexAcquired(mutex, mutex->lock);
  183. return osOK;
  184. }
  185. // Check if timeout is specified
  186. if (timeout != 0U) {
  187. // Check if Priority inheritance protocol is enabled
  188. if (mutex->attr & osMutexPrioInherit) {
  189. // Raise priority of owner Thread if lower than priority of running Thread
  190. if (mutex->owner_thread->priority < runnig_thread->priority) {
  191. mutex->owner_thread->priority = runnig_thread->priority;
  192. osRtxThreadListSort(mutex->owner_thread);
  193. }
  194. }
  195. EvrRtxMutexAcquirePending(mutex, timeout);
  196. // Suspend current Thread
  197. osRtxThreadListPut((os_object_t*)mutex, runnig_thread);
  198. osRtxThreadWaitEnter(osRtxThreadWaitingMutex, timeout);
  199. return osErrorTimeout;
  200. }
  201. // Mutex was not acquired
  202. EvrRtxMutexNotAcquired(mutex);
  203. return osErrorResource;
  204. }
  205. /// Release a Mutex that was acquired by osMutexAcquire.
  206. /// \note API identical to osMutexRelease
  207. osStatus_t svcRtxMutexRelease (osMutexId_t mutex_id) {
  208. os_mutex_t *mutex = (os_mutex_t *)mutex_id;
  209. os_mutex_t *mutex0;
  210. os_thread_t *thread;
  211. os_thread_t *runnig_thread;
  212. int8_t priority;
  213. runnig_thread = osRtxThreadGetRunning();
  214. if (runnig_thread == NULL) {
  215. EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
  216. return osError;
  217. }
  218. // Check parameters
  219. if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
  220. EvrRtxMutexError(mutex, osErrorParameter);
  221. return osErrorParameter;
  222. }
  223. // Check object state
  224. if (mutex->state == osRtxObjectInactive) {
  225. EvrRtxMutexError(mutex, osErrorResource);
  226. return osErrorResource;
  227. }
  228. // Check if running Thread is not the owner
  229. if (mutex->owner_thread != runnig_thread) {
  230. EvrRtxMutexError(mutex, osRtxErrorMutexNotOwned);
  231. return osErrorResource;
  232. }
  233. // Check if Mutex is not locked
  234. if (mutex->lock == 0U) {
  235. EvrRtxMutexError(mutex, osRtxErrorMutexNotLocked);
  236. return osErrorResource;
  237. }
  238. // Decrement Lock counter
  239. mutex->lock--;
  240. EvrRtxMutexReleased(mutex, mutex->lock);
  241. // Check Lock counter
  242. if (mutex->lock != 0U) {
  243. return osOK;
  244. }
  245. // Remove Mutex from Thread owner list
  246. if (mutex->owner_next != NULL) {
  247. mutex->owner_next->owner_prev = mutex->owner_prev;
  248. }
  249. if (mutex->owner_prev != NULL) {
  250. mutex->owner_prev->owner_next = mutex->owner_next;
  251. } else {
  252. runnig_thread->mutex_list = mutex->owner_next;
  253. }
  254. // Restore running Thread priority
  255. if (mutex->attr & osMutexPrioInherit) {
  256. priority = runnig_thread->priority_base;
  257. mutex0 = runnig_thread->mutex_list;
  258. while (mutex0) {
  259. // Mutexes owned by running Thread
  260. if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
  261. // Higher priority Thread is waiting for Mutex
  262. priority = mutex0->thread_list->priority;
  263. }
  264. mutex0 = mutex0->owner_next;
  265. }
  266. runnig_thread->priority = priority;
  267. }
  268. // Check if Thread is waiting for a Mutex
  269. if (mutex->thread_list != NULL) {
  270. // Wakeup waiting Thread with highest Priority
  271. thread = osRtxThreadListGet((os_object_t*)mutex);
  272. osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
  273. // Thread is the new Mutex owner
  274. mutex->owner_thread = thread;
  275. mutex->owner_next = thread->mutex_list;
  276. mutex->owner_prev = NULL;
  277. thread->mutex_list = mutex;
  278. mutex->lock = 1U;
  279. EvrRtxMutexAcquired(mutex, 1U);
  280. }
  281. osRtxThreadDispatch(NULL);
  282. return osOK;
  283. }
  284. /// Get Thread which owns a Mutex object.
  285. /// \note API identical to osMutexGetOwner
  286. osThreadId_t svcRtxMutexGetOwner (osMutexId_t mutex_id) {
  287. os_mutex_t *mutex = (os_mutex_t *)mutex_id;
  288. // Check parameters
  289. if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
  290. EvrRtxMutexGetOwner(mutex, NULL);
  291. return NULL;
  292. }
  293. // Check object state
  294. if (mutex->state == osRtxObjectInactive) {
  295. EvrRtxMutexGetOwner(mutex, NULL);
  296. return NULL;
  297. }
  298. // Check if Mutex is not locked
  299. if (mutex->lock == 0U) {
  300. EvrRtxMutexGetOwner(mutex, NULL);
  301. return NULL;
  302. }
  303. EvrRtxMutexGetOwner(mutex, mutex->owner_thread);
  304. return mutex->owner_thread;
  305. }
  306. /// Delete a Mutex object.
  307. /// \note API identical to osMutexDelete
  308. osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id) {
  309. os_mutex_t *mutex = (os_mutex_t *)mutex_id;
  310. os_mutex_t *mutex0;
  311. os_thread_t *thread;
  312. int8_t priority;
  313. // Check parameters
  314. if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
  315. EvrRtxMutexError(mutex, osErrorParameter);
  316. return osErrorParameter;
  317. }
  318. // Check object state
  319. if (mutex->state == osRtxObjectInactive) {
  320. EvrRtxMutexError(mutex, osErrorResource);
  321. return osErrorResource;
  322. }
  323. // Mark object as inactive
  324. mutex->state = osRtxObjectInactive;
  325. // Check if Mutex is locked
  326. if (mutex->lock != 0U) {
  327. thread = mutex->owner_thread;
  328. // Remove Mutex from Thread owner list
  329. if (mutex->owner_next != NULL) {
  330. mutex->owner_next->owner_prev = mutex->owner_prev;
  331. }
  332. if (mutex->owner_prev != NULL) {
  333. mutex->owner_prev->owner_next = mutex->owner_next;
  334. } else {
  335. thread->mutex_list = mutex->owner_next;
  336. }
  337. // Restore owner Thread priority
  338. if (mutex->attr & osMutexPrioInherit) {
  339. priority = thread->priority_base;
  340. mutex0 = thread->mutex_list;
  341. while (mutex0) {
  342. // Mutexes owned by running Thread
  343. if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
  344. // Higher priority Thread is waiting for Mutex
  345. priority = mutex0->thread_list->priority;
  346. }
  347. mutex0 = mutex0->owner_next;
  348. }
  349. if (thread->priority != priority) {
  350. thread->priority = priority;
  351. osRtxThreadListSort(thread);
  352. }
  353. }
  354. // Unblock waiting threads
  355. if (mutex->thread_list != NULL) {
  356. do {
  357. thread = osRtxThreadListGet((os_object_t*)mutex);
  358. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
  359. } while (mutex->thread_list != NULL);
  360. }
  361. osRtxThreadDispatch(NULL);
  362. }
  363. // Free object memory
  364. if (mutex->flags & osRtxFlagSystemObject) {
  365. if (osRtxInfo.mpi.mutex != NULL) {
  366. osRtxMemoryPoolFree(osRtxInfo.mpi.mutex, mutex);
  367. } else {
  368. osRtxMemoryFree(osRtxInfo.mem.common, mutex);
  369. }
  370. }
  371. EvrRtxMutexDestroyed(mutex);
  372. return osOK;
  373. }
  374. // ==== Public API ====
  375. /// Create and Initialize a Mutex object.
  376. osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
  377. EvrRtxMutexNew(attr);
  378. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  379. EvrRtxMutexError(NULL, osErrorISR);
  380. return NULL;
  381. }
  382. return __svcMutexNew(attr);
  383. }
  384. /// Get name of a Mutex object.
  385. const char *osMutexGetName (osMutexId_t mutex_id) {
  386. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  387. EvrRtxMutexGetName(mutex_id, NULL);
  388. return NULL;
  389. }
  390. return __svcMutexGetName(mutex_id);
  391. }
  392. /// Acquire a Mutex or timeout if it is locked.
  393. osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  394. EvrRtxMutexAcquire(mutex_id, timeout);
  395. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  396. EvrRtxMutexError(mutex_id, osErrorISR);
  397. return osErrorISR;
  398. }
  399. return __svcMutexAcquire(mutex_id, timeout);
  400. }
  401. /// Release a Mutex that was acquired by \ref osMutexAcquire.
  402. osStatus_t osMutexRelease (osMutexId_t mutex_id) {
  403. EvrRtxMutexRelease(mutex_id);
  404. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  405. EvrRtxMutexError(mutex_id, osErrorISR);
  406. return osErrorISR;
  407. }
  408. return __svcMutexRelease(mutex_id);
  409. }
  410. /// Get Thread which owns a Mutex object.
  411. osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
  412. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  413. EvrRtxMutexGetOwner(mutex_id, NULL);
  414. return NULL;
  415. }
  416. return __svcMutexGetOwner(mutex_id);
  417. }
  418. /// Delete a Mutex object.
  419. osStatus_t osMutexDelete (osMutexId_t mutex_id) {
  420. EvrRtxMutexDelete(mutex_id);
  421. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  422. EvrRtxMutexError(mutex_id, osErrorISR);
  423. return osErrorISR;
  424. }
  425. return __svcMutexDelete(mutex_id);
  426. }