训练营PLSR题目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1121 regels
46 KiB

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