os_sem.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-II
  4. * The Real-Time Kernel
  5. * SEMAPHORE MANAGEMENT
  6. *
  7. * (c) Copyright 1992-2009, Micrium, Weston, FL
  8. * All Rights Reserved
  9. *
  10. * File : OS_SEM.C
  11. * By : Jean J. Labrosse
  12. * Version : V2.91
  13. *
  14. * LICENSING TERMS:
  15. * ---------------
  16. * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
  17. * If you plan on using uC/OS-II in a commercial product you need to contact Micriµm to properly license
  18. * its use in your product. We provide ALL the source code for your convenience and to help you experience
  19. * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
  20. * licensing fee.
  21. *********************************************************************************************************
  22. */
  23. #ifndef OS_MASTER_FILE
  24. #include <ucos_ii.h>
  25. #endif
  26. #if OS_SEM_EN > 0u
  27. /*$PAGE*/
  28. /*
  29. *********************************************************************************************************
  30. * ACCEPT SEMAPHORE
  31. *
  32. * Description: This function checks the semaphore to see if a resource is available or, if an event
  33. * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
  34. * resource is not available or the event did not occur.
  35. *
  36. * Arguments : pevent is a pointer to the event control block
  37. *
  38. * Returns : > 0 if the resource is available or the event did not occur the semaphore is
  39. * decremented to obtain the resource.
  40. * == 0 if the resource is not available or the event did not occur or,
  41. * if 'pevent' is a NULL pointer or,
  42. * if you didn't pass a pointer to a semaphore
  43. *********************************************************************************************************
  44. */
  45. #if OS_SEM_ACCEPT_EN > 0u
  46. INT16U OSSemAccept (OS_EVENT *pevent)
  47. {
  48. INT16U cnt;
  49. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  50. OS_CPU_SR cpu_sr = 0u;
  51. #endif
  52. #if OS_ARG_CHK_EN > 0u
  53. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  54. return (0u);
  55. }
  56. #endif
  57. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  58. return (0u);
  59. }
  60. OS_ENTER_CRITICAL();
  61. cnt = pevent->OSEventCnt;
  62. if (cnt > 0u) { /* See if resource is available */
  63. pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
  64. }
  65. OS_EXIT_CRITICAL();
  66. return (cnt); /* Return semaphore count */
  67. }
  68. #endif
  69. /*$PAGE*/
  70. /*
  71. *********************************************************************************************************
  72. * CREATE A SEMAPHORE
  73. *
  74. * Description: This function creates a semaphore.
  75. *
  76. * Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
  77. * available (or no event has occurred). You initialize the semaphore to a
  78. * non-zero value to specify how many resources are available (e.g. if you have
  79. * 10 resources, you would initialize the semaphore to 10).
  80. *
  81. * Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the
  82. * created semaphore
  83. * == (void *)0 if no event control blocks were available
  84. *********************************************************************************************************
  85. */
  86. OS_EVENT *OSSemCreate (INT16U cnt)
  87. {
  88. OS_EVENT *pevent;
  89. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  90. OS_CPU_SR cpu_sr = 0u;
  91. #endif
  92. #ifdef OS_SAFETY_CRITICAL_IEC61508
  93. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  94. OS_SAFETY_CRITICAL_EXCEPTION();
  95. }
  96. #endif
  97. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  98. return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
  99. }
  100. OS_ENTER_CRITICAL();
  101. pevent = OSEventFreeList; /* Get next free event control block */
  102. if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
  103. OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  104. }
  105. OS_EXIT_CRITICAL();
  106. if (pevent != (OS_EVENT *)0) { /* Get an event control block */
  107. pevent->OSEventType = OS_EVENT_TYPE_SEM;
  108. pevent->OSEventCnt = cnt; /* Set semaphore value */
  109. pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */
  110. #if OS_EVENT_NAME_EN > 0u
  111. pevent->OSEventName = (INT8U *)(void *)"?";
  112. #endif
  113. OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */
  114. }
  115. return (pevent);
  116. }
  117. /*$PAGE*/
  118. /*
  119. *********************************************************************************************************
  120. * DELETE A SEMAPHORE
  121. *
  122. * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
  123. *
  124. * Arguments : pevent is a pointer to the event control block associated with the desired
  125. * semaphore.
  126. *
  127. * opt determines delete options as follows:
  128. * opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
  129. * opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
  130. * In this case, all the tasks pending will be readied.
  131. *
  132. * perr is a pointer to an error code that can contain one of the following values:
  133. * OS_ERR_NONE The call was successful and the semaphore was deleted
  134. * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
  135. * OS_ERR_INVALID_OPT An invalid option was specified
  136. * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
  137. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
  138. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  139. *
  140. * Returns : pevent upon error
  141. * (OS_EVENT *)0 if the semaphore was successfully deleted.
  142. *
  143. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
  144. * the semaphore MUST check the return code of OSSemPend().
  145. * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
  146. * they check 'pevent' to see that it's a NULL pointer.
  147. * 3) This call can potentially disable interrupts for a long time. The interrupt disable
  148. * time is directly proportional to the number of tasks waiting on the semaphore.
  149. * 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
  150. * applications where the semaphore is used for mutual exclusion because the resource(s)
  151. * will no longer be guarded by the semaphore.
  152. *********************************************************************************************************
  153. */
  154. #if OS_SEM_DEL_EN > 0u
  155. OS_EVENT *OSSemDel (OS_EVENT *pevent,
  156. INT8U opt,
  157. INT8U *perr)
  158. {
  159. BOOLEAN tasks_waiting;
  160. OS_EVENT *pevent_return;
  161. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  162. OS_CPU_SR cpu_sr = 0u;
  163. #endif
  164. #ifdef OS_SAFETY_CRITICAL
  165. if (perr == (INT8U *)0) {
  166. OS_SAFETY_CRITICAL_EXCEPTION();
  167. }
  168. #endif
  169. #if OS_ARG_CHK_EN > 0u
  170. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  171. *perr = OS_ERR_PEVENT_NULL;
  172. return (pevent);
  173. }
  174. #endif
  175. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  176. *perr = OS_ERR_EVENT_TYPE;
  177. return (pevent);
  178. }
  179. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  180. *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  181. return (pevent);
  182. }
  183. OS_ENTER_CRITICAL();
  184. if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */
  185. tasks_waiting = OS_TRUE; /* Yes */
  186. } else {
  187. tasks_waiting = OS_FALSE; /* No */
  188. }
  189. switch (opt) {
  190. case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
  191. if (tasks_waiting == OS_FALSE) {
  192. #if OS_EVENT_NAME_EN > 0u
  193. pevent->OSEventName = (INT8U *)(void *)"?";
  194. #endif
  195. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  196. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  197. pevent->OSEventCnt = 0u;
  198. OSEventFreeList = pevent; /* Get next free event control block */
  199. OS_EXIT_CRITICAL();
  200. *perr = OS_ERR_NONE;
  201. pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
  202. } else {
  203. OS_EXIT_CRITICAL();
  204. *perr = OS_ERR_TASK_WAITING;
  205. pevent_return = pevent;
  206. }
  207. break;
  208. case OS_DEL_ALWAYS: /* Always delete the semaphore */
  209. while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */
  210. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
  211. }
  212. #if OS_EVENT_NAME_EN > 0u
  213. pevent->OSEventName = (INT8U *)(void *)"?";
  214. #endif
  215. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  216. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  217. pevent->OSEventCnt = 0u;
  218. OSEventFreeList = pevent; /* Get next free event control block */
  219. OS_EXIT_CRITICAL();
  220. if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
  221. OS_Sched(); /* Find highest priority task ready to run */
  222. }
  223. *perr = OS_ERR_NONE;
  224. pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
  225. break;
  226. default:
  227. OS_EXIT_CRITICAL();
  228. *perr = OS_ERR_INVALID_OPT;
  229. pevent_return = pevent;
  230. break;
  231. }
  232. return (pevent_return);
  233. }
  234. #endif
  235. /*$PAGE*/
  236. /*
  237. *********************************************************************************************************
  238. * PEND ON SEMAPHORE
  239. *
  240. * Description: This function waits for a semaphore.
  241. *
  242. * Arguments : pevent is a pointer to the event control block associated with the desired
  243. * semaphore.
  244. *
  245. * timeout is an optional timeout period (in clock ticks). If non-zero, your task will
  246. * wait for the resource up to the amount of time specified by this argument.
  247. * If you specify 0, however, your task will wait forever at the specified
  248. * semaphore or, until the resource becomes available (or the event occurs).
  249. *
  250. * perr is a pointer to where an error message will be deposited. Possible error
  251. * messages are:
  252. *
  253. * OS_ERR_NONE The call was successful and your task owns the resource
  254. * or, the event you are waiting for occurred.
  255. * OS_ERR_TIMEOUT The semaphore was not received within the specified
  256. * 'timeout'.
  257. * OS_ERR_PEND_ABORT The wait on the semaphore was aborted.
  258. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  259. * OS_ERR_PEND_ISR If you called this function from an ISR and the result
  260. * would lead to a suspension.
  261. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  262. * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
  263. *
  264. * Returns : none
  265. *********************************************************************************************************
  266. */
  267. /*$PAGE*/
  268. void OSSemPend (OS_EVENT *pevent,
  269. INT32U timeout,
  270. INT8U *perr)
  271. {
  272. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  273. OS_CPU_SR cpu_sr = 0u;
  274. #endif
  275. #ifdef OS_SAFETY_CRITICAL
  276. if (perr == (INT8U *)0) {
  277. OS_SAFETY_CRITICAL_EXCEPTION();
  278. }
  279. #endif
  280. #if OS_ARG_CHK_EN > 0u
  281. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  282. *perr = OS_ERR_PEVENT_NULL;
  283. return;
  284. }
  285. #endif
  286. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  287. *perr = OS_ERR_EVENT_TYPE;
  288. return;
  289. }
  290. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  291. *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
  292. return;
  293. }
  294. if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
  295. *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
  296. return;
  297. }
  298. OS_ENTER_CRITICAL();
  299. if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */
  300. pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */
  301. OS_EXIT_CRITICAL();
  302. *perr = OS_ERR_NONE;
  303. return;
  304. }
  305. /* Otherwise, must wait until event occurs */
  306. OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
  307. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
  308. OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
  309. OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
  310. OS_EXIT_CRITICAL();
  311. OS_Sched(); /* Find next highest priority task ready */
  312. OS_ENTER_CRITICAL();
  313. switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
  314. case OS_STAT_PEND_OK:
  315. *perr = OS_ERR_NONE;
  316. break;
  317. case OS_STAT_PEND_ABORT:
  318. *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
  319. break;
  320. case OS_STAT_PEND_TO:
  321. default:
  322. OS_EventTaskRemove(OSTCBCur, pevent);
  323. *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
  324. break;
  325. }
  326. OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
  327. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
  328. OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
  329. #if (OS_EVENT_MULTI_EN > 0u)
  330. OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
  331. #endif
  332. OS_EXIT_CRITICAL();
  333. }
  334. /*$PAGE*/
  335. /*
  336. *********************************************************************************************************
  337. * ABORT WAITING ON A SEMAPHORE
  338. *
  339. * Description: This function aborts & readies any tasks currently waiting on a semaphore. This function
  340. * should be used to fault-abort the wait on the semaphore, rather than to normally signal
  341. * the semaphore via OSSemPost().
  342. *
  343. * Arguments : pevent is a pointer to the event control block associated with the desired
  344. * semaphore.
  345. *
  346. * opt determines the type of ABORT performed:
  347. * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
  348. * semaphore
  349. * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
  350. * semaphore
  351. *
  352. * perr is a pointer to where an error message will be deposited. Possible error
  353. * messages are:
  354. *
  355. * OS_ERR_NONE No tasks were waiting on the semaphore.
  356. * OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied
  357. * and informed of the aborted wait; check return value
  358. * for the number of tasks whose wait on the semaphore
  359. * was aborted.
  360. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  361. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  362. *
  363. * Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
  364. * > 0 if one or more tasks waiting on the semaphore are now readied and informed.
  365. *********************************************************************************************************
  366. */
  367. #if OS_SEM_PEND_ABORT_EN > 0u
  368. INT8U OSSemPendAbort (OS_EVENT *pevent,
  369. INT8U opt,
  370. INT8U *perr)
  371. {
  372. INT8U nbr_tasks;
  373. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  374. OS_CPU_SR cpu_sr = 0u;
  375. #endif
  376. #ifdef OS_SAFETY_CRITICAL
  377. if (perr == (INT8U *)0) {
  378. OS_SAFETY_CRITICAL_EXCEPTION();
  379. }
  380. #endif
  381. #if OS_ARG_CHK_EN > 0u
  382. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  383. *perr = OS_ERR_PEVENT_NULL;
  384. return (0u);
  385. }
  386. #endif
  387. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  388. *perr = OS_ERR_EVENT_TYPE;
  389. return (0u);
  390. }
  391. OS_ENTER_CRITICAL();
  392. if (pevent->OSEventGrp != 0u) { /* See if any task waiting on semaphore? */
  393. nbr_tasks = 0u;
  394. switch (opt) {
  395. case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
  396. while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on semaphore */
  397. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  398. nbr_tasks++;
  399. }
  400. break;
  401. case OS_PEND_OPT_NONE:
  402. default: /* No, ready HPT waiting on semaphore */
  403. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  404. nbr_tasks++;
  405. break;
  406. }
  407. OS_EXIT_CRITICAL();
  408. OS_Sched(); /* Find HPT ready to run */
  409. *perr = OS_ERR_PEND_ABORT;
  410. return (nbr_tasks);
  411. }
  412. OS_EXIT_CRITICAL();
  413. *perr = OS_ERR_NONE;
  414. return (0u); /* No tasks waiting on semaphore */
  415. }
  416. #endif
  417. /*$PAGE*/
  418. /*
  419. *********************************************************************************************************
  420. * POST TO A SEMAPHORE
  421. *
  422. * Description: This function signals a semaphore
  423. *
  424. * Arguments : pevent is a pointer to the event control block associated with the desired
  425. * semaphore.
  426. *
  427. * Returns : OS_ERR_NONE The call was successful and the semaphore was signaled.
  428. * OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have
  429. * signalled the semaphore more often than you waited on it with either
  430. * OSSemAccept() or OSSemPend().
  431. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
  432. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  433. *********************************************************************************************************
  434. */
  435. INT8U OSSemPost (OS_EVENT *pevent)
  436. {
  437. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  438. OS_CPU_SR cpu_sr = 0u;
  439. #endif
  440. #if OS_ARG_CHK_EN > 0u
  441. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  442. return (OS_ERR_PEVENT_NULL);
  443. }
  444. #endif
  445. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  446. return (OS_ERR_EVENT_TYPE);
  447. }
  448. OS_ENTER_CRITICAL();
  449. if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */
  450. /* Ready HPT waiting on event */
  451. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
  452. OS_EXIT_CRITICAL();
  453. OS_Sched(); /* Find HPT ready to run */
  454. return (OS_ERR_NONE);
  455. }
  456. if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */
  457. pevent->OSEventCnt++; /* Increment semaphore count to register event */
  458. OS_EXIT_CRITICAL();
  459. return (OS_ERR_NONE);
  460. }
  461. OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */
  462. return (OS_ERR_SEM_OVF);
  463. }
  464. /*$PAGE*/
  465. /*
  466. *********************************************************************************************************
  467. * QUERY A SEMAPHORE
  468. *
  469. * Description: This function obtains information about a semaphore
  470. *
  471. * Arguments : pevent is a pointer to the event control block associated with the desired
  472. * semaphore
  473. *
  474. * p_sem_data is a pointer to a structure that will contain information about the
  475. * semaphore.
  476. *
  477. * Returns : OS_ERR_NONE The call was successful and the message was sent
  478. * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore.
  479. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  480. * OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer
  481. *********************************************************************************************************
  482. */
  483. #if OS_SEM_QUERY_EN > 0u
  484. INT8U OSSemQuery (OS_EVENT *pevent,
  485. OS_SEM_DATA *p_sem_data)
  486. {
  487. INT8U i;
  488. OS_PRIO *psrc;
  489. OS_PRIO *pdest;
  490. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  491. OS_CPU_SR cpu_sr = 0u;
  492. #endif
  493. #if OS_ARG_CHK_EN > 0u
  494. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  495. return (OS_ERR_PEVENT_NULL);
  496. }
  497. if (p_sem_data == (OS_SEM_DATA *)0) { /* Validate 'p_sem_data' */
  498. return (OS_ERR_PDATA_NULL);
  499. }
  500. #endif
  501. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  502. return (OS_ERR_EVENT_TYPE);
  503. }
  504. OS_ENTER_CRITICAL();
  505. p_sem_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
  506. psrc = &pevent->OSEventTbl[0];
  507. pdest = &p_sem_data->OSEventTbl[0];
  508. for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
  509. *pdest++ = *psrc++;
  510. }
  511. p_sem_data->OSCnt = pevent->OSEventCnt; /* Get semaphore count */
  512. OS_EXIT_CRITICAL();
  513. return (OS_ERR_NONE);
  514. }
  515. #endif /* OS_SEM_QUERY_EN */
  516. /*$PAGE*/
  517. /*
  518. *********************************************************************************************************
  519. * SET SEMAPHORE
  520. *
  521. * Description: This function sets the semaphore count to the value specified as an argument. Typically,
  522. * this value would be 0.
  523. *
  524. * You would typically use this function when a semaphore is used as a signaling mechanism
  525. * and, you want to reset the count value.
  526. *
  527. * Arguments : pevent is a pointer to the event control block
  528. *
  529. * cnt is the new value for the semaphore count. You would pass 0 to reset the
  530. * semaphore count.
  531. *
  532. * perr is a pointer to an error code returned by the function as follows:
  533. *
  534. * OS_ERR_NONE The call was successful and the semaphore value was set.
  535. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  536. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  537. * OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
  538. *********************************************************************************************************
  539. */
  540. #if OS_SEM_SET_EN > 0u
  541. void OSSemSet (OS_EVENT *pevent,
  542. INT16U cnt,
  543. INT8U *perr)
  544. {
  545. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  546. OS_CPU_SR cpu_sr = 0u;
  547. #endif
  548. #ifdef OS_SAFETY_CRITICAL
  549. if (perr == (INT8U *)0) {
  550. OS_SAFETY_CRITICAL_EXCEPTION();
  551. }
  552. #endif
  553. #if OS_ARG_CHK_EN > 0u
  554. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  555. *perr = OS_ERR_PEVENT_NULL;
  556. return;
  557. }
  558. #endif
  559. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  560. *perr = OS_ERR_EVENT_TYPE;
  561. return;
  562. }
  563. OS_ENTER_CRITICAL();
  564. *perr = OS_ERR_NONE;
  565. if (pevent->OSEventCnt > 0u) { /* See if semaphore already has a count */
  566. pevent->OSEventCnt = cnt; /* Yes, set it to the new value specified. */
  567. } else { /* No */
  568. if (pevent->OSEventGrp == 0u) { /* See if task(s) waiting? */
  569. pevent->OSEventCnt = cnt; /* No, OK to set the value */
  570. } else {
  571. *perr = OS_ERR_TASK_WAITING;
  572. }
  573. }
  574. OS_EXIT_CRITICAL();
  575. }
  576. #endif
  577. #endif /* OS_SEM_EN */