os_mutex.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * Copyright 2009-2022 Silicon Laboratories Inc. www.silabs.com
  7. *
  8. * SPDX-License-Identifier: APACHE-2.0
  9. *
  10. * This software is subject to an open source license and is distributed by
  11. * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  12. * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  13. *
  14. *********************************************************************************************************
  15. */
  16. /*
  17. *********************************************************************************************************
  18. * MUTEX MANAGEMENT
  19. *
  20. * File : os_mutex.c
  21. * Version : V3.08.02
  22. *********************************************************************************************************
  23. */
  24. #define MICRIUM_SOURCE
  25. #include "os.h"
  26. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  27. const CPU_CHAR *os_mutex__c = "$Id: $";
  28. #endif
  29. #if (OS_CFG_MUTEX_EN > 0u)
  30. /*
  31. ************************************************************************************************************************
  32. * CREATE A MUTEX
  33. *
  34. * Description: This function creates a mutex.
  35. *
  36. * Arguments : p_mutex is a pointer to the mutex to initialize. Your application is responsible for allocating
  37. * storage for the mutex.
  38. *
  39. * p_name is a pointer to the name you would like to give the mutex.
  40. *
  41. * p_err is a pointer to a variable that will contain an error code returned by this function.
  42. *
  43. * OS_ERR_NONE If the call was successful
  44. * OS_ERR_CREATE_ISR If you called this function from an ISR
  45. * OS_ERR_ILLEGAL_CREATE_RUN_TIME If you are trying to create the mutex after you called
  46. * OSSafetyCriticalStart()
  47. * OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer
  48. * OS_ERR_OBJ_CREATED If the mutex was already created
  49. *
  50. * Returns : none
  51. *
  52. * Note(s) : none
  53. ************************************************************************************************************************
  54. */
  55. void OSMutexCreate (OS_MUTEX *p_mutex,
  56. CPU_CHAR *p_name,
  57. OS_ERR *p_err)
  58. {
  59. CPU_SR_ALLOC();
  60. #ifdef OS_SAFETY_CRITICAL
  61. if (p_err == (OS_ERR *)0) {
  62. OS_SAFETY_CRITICAL_EXCEPTION();
  63. return;
  64. }
  65. #endif
  66. #ifdef OS_SAFETY_CRITICAL_IEC61508
  67. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  68. *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
  69. return;
  70. }
  71. #endif
  72. #if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
  73. if (OSIntNestingCtr > 0u) { /* Not allowed to be called from an ISR */
  74. *p_err = OS_ERR_CREATE_ISR;
  75. return;
  76. }
  77. #endif
  78. #if (OS_CFG_ARG_CHK_EN > 0u)
  79. if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
  80. *p_err = OS_ERR_OBJ_PTR_NULL;
  81. return;
  82. }
  83. #endif
  84. CPU_CRITICAL_ENTER();
  85. #if (OS_OBJ_TYPE_REQ > 0u)
  86. #if (OS_CFG_OBJ_CREATED_CHK_EN > 0u)
  87. if (p_mutex->Type == OS_OBJ_TYPE_MUTEX) {
  88. CPU_CRITICAL_EXIT();
  89. *p_err = OS_ERR_OBJ_CREATED;
  90. return;
  91. }
  92. #endif
  93. p_mutex->Type = OS_OBJ_TYPE_MUTEX; /* Mark the data structure as a mutex */
  94. #endif
  95. #if (OS_CFG_DBG_EN > 0u)
  96. p_mutex->NamePtr = p_name;
  97. #else
  98. (void)p_name;
  99. #endif
  100. p_mutex->MutexGrpNextPtr = (OS_MUTEX *)0;
  101. p_mutex->OwnerTCBPtr = (OS_TCB *)0;
  102. p_mutex->OwnerNestingCtr = 0u; /* Mutex is available */
  103. #if (OS_CFG_TS_EN > 0u)
  104. p_mutex->TS = 0u;
  105. #endif
  106. OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */
  107. #if (OS_CFG_DBG_EN > 0u)
  108. OS_MutexDbgListAdd(p_mutex);
  109. OSMutexQty++;
  110. #endif
  111. OS_TRACE_MUTEX_CREATE(p_mutex, p_name);
  112. CPU_CRITICAL_EXIT();
  113. *p_err = OS_ERR_NONE;
  114. }
  115. /*
  116. ************************************************************************************************************************
  117. * DELETE A MUTEX
  118. *
  119. * Description: This function deletes a mutex and readies all tasks pending on the mutex.
  120. *
  121. * Arguments : p_mutex is a pointer to the mutex to delete
  122. *
  123. * opt determines delete options as follows:
  124. *
  125. * OS_OPT_DEL_NO_PEND Delete mutex ONLY if no task pending
  126. * OS_OPT_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
  127. * In this case, all the tasks pending will be readied.
  128. *
  129. * p_err is a pointer to a variable that will contain an error code returned by this function.
  130. *
  131. * OS_ERR_NONE The call was successful and the mutex was deleted
  132. * OS_ERR_DEL_ISR If you attempted to delete the mutex from an ISR
  133. * OS_ERR_ILLEGAL_DEL_RUN_TIME If you are trying to delete the mutex after you called
  134. * OSStart()
  135. * OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer
  136. * OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing to a mutex
  137. * OS_ERR_OPT_INVALID An invalid option was specified
  138. * OS_ERR_OS_NOT_RUNNING If uC/OS-III is not running yet
  139. * OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
  140. *
  141. * Returns : == 0 if no tasks were waiting on the mutex, or upon error.
  142. * > 0 if one or more tasks waiting on the mutex are now readied and informed.
  143. *
  144. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of the mutex MUST
  145. * check the return code of OSMutexPend().
  146. *
  147. * 2) Because ALL tasks pending on the mutex will be readied, you MUST be careful in applications where the
  148. * mutex is used for mutual exclusion because the resource(s) will no longer be guarded by the mutex.
  149. ************************************************************************************************************************
  150. */
  151. #if (OS_CFG_MUTEX_DEL_EN > 0u)
  152. OS_OBJ_QTY OSMutexDel (OS_MUTEX *p_mutex,
  153. OS_OPT opt,
  154. OS_ERR *p_err)
  155. {
  156. OS_OBJ_QTY nbr_tasks;
  157. OS_PEND_LIST *p_pend_list;
  158. OS_TCB *p_tcb;
  159. OS_TCB *p_tcb_owner;
  160. CPU_TS ts;
  161. #if (OS_CFG_MUTEX_EN > 0u)
  162. OS_PRIO prio_new;
  163. #endif
  164. CPU_SR_ALLOC();
  165. #ifdef OS_SAFETY_CRITICAL
  166. if (p_err == (OS_ERR *)0) {
  167. OS_SAFETY_CRITICAL_EXCEPTION();
  168. return (0u);
  169. }
  170. #endif
  171. OS_TRACE_MUTEX_DEL_ENTER(p_mutex, opt);
  172. #ifdef OS_SAFETY_CRITICAL_IEC61508
  173. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  174. OS_TRACE_MUTEX_DEL_EXIT(OS_ERR_ILLEGAL_DEL_RUN_TIME);
  175. *p_err = OS_ERR_ILLEGAL_DEL_RUN_TIME;
  176. return (0u);
  177. }
  178. #endif
  179. #if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
  180. if (OSIntNestingCtr > 0u) { /* Not allowed to delete a mutex from an ISR */
  181. OS_TRACE_MUTEX_DEL_EXIT(OS_ERR_DEL_ISR);
  182. *p_err = OS_ERR_DEL_ISR;
  183. return (0u);
  184. }
  185. #endif
  186. #if (OS_CFG_INVALID_OS_CALLS_CHK_EN > 0u)
  187. if (OSRunning != OS_STATE_OS_RUNNING) { /* Is the kernel running? */
  188. OS_TRACE_MUTEX_DEL_EXIT(OS_ERR_OS_NOT_RUNNING);
  189. *p_err = OS_ERR_OS_NOT_RUNNING;
  190. return (0u);
  191. }
  192. #endif
  193. #if (OS_CFG_ARG_CHK_EN > 0u)
  194. if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
  195. OS_TRACE_MUTEX_DEL_EXIT(OS_ERR_OBJ_PTR_NULL);
  196. *p_err = OS_ERR_OBJ_PTR_NULL;
  197. return (0u);
  198. }
  199. #endif
  200. #if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
  201. if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
  202. OS_TRACE_MUTEX_DEL_EXIT(OS_ERR_OBJ_TYPE);
  203. *p_err = OS_ERR_OBJ_TYPE;
  204. return (0u);
  205. }
  206. #endif
  207. CPU_CRITICAL_ENTER();
  208. p_pend_list = &p_mutex->PendList;
  209. nbr_tasks = 0u;
  210. switch (opt) {
  211. case OS_OPT_DEL_NO_PEND: /* Delete mutex only if no task waiting */
  212. if (p_pend_list->HeadPtr == (OS_TCB *)0) {
  213. #if (OS_CFG_DBG_EN > 0u)
  214. OS_MutexDbgListRemove(p_mutex);
  215. OSMutexQty--;
  216. #endif
  217. OS_TRACE_MUTEX_DEL(p_mutex);
  218. if (p_mutex->OwnerTCBPtr != (OS_TCB *)0) { /* Does the mutex belong to a task? */
  219. OS_MutexGrpRemove(p_mutex->OwnerTCBPtr, p_mutex); /* yes, remove it from the task group. */
  220. }
  221. OS_MutexClr(p_mutex);
  222. CPU_CRITICAL_EXIT();
  223. *p_err = OS_ERR_NONE;
  224. } else {
  225. CPU_CRITICAL_EXIT();
  226. *p_err = OS_ERR_TASK_WAITING;
  227. }
  228. break;
  229. case OS_OPT_DEL_ALWAYS: /* Always delete the mutex */
  230. #if (OS_CFG_TS_EN > 0u)
  231. ts = OS_TS_GET(); /* Get timestamp */
  232. #else
  233. ts = 0u;
  234. #endif
  235. while (p_pend_list->HeadPtr != (OS_TCB *)0) { /* Remove all tasks from the pend list */
  236. p_tcb = p_pend_list->HeadPtr;
  237. OS_PendAbort(p_tcb,
  238. ts,
  239. OS_STATUS_PEND_DEL);
  240. nbr_tasks++;
  241. }
  242. #if (OS_CFG_DBG_EN > 0u)
  243. OS_MutexDbgListRemove(p_mutex);
  244. OSMutexQty--;
  245. #endif
  246. OS_TRACE_MUTEX_DEL(p_mutex);
  247. p_tcb_owner = p_mutex->OwnerTCBPtr;
  248. if (p_tcb_owner != (OS_TCB *)0) { /* Does the mutex belong to a task? */
  249. OS_MutexGrpRemove(p_tcb_owner, p_mutex); /* yes, remove it from the task group. */
  250. }
  251. if (p_tcb_owner != (OS_TCB *)0) { /* Did we had to change the prio of owner? */
  252. if (p_tcb_owner->Prio != p_tcb_owner->BasePrio) {
  253. prio_new = OS_MutexGrpPrioFindHighest(p_tcb_owner);
  254. prio_new = (prio_new > p_tcb_owner->BasePrio) ? p_tcb_owner->BasePrio : prio_new;
  255. OS_TaskChangePrio(p_tcb_owner, prio_new);
  256. OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio);
  257. }
  258. }
  259. OS_MutexClr(p_mutex);
  260. CPU_CRITICAL_EXIT();
  261. OSSched(); /* Find highest priority task ready to run */
  262. *p_err = OS_ERR_NONE;
  263. break;
  264. default:
  265. CPU_CRITICAL_EXIT();
  266. *p_err = OS_ERR_OPT_INVALID;
  267. break;
  268. }
  269. OS_TRACE_MUTEX_DEL_EXIT(*p_err);
  270. return (nbr_tasks);
  271. }
  272. #endif
  273. /*
  274. ************************************************************************************************************************
  275. * PEND ON MUTEX
  276. *
  277. * Description: This function waits for a mutex.
  278. *
  279. * Arguments : p_mutex is a pointer to the mutex
  280. *
  281. * timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait for the
  282. * resource up to the amount of time (in 'ticks') specified by this argument. If you specify
  283. * 0, however, your task will wait forever at the specified mutex or, until the resource
  284. * becomes available.
  285. *
  286. * opt determines whether the user wants to block if the mutex is available or not:
  287. *
  288. * OS_OPT_PEND_BLOCKING
  289. * OS_OPT_PEND_NON_BLOCKING
  290. *
  291. * p_ts is a pointer to a variable that will receive the timestamp of when the mutex was posted or
  292. * pend aborted or the mutex deleted. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you
  293. * will not get the timestamp. In other words, passing a NULL pointer is valid and indicates
  294. * that you don't need the timestamp.
  295. *
  296. * p_err is a pointer to a variable that will contain an error code returned by this function.
  297. *
  298. * OS_ERR_NONE The call was successful and your task owns the resource
  299. * OS_ERR_MUTEX_OWNER If calling task already owns the mutex
  300. * OS_ERR_MUTEX_OVF Mutex nesting counter overflowed
  301. * OS_ERR_OBJ_DEL If 'p_mutex' was deleted
  302. * OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer
  303. * OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
  304. * OS_ERR_OPT_INVALID If you didn't specify a valid option
  305. * OS_ERR_OS_NOT_RUNNING If uC/OS-III is not running yet
  306. * OS_ERR_PEND_ABORT If the pend was aborted by another task
  307. * OS_ERR_PEND_ISR If you called this function from an ISR and the result
  308. * would lead to a suspension
  309. * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the mutex was not
  310. * available
  311. * OS_ERR_SCHED_LOCKED If you called this function when the scheduler is locked
  312. * OS_ERR_STATUS_INVALID If the pend status has an invalid value
  313. * OS_ERR_TIMEOUT The mutex was not received within the specified timeout
  314. * OS_ERR_TICK_DISABLED If kernel ticks are disabled and a timeout is specified
  315. *
  316. * Returns : none
  317. *
  318. * Note(s) : This API 'MUST NOT' be called from a timer callback function.
  319. ************************************************************************************************************************
  320. */
  321. void OSMutexPend (OS_MUTEX *p_mutex,
  322. OS_TICK timeout,
  323. OS_OPT opt,
  324. CPU_TS *p_ts,
  325. OS_ERR *p_err)
  326. {
  327. OS_TCB *p_tcb;
  328. CPU_SR_ALLOC();
  329. #if (OS_CFG_TS_EN == 0u)
  330. (void)p_ts; /* Prevent compiler warning for not using 'ts' */
  331. #endif
  332. #ifdef OS_SAFETY_CRITICAL
  333. if (p_err == (OS_ERR *)0) {
  334. OS_SAFETY_CRITICAL_EXCEPTION();
  335. return;
  336. }
  337. #endif
  338. OS_TRACE_MUTEX_PEND_ENTER(p_mutex, timeout, opt, p_ts);
  339. #if (OS_CFG_TICK_EN == 0u)
  340. if (timeout != 0u) {
  341. *p_err = OS_ERR_TICK_DISABLED;
  342. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  343. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_TICK_DISABLED);
  344. return;
  345. }
  346. #endif
  347. #if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
  348. if (OSIntNestingCtr > 0u) { /* Not allowed to call from an ISR */
  349. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  350. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_PEND_ISR);
  351. *p_err = OS_ERR_PEND_ISR;
  352. return;
  353. }
  354. #endif
  355. #if (OS_CFG_INVALID_OS_CALLS_CHK_EN > 0u)
  356. if (OSRunning != OS_STATE_OS_RUNNING) { /* Is the kernel running? */
  357. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_OS_NOT_RUNNING);
  358. *p_err = OS_ERR_OS_NOT_RUNNING;
  359. return;
  360. }
  361. #endif
  362. #if (OS_CFG_ARG_CHK_EN > 0u)
  363. if (p_mutex == (OS_MUTEX *)0) { /* Validate arguments */
  364. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  365. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_OBJ_PTR_NULL);
  366. *p_err = OS_ERR_OBJ_PTR_NULL;
  367. return;
  368. }
  369. switch (opt) { /* Validate 'opt' */
  370. case OS_OPT_PEND_BLOCKING:
  371. case OS_OPT_PEND_NON_BLOCKING:
  372. break;
  373. default:
  374. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  375. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_OPT_INVALID);
  376. *p_err = OS_ERR_OPT_INVALID;
  377. return;
  378. }
  379. #endif
  380. #if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
  381. if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
  382. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  383. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_OBJ_TYPE);
  384. *p_err = OS_ERR_OBJ_TYPE;
  385. return;
  386. }
  387. #endif
  388. CPU_CRITICAL_ENTER();
  389. if (p_mutex->OwnerNestingCtr == 0u) { /* Resource available? */
  390. p_mutex->OwnerTCBPtr = OSTCBCurPtr; /* Yes, caller may proceed */
  391. p_mutex->OwnerNestingCtr = 1u;
  392. #if (OS_CFG_TS_EN > 0u)
  393. if (p_ts != (CPU_TS *)0) {
  394. *p_ts = p_mutex->TS;
  395. }
  396. #endif
  397. OS_MutexGrpAdd(OSTCBCurPtr, p_mutex); /* Add mutex to owner's group */
  398. CPU_CRITICAL_EXIT();
  399. OS_TRACE_MUTEX_PEND(p_mutex);
  400. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_NONE);
  401. *p_err = OS_ERR_NONE;
  402. return;
  403. }
  404. if (OSTCBCurPtr == p_mutex->OwnerTCBPtr) { /* See if current task is already the owner of the mutex*/
  405. if (p_mutex->OwnerNestingCtr == (OS_NESTING_CTR)-1) {
  406. CPU_CRITICAL_EXIT();
  407. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  408. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_MUTEX_OVF);
  409. *p_err = OS_ERR_MUTEX_OVF;
  410. return;
  411. }
  412. p_mutex->OwnerNestingCtr++;
  413. #if (OS_CFG_TS_EN > 0u)
  414. if (p_ts != (CPU_TS *)0) {
  415. *p_ts = p_mutex->TS;
  416. }
  417. #endif
  418. CPU_CRITICAL_EXIT();
  419. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  420. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_MUTEX_OWNER);
  421. *p_err = OS_ERR_MUTEX_OWNER; /* Indicate that current task already owns the mutex */
  422. return;
  423. }
  424. if ((opt & OS_OPT_PEND_NON_BLOCKING) != 0u) { /* Caller wants to block if not available? */
  425. CPU_CRITICAL_EXIT();
  426. #if (OS_CFG_TS_EN > 0u)
  427. if (p_ts != (CPU_TS *)0) {
  428. *p_ts = 0u;
  429. }
  430. #endif
  431. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  432. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_PEND_WOULD_BLOCK);
  433. *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
  434. return;
  435. } else {
  436. if (OSSchedLockNestingCtr > 0u) { /* Can't pend when the scheduler is locked */
  437. CPU_CRITICAL_EXIT();
  438. #if (OS_CFG_TS_EN > 0u)
  439. if (p_ts != (CPU_TS *)0) {
  440. *p_ts = 0u;
  441. }
  442. #endif
  443. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  444. OS_TRACE_MUTEX_PEND_EXIT(OS_ERR_SCHED_LOCKED);
  445. *p_err = OS_ERR_SCHED_LOCKED;
  446. return;
  447. }
  448. }
  449. p_tcb = p_mutex->OwnerTCBPtr; /* Point to the TCB of the Mutex owner */
  450. if (p_tcb->Prio > OSTCBCurPtr->Prio) { /* See if mutex owner has a lower priority than current */
  451. OS_TaskChangePrio(p_tcb, OSTCBCurPtr->Prio);
  452. OS_TRACE_MUTEX_TASK_PRIO_INHERIT(p_tcb, p_tcb->Prio);
  453. }
  454. OS_Pend((OS_PEND_OBJ *)((void *)p_mutex), /* Block task pending on Mutex */
  455. OSTCBCurPtr,
  456. OS_TASK_PEND_ON_MUTEX,
  457. timeout);
  458. CPU_CRITICAL_EXIT();
  459. OS_TRACE_MUTEX_PEND_BLOCK(p_mutex);
  460. OSSched(); /* Find the next highest priority task ready to run */
  461. CPU_CRITICAL_ENTER();
  462. switch (OSTCBCurPtr->PendStatus) {
  463. case OS_STATUS_PEND_OK: /* We got the mutex */
  464. #if (OS_CFG_TS_EN > 0u)
  465. if (p_ts != (CPU_TS *)0) {
  466. *p_ts = OSTCBCurPtr->TS;
  467. }
  468. #endif
  469. OS_TRACE_MUTEX_PEND(p_mutex);
  470. *p_err = OS_ERR_NONE;
  471. break;
  472. case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
  473. #if (OS_CFG_TS_EN > 0u)
  474. if (p_ts != (CPU_TS *)0) {
  475. *p_ts = OSTCBCurPtr->TS;
  476. }
  477. #endif
  478. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  479. *p_err = OS_ERR_PEND_ABORT;
  480. break;
  481. case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get mutex within timeout */
  482. #if (OS_CFG_TS_EN > 0u)
  483. if (p_ts != (CPU_TS *)0) {
  484. *p_ts = 0u;
  485. }
  486. #endif
  487. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  488. *p_err = OS_ERR_TIMEOUT;
  489. break;
  490. case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
  491. #if (OS_CFG_TS_EN > 0u)
  492. if (p_ts != (CPU_TS *)0) {
  493. *p_ts = OSTCBCurPtr->TS;
  494. }
  495. #endif
  496. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  497. *p_err = OS_ERR_OBJ_DEL;
  498. break;
  499. default:
  500. OS_TRACE_MUTEX_PEND_FAILED(p_mutex);
  501. *p_err = OS_ERR_STATUS_INVALID;
  502. break;
  503. }
  504. CPU_CRITICAL_EXIT();
  505. OS_TRACE_MUTEX_PEND_EXIT(*p_err);
  506. }
  507. /*
  508. ************************************************************************************************************************
  509. * ABORT WAITING ON A MUTEX
  510. *
  511. * Description: This function aborts & readies any tasks currently waiting on a mutex. This function should be used
  512. * to fault-abort the wait on the mutex, rather than to normally signal the mutex via OSMutexPost().
  513. *
  514. * Arguments : p_mutex is a pointer to the mutex
  515. *
  516. * opt determines the type of ABORT performed:
  517. *
  518. * OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the mutex
  519. * OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the mutex
  520. * OS_OPT_POST_NO_SCHED Do not call the scheduler
  521. *
  522. * p_err is a pointer to a variable that will contain an error code returned by this function.
  523. *
  524. * OS_ERR_NONE At least one task waiting on the mutex was readied and
  525. * informed of the aborted wait; check return value for the
  526. * number of tasks whose wait on the mutex was aborted
  527. * OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer
  528. * OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
  529. * OS_ERR_OPT_INVALID If you specified an invalid option
  530. * OS_ERR_OS_NOT_RUNNING If uC/OS-III is not running yet
  531. * OS_ERR_PEND_ABORT_ISR If you attempted to call this function from an ISR
  532. * OS_ERR_PEND_ABORT_NONE No task were pending
  533. *
  534. * Returns : == 0 if no tasks were waiting on the mutex, or upon error.
  535. * > 0 if one or more tasks waiting on the mutex are now readied and informed.
  536. *
  537. * Note(s) : none
  538. ************************************************************************************************************************
  539. */
  540. #if (OS_CFG_MUTEX_PEND_ABORT_EN > 0u)
  541. OS_OBJ_QTY OSMutexPendAbort (OS_MUTEX *p_mutex,
  542. OS_OPT opt,
  543. OS_ERR *p_err)
  544. {
  545. OS_PEND_LIST *p_pend_list;
  546. OS_TCB *p_tcb;
  547. OS_TCB *p_tcb_owner;
  548. CPU_TS ts;
  549. OS_OBJ_QTY nbr_tasks;
  550. OS_PRIO prio_new;
  551. CPU_SR_ALLOC();
  552. #ifdef OS_SAFETY_CRITICAL
  553. if (p_err == (OS_ERR *)0) {
  554. OS_SAFETY_CRITICAL_EXCEPTION();
  555. return ((OS_OBJ_QTY)0u);
  556. }
  557. #endif
  558. #if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
  559. if (OSIntNestingCtr > 0u) { /* Not allowed to Pend Abort from an ISR */
  560. *p_err = OS_ERR_PEND_ABORT_ISR;
  561. return (0u);
  562. }
  563. #endif
  564. #if (OS_CFG_INVALID_OS_CALLS_CHK_EN > 0u)
  565. if (OSRunning != OS_STATE_OS_RUNNING) { /* Is the kernel running? */
  566. *p_err = OS_ERR_OS_NOT_RUNNING;
  567. return (0u);
  568. }
  569. #endif
  570. #if (OS_CFG_ARG_CHK_EN > 0u)
  571. if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
  572. *p_err = OS_ERR_OBJ_PTR_NULL;
  573. return (0u);
  574. }
  575. switch (opt) { /* Validate 'opt' */
  576. case OS_OPT_PEND_ABORT_1:
  577. case OS_OPT_PEND_ABORT_ALL:
  578. case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
  579. case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
  580. break;
  581. default:
  582. *p_err = OS_ERR_OPT_INVALID;
  583. return (0u);
  584. }
  585. #endif
  586. #if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
  587. if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
  588. *p_err = OS_ERR_OBJ_TYPE;
  589. return (0u);
  590. }
  591. #endif
  592. CPU_CRITICAL_ENTER();
  593. p_pend_list = &p_mutex->PendList;
  594. if (p_pend_list->HeadPtr == (OS_TCB *)0) { /* Any task waiting on mutex? */
  595. CPU_CRITICAL_EXIT(); /* No */
  596. *p_err = OS_ERR_PEND_ABORT_NONE;
  597. return (0u);
  598. }
  599. nbr_tasks = 0u;
  600. #if (OS_CFG_TS_EN > 0u)
  601. ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
  602. #else
  603. ts = 0u;
  604. #endif
  605. while (p_pend_list->HeadPtr != (OS_TCB *)0) {
  606. p_tcb = p_pend_list->HeadPtr;
  607. OS_PendAbort(p_tcb,
  608. ts,
  609. OS_STATUS_PEND_ABORT);
  610. p_tcb_owner = p_mutex->OwnerTCBPtr;
  611. prio_new = p_tcb_owner->Prio;
  612. if ((p_tcb_owner->Prio != p_tcb_owner->BasePrio) &&
  613. (p_tcb_owner->Prio == p_tcb->Prio)) { /* Has the owner inherited a priority? */
  614. prio_new = OS_MutexGrpPrioFindHighest(p_tcb_owner);
  615. prio_new = (prio_new > p_tcb_owner->BasePrio) ? p_tcb_owner->BasePrio : prio_new;
  616. }
  617. if(prio_new != p_tcb_owner->Prio) {
  618. OS_TaskChangePrio(p_tcb_owner, prio_new);
  619. OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio);
  620. }
  621. nbr_tasks++;
  622. if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
  623. break; /* No */
  624. }
  625. }
  626. CPU_CRITICAL_EXIT();
  627. if ((opt & OS_OPT_POST_NO_SCHED) == 0u) {
  628. OSSched(); /* Run the scheduler */
  629. }
  630. *p_err = OS_ERR_NONE;
  631. return (nbr_tasks);
  632. }
  633. #endif
  634. /*
  635. ************************************************************************************************************************
  636. * POST TO A MUTEX
  637. *
  638. * Description: This function signals a mutex.
  639. *
  640. * Arguments : p_mutex is a pointer to the mutex
  641. *
  642. * opt is an option you can specify to alter the behavior of the post. The choices are:
  643. *
  644. * OS_OPT_POST_NONE No special option selected
  645. * OS_OPT_POST_NO_SCHED If you don't want the scheduler to be called after the post.
  646. *
  647. * p_err is a pointer to a variable that will contain an error code returned by this function.
  648. *
  649. * OS_ERR_NONE The call was successful and the mutex was signaled
  650. * OS_ERR_MUTEX_NESTING Mutex owner nested its use of the mutex
  651. * OS_ERR_MUTEX_NOT_OWNER If the task posting is not the Mutex owner
  652. * OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer
  653. * OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing at a mutex
  654. * OS_ERR_OPT_INVALID If you specified an invalid option
  655. * OS_ERR_OS_NOT_RUNNING If uC/OS-III is not running yet
  656. * OS_ERR_POST_ISR If you attempted to post from an ISR
  657. *
  658. * Returns : none
  659. *
  660. * Note(s) : none
  661. ************************************************************************************************************************
  662. */
  663. void OSMutexPost (OS_MUTEX *p_mutex,
  664. OS_OPT opt,
  665. OS_ERR *p_err)
  666. {
  667. OS_PEND_LIST *p_pend_list;
  668. OS_TCB *p_tcb;
  669. CPU_TS ts;
  670. OS_PRIO prio_new;
  671. CPU_SR_ALLOC();
  672. #ifdef OS_SAFETY_CRITICAL
  673. if (p_err == (OS_ERR *)0) {
  674. OS_SAFETY_CRITICAL_EXCEPTION();
  675. return;
  676. }
  677. #endif
  678. OS_TRACE_MUTEX_POST_ENTER(p_mutex, opt);
  679. #if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
  680. if (OSIntNestingCtr > 0u) { /* Not allowed to call from an ISR */
  681. OS_TRACE_MUTEX_POST_FAILED(p_mutex);
  682. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_POST_ISR);
  683. *p_err = OS_ERR_POST_ISR;
  684. return;
  685. }
  686. #endif
  687. #if (OS_CFG_INVALID_OS_CALLS_CHK_EN > 0u)
  688. if (OSRunning != OS_STATE_OS_RUNNING) { /* Is the kernel running? */
  689. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_OS_NOT_RUNNING);
  690. *p_err = OS_ERR_OS_NOT_RUNNING;
  691. return;
  692. }
  693. #endif
  694. #if (OS_CFG_ARG_CHK_EN > 0u)
  695. if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
  696. OS_TRACE_MUTEX_POST_FAILED(p_mutex);
  697. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_OBJ_PTR_NULL);
  698. *p_err = OS_ERR_OBJ_PTR_NULL;
  699. return;
  700. }
  701. switch (opt) { /* Validate 'opt' */
  702. case OS_OPT_POST_NONE:
  703. case OS_OPT_POST_NO_SCHED:
  704. break;
  705. default:
  706. OS_TRACE_MUTEX_POST_FAILED(p_mutex);
  707. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_OPT_INVALID);
  708. *p_err = OS_ERR_OPT_INVALID;
  709. return;
  710. }
  711. #endif
  712. #if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
  713. if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
  714. OS_TRACE_MUTEX_POST_FAILED(p_mutex);
  715. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_OBJ_TYPE);
  716. *p_err = OS_ERR_OBJ_TYPE;
  717. return;
  718. }
  719. #endif
  720. CPU_CRITICAL_ENTER();
  721. if (OSTCBCurPtr != p_mutex->OwnerTCBPtr) { /* Make sure the mutex owner is releasing the mutex */
  722. CPU_CRITICAL_EXIT();
  723. OS_TRACE_MUTEX_POST_FAILED(p_mutex);
  724. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_MUTEX_NOT_OWNER);
  725. *p_err = OS_ERR_MUTEX_NOT_OWNER;
  726. return;
  727. }
  728. OS_TRACE_MUTEX_POST(p_mutex);
  729. #if (OS_CFG_TS_EN > 0u)
  730. ts = OS_TS_GET(); /* Get timestamp */
  731. p_mutex->TS = ts;
  732. #else
  733. ts = 0u;
  734. #endif
  735. p_mutex->OwnerNestingCtr--; /* Decrement owner's nesting counter */
  736. if (p_mutex->OwnerNestingCtr > 0u) { /* Are we done with all nestings? */
  737. CPU_CRITICAL_EXIT(); /* No */
  738. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_MUTEX_NESTING);
  739. *p_err = OS_ERR_MUTEX_NESTING;
  740. return;
  741. }
  742. OS_MutexGrpRemove(OSTCBCurPtr, p_mutex); /* Remove mutex from owner's group */
  743. p_pend_list = &p_mutex->PendList;
  744. if (p_pend_list->HeadPtr == (OS_TCB *)0) { /* Any task waiting on mutex? */
  745. p_mutex->OwnerTCBPtr = (OS_TCB *)0; /* No */
  746. p_mutex->OwnerNestingCtr = 0u;
  747. CPU_CRITICAL_EXIT();
  748. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_NONE);
  749. *p_err = OS_ERR_NONE;
  750. return;
  751. }
  752. /* Yes */
  753. if (OSTCBCurPtr->Prio != OSTCBCurPtr->BasePrio) { /* Has owner inherited a priority? */
  754. prio_new = OS_MutexGrpPrioFindHighest(OSTCBCurPtr); /* Yes, find highest priority pending */
  755. prio_new = (prio_new > OSTCBCurPtr->BasePrio) ? OSTCBCurPtr->BasePrio : prio_new;
  756. if (prio_new > OSTCBCurPtr->Prio) {
  757. OS_RdyListRemove(OSTCBCurPtr);
  758. OSTCBCurPtr->Prio = prio_new; /* Lower owner's priority back to its original one */
  759. OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(OSTCBCurPtr, prio_new);
  760. OS_PrioInsert(prio_new);
  761. OS_RdyListInsertTail(OSTCBCurPtr); /* Insert owner in ready list at new priority */
  762. OSPrioCur = prio_new;
  763. }
  764. }
  765. /* Get TCB from head of pend list */
  766. p_tcb = p_pend_list->HeadPtr;
  767. p_mutex->OwnerTCBPtr = p_tcb; /* Give mutex to new owner */
  768. p_mutex->OwnerNestingCtr = 1u;
  769. OS_MutexGrpAdd(p_tcb, p_mutex);
  770. /* Post to mutex */
  771. OS_Post((OS_PEND_OBJ *)((void *)p_mutex),
  772. p_tcb,
  773. (void *)0,
  774. 0u,
  775. ts);
  776. CPU_CRITICAL_EXIT();
  777. if ((opt & OS_OPT_POST_NO_SCHED) == 0u) {
  778. OSSched(); /* Run the scheduler */
  779. }
  780. OS_TRACE_MUTEX_POST_EXIT(OS_ERR_NONE);
  781. *p_err = OS_ERR_NONE;
  782. }
  783. /*
  784. ************************************************************************************************************************
  785. * CLEAR THE CONTENTS OF A MUTEX
  786. *
  787. * Description: This function is called by OSMutexDel() to clear the contents of a mutex
  788. *
  789. * Argument(s): p_mutex is a pointer to the mutex to clear
  790. * -------
  791. *
  792. * Returns : none
  793. *
  794. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  795. ************************************************************************************************************************
  796. */
  797. void OS_MutexClr (OS_MUTEX *p_mutex)
  798. {
  799. #if (OS_OBJ_TYPE_REQ > 0u)
  800. p_mutex->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
  801. #endif
  802. #if (OS_CFG_DBG_EN > 0u)
  803. p_mutex->NamePtr = (CPU_CHAR *)((void *)"?MUTEX");
  804. #endif
  805. p_mutex->MutexGrpNextPtr = (OS_MUTEX *)0;
  806. p_mutex->OwnerTCBPtr = (OS_TCB *)0;
  807. p_mutex->OwnerNestingCtr = 0u;
  808. #if (OS_CFG_TS_EN > 0u)
  809. p_mutex->TS = 0u;
  810. #endif
  811. OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */
  812. }
  813. /*
  814. ************************************************************************************************************************
  815. * ADD/REMOVE MUTEX TO/FROM DEBUG LIST
  816. *
  817. * Description: These functions are called by uC/OS-III to add or remove a mutex to/from the debug list.
  818. *
  819. * Arguments : p_mutex is a pointer to the mutex to add/remove
  820. *
  821. * Returns : none
  822. *
  823. * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
  824. ************************************************************************************************************************
  825. */
  826. #if (OS_CFG_DBG_EN > 0u)
  827. void OS_MutexDbgListAdd (OS_MUTEX *p_mutex)
  828. {
  829. p_mutex->DbgNamePtr = (CPU_CHAR *)((void *)" ");
  830. p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
  831. if (OSMutexDbgListPtr == (OS_MUTEX *)0) {
  832. p_mutex->DbgNextPtr = (OS_MUTEX *)0;
  833. } else {
  834. p_mutex->DbgNextPtr = OSMutexDbgListPtr;
  835. OSMutexDbgListPtr->DbgPrevPtr = p_mutex;
  836. }
  837. OSMutexDbgListPtr = p_mutex;
  838. }
  839. void OS_MutexDbgListRemove (OS_MUTEX *p_mutex)
  840. {
  841. OS_MUTEX *p_mutex_next;
  842. OS_MUTEX *p_mutex_prev;
  843. p_mutex_prev = p_mutex->DbgPrevPtr;
  844. p_mutex_next = p_mutex->DbgNextPtr;
  845. if (p_mutex_prev == (OS_MUTEX *)0) {
  846. OSMutexDbgListPtr = p_mutex_next;
  847. if (p_mutex_next != (OS_MUTEX *)0) {
  848. p_mutex_next->DbgPrevPtr = (OS_MUTEX *)0;
  849. }
  850. p_mutex->DbgNextPtr = (OS_MUTEX *)0;
  851. } else if (p_mutex_next == (OS_MUTEX *)0) {
  852. p_mutex_prev->DbgNextPtr = (OS_MUTEX *)0;
  853. p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
  854. } else {
  855. p_mutex_prev->DbgNextPtr = p_mutex_next;
  856. p_mutex_next->DbgPrevPtr = p_mutex_prev;
  857. p_mutex->DbgNextPtr = (OS_MUTEX *)0;
  858. p_mutex->DbgPrevPtr = (OS_MUTEX *)0;
  859. }
  860. }
  861. #endif
  862. /*
  863. ************************************************************************************************************************
  864. * MUTEX GROUP ADD
  865. *
  866. * Description: This function is called by the kernel to add a mutex to a task's mutex group.
  867. *
  868. * Argument(s): p_tcb is a pointer to the tcb of the task to give the mutex to.
  869. *
  870. * p_mutex is a point to the mutex to add to the group.
  871. *
  872. *
  873. * Returns : none
  874. *
  875. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  876. ************************************************************************************************************************
  877. */
  878. void OS_MutexGrpAdd (OS_TCB *p_tcb, OS_MUTEX *p_mutex)
  879. {
  880. p_mutex->MutexGrpNextPtr = p_tcb->MutexGrpHeadPtr; /* The mutex grp is not sorted add to head of list. */
  881. p_tcb->MutexGrpHeadPtr = p_mutex;
  882. }
  883. /*
  884. ************************************************************************************************************************
  885. * MUTEX GROUP REMOVE
  886. *
  887. * Description: This function is called by the kernel to remove a mutex to a task's mutex group.
  888. *
  889. * Argument(s): p_tcb is a pointer to the tcb of the task to remove the mutex from.
  890. *
  891. * p_mutex is a point to the mutex to remove from the group.
  892. *
  893. *
  894. * Returns : none
  895. *
  896. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  897. ************************************************************************************************************************
  898. */
  899. void OS_MutexGrpRemove (OS_TCB *p_tcb, OS_MUTEX *p_mutex)
  900. {
  901. OS_MUTEX **pp_mutex;
  902. pp_mutex = &p_tcb->MutexGrpHeadPtr;
  903. while(*pp_mutex != p_mutex) {
  904. pp_mutex = &(*pp_mutex)->MutexGrpNextPtr;
  905. }
  906. *pp_mutex = (*pp_mutex)->MutexGrpNextPtr;
  907. }
  908. /*
  909. ************************************************************************************************************************
  910. * MUTEX FIND HIGHEST PENDING
  911. *
  912. * Description: This function is called by the kernel to find the highest task pending on any mutex from a group.
  913. *
  914. * Argument(s): p_tcb is a pointer to the tcb of the task to process.
  915. *
  916. *
  917. * Returns : Highest priority pending or OS_CFG_PRIO_MAX - 1u if none found.
  918. *
  919. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  920. ************************************************************************************************************************
  921. */
  922. OS_PRIO OS_MutexGrpPrioFindHighest (OS_TCB *p_tcb)
  923. {
  924. OS_MUTEX **pp_mutex;
  925. OS_PRIO highest_prio;
  926. OS_PRIO prio;
  927. OS_TCB *p_head;
  928. highest_prio = (OS_PRIO)(OS_CFG_PRIO_MAX - 1u);
  929. pp_mutex = &p_tcb->MutexGrpHeadPtr;
  930. while(*pp_mutex != (OS_MUTEX *)0) {
  931. p_head = (*pp_mutex)->PendList.HeadPtr;
  932. if (p_head != (OS_TCB *)0) {
  933. prio = p_head->Prio;
  934. if(prio < highest_prio) {
  935. highest_prio = prio;
  936. }
  937. }
  938. pp_mutex = &(*pp_mutex)->MutexGrpNextPtr;
  939. }
  940. return (highest_prio);
  941. }
  942. /*
  943. ************************************************************************************************************************
  944. * MUTEX GROUP POST ALL
  945. *
  946. * Description: This function is called by the kernel to post (release) all the mutex from a group. Used when deleting
  947. * a task.
  948. *
  949. * Argument(s): p_tcb is a pointer to the tcb of the task to process.
  950. *
  951. *
  952. * Returns : none.
  953. *
  954. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  955. ************************************************************************************************************************
  956. */
  957. void OS_MutexGrpPostAll (OS_TCB *p_tcb)
  958. {
  959. OS_MUTEX *p_mutex;
  960. OS_MUTEX *p_mutex_next;
  961. CPU_TS ts;
  962. OS_PEND_LIST *p_pend_list;
  963. OS_TCB *p_tcb_new;
  964. p_mutex = p_tcb->MutexGrpHeadPtr;
  965. while(p_mutex != (OS_MUTEX *)0) {
  966. OS_TRACE_MUTEX_POST(p_mutex);
  967. p_mutex_next = p_mutex->MutexGrpNextPtr;
  968. #if (OS_CFG_TS_EN > 0u)
  969. ts = OS_TS_GET(); /* Get timestamp */
  970. p_mutex->TS = ts;
  971. #else
  972. ts = 0u;
  973. #endif
  974. OS_MutexGrpRemove(p_tcb, p_mutex); /* Remove mutex from owner's group */
  975. p_pend_list = &p_mutex->PendList;
  976. if (p_pend_list->HeadPtr == (OS_TCB *)0) { /* Any task waiting on mutex? */
  977. p_mutex->OwnerNestingCtr = 0u; /* Decrement owner's nesting counter */
  978. p_mutex->OwnerTCBPtr = (OS_TCB *)0; /* No */
  979. } else {
  980. /* Get TCB from head of pend list */
  981. p_tcb_new = p_pend_list->HeadPtr;
  982. p_mutex->OwnerTCBPtr = p_tcb; /* Give mutex to new owner */
  983. p_mutex->OwnerNestingCtr = 1u;
  984. OS_MutexGrpAdd(p_tcb_new, p_mutex);
  985. /* Post to mutex */
  986. OS_Post((OS_PEND_OBJ *)((void *)p_mutex),
  987. p_tcb_new,
  988. (void *)0,
  989. 0u,
  990. ts);
  991. }
  992. p_mutex = p_mutex_next;
  993. }
  994. }
  995. #endif /* OS_CFG_MUTEX_EN */