1 / 41

Chapter 6 Intertask Communication & Sysnchronization

Chapter 6 Intertask Communication & Sysnchronization. Semaphores, message mailboxes, and message queue. Figure 6.1 use of event control blocks (ECB). Event Control Blocks. Each semaphore, mailbox, and queue is assigned an ECB. typedef struct {

basil
Download Presentation

Chapter 6 Intertask Communication & Sysnchronization

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 6Intertask Communication & Sysnchronization Semaphores, message mailboxes, and message queue

  2. Figure 6.1 use of event control blocks (ECB)

  3. Event Control Blocks • Each semaphore, mailbox, and queue is assigned an ECB typedef struct { void *OSEventPtr; /* Ptr to message or queue structure */ INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* Wait list for event to occur */ INT16U OSEventCnt; /* Count (when event is a semaphore) */ INT8U OSEventType; /* Event type */ INT8U OSEventGrp; /* Group for wait list */ } OS_EVENT; • OSEventPtr: only used when the ECB is assigned to a mailbox or a queue • OSEventTbl[] and OSEventGrp are similar to OSRdyTbl[ and OSRdyGrp, respectively • OSEventCnt: used to hold the semaphore count • OSEventType: contains the type associated with the ECB • OS_EVENT_SEM, OS_EVENT_TYPE_MBOX, OS_EVENT_TYPE_Q

  4. Figure 6.2 Wait list for task waiting for an event to occur

  5. pevent->OSEventGrp |= OSMapTbl[prio >> 3]; pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; Making a task wait for an event Removing a task from a wait list if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) { pevent->OSEventGrp &= ~OSMapTbl[prio >> 3]; } Finding the highest priority task waiting for the event y = OSUnMapTbl[pevent->OSEventGrp]; x = OSUnMapTbl[pevent->OSEventTbl[y]]; prio = (y << 3) + x;

  6. Figure 6.3 List of free ECBs • The number of ECBs to allocate depends on the number of semaphores, mailboxes, and queues needed for your application • When OSInit() is called, all ECBs are linked in a singly linked list • The list of free ECBs

  7. Four common operations can be performed on ECBs • Initialize an ECB • Make a task ready • Make a task wait for an event • Make a task ready because a timeout occurred while waiting for an event • Four functions have been created to performs these operations • OSEventWaitListInit() • OSEventTaskRdy() • OSEventWait() • OSEventTO()

  8. Initializing an ECBOSEventWaitListInit() • Is called by OSSemCreate(), OSMboxCreate (), OSQCreate () • No task is waiting on the ECB void OSEventWaitListInit (OS_EVENT *pevent) { INT8U i; pevent->OSEventGrp = 0x00; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { pevent->OSEventTbl[i] = 0x00; } }

  9. Making a task readyOSEventTaskRdy() • This function is called by • OSSemPost(), OSMbosPost(), OSQPost(), and OSQPostFront() • Removes the highest priority task (HPT) from the wait list of the ECB and makes this task ready to run void OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk) { OS_TCB *ptcb; INT8U x; INT8U y; INT8U bitx; INT8U bity; INT8U prio;

  10. y = OSUnMapTbl[pevent->OSEventGrp]; (1) bity = OSMapTbl[y]; (2) x = OSUnMapTbl[pevent->OSEventTbl[y]]; (3) bitx = OSMapTbl[x]; (4) prio = (INT8U)((y << 3) + x); (5) if ((pevent->OSEventTbl[y] &= ~bitx) == 0) { (6) pevent->OSEventGrp &= ~bity; } ptcb = OSTCBPrioTbl[prio]; (7) ptcb->OSTCBDly = 0; (8) ptcb->OSTCBEventPtr = (OS_EVENT *)0; (9) #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN ptcb->OSTCBMsg = msg; (10) #else msg = msg; #endif ptcb->OSTCBStat &= ~msk; (Semaphore,mail box, mail queue) (11) if (ptcb->OSTCBStat == OS_STAT_RDY) { (12) OSRdyGrp |= bity; (13) OSRdyTbl[y] |= bitx; } } OSEventTaskRdy (cont’d)

  11. Figure 6.4 Making a task ready to run

  12. Making a task wait for an eventOSEventTaskWait() • Called by OSSemPend(), OSMboxPend, and OSQPend() when a task must wait on an ECB • OSEventTaskWait() removes the current task from the ready list and places it in the wait list of the ECB void OSEventTaskWait (OS_EVENT *pevent) { OSTCBCur->OSTCBEventPtr = pevent; (1) if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (2) OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; (3) pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; }

  13. Making a task ready becase of a timeoutOSEventTO() • Called by OSSemPend(), OSMboxPend(), OSQPend() when a task has been made ready to run by OSTimeTick() • OSEventTO() must remove the task from the wait list of the ECB and mark the task as being ready void OSEventTO (OS_EVENT *pevent) { if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (1) pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBStat = OS_STAT_RDY; (2) OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (3) }

  14. Semaphores • Create a semaphore by calling OSSemCreate() • The initial count of the semaphore can be 0 to 65535 • Use to signal the occurrence of one ore more event, the init value is 0 (flag) • Use to access a shared resource, the init value is set to 1 (binary) (key) • Five services will access semaphore: • OSSemCreate(), OSSemPend(), OSSemPost(), OSSemAccept(), OSSemQuery() Figure 6.5 Relationships between tasks, ISRs, and a semaphore

  15. Creating a SemaphoreOSSemCreate() OS_EVENT *OSSemCreate (INT16U cnt) { OS_EVENT *pevent; OS_ENTER_CRITICAL(); pevent = OSEventFreeList; (1) if (OSEventFreeList != (OS_EVENT *)0) { (2) OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } OS_EXIT_CRITICAL(); if (pevent != (OS_EVENT *)0) { (3) pevent->OSEventType = OS_EVENT_TYPE_SEM; (4) pevent->OSEventCnt = cnt; (5) OSEventWaitListInit(pevent); (6) } return (pevent); (7) }

  16. Waiting on a SemaphoreOSSemPend() void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) { OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1) OS_EXIT_CRITICAL(); *err = OS_ERR_EVENT_TYPE; } if (pevent->OSEventCnt > 0) { (2) pevent->OSEventCnt--; (3) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } else if (OSIntNesting > 0) { (4) OS_EXIT_CRITICAL(); *err = OS_ERR_PEND_ISR; } else { OSTCBCur->OSTCBStat |= OS_STAT_SEM; (5) OSTCBCur->OSTCBDly = timeout; (6) OSEventTaskWait(pevent); (7) OS_EXIT_CRITICAL(); OSSched(); (8) OS_ENTER_CRITICAL(); if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { (9) OSEventTO(pevent); (10) OS_EXIT_CRITICAL(); *err = OS_TIMEOUT; } else { OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } } }

  17. Signaling a SemaphoreOSSemPost() INT8U OSSemPost (OS_EVENT *pevent) { OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } if (pevent->OSEventGrp) { (2) OSEventTaskRdy(pevent, (void *)0, OS_STAT_SEM); (3) OS_EXIT_CRITICAL(); OSSched(); (4) return (OS_NO_ERR); } else { if (pevent->OSEventCnt < 65535) { pevent->OSEventCnt++; (5) OS_EXIT_CRITICAL(); return (OS_NO_ERR); } else { OS_EXIT_CRITICAL(); return (OS_SEM_OVF); } } }

  18. Getting a Semaphore without WaitingOSSemAccept() • To obtain a semaphore without putting a task to sleep if the semaphore is not available INT16U OSSemAccept (OS_EVENT *pevent) { INT16U cnt; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1) OS_EXIT_CRITICAL(); return (0); } cnt = pevent->OSEventCnt; (2) if (cnt > 0) { (3) pevent->OSEventCnt--; (4) } OS_EXIT_CRITICAL(); return (cnt); (5) }

  19. Obaining the status of a semaphoreOSSemQuery() • Allow APs to take a snapshot of an ECB • Two arguments are required • Pevent: pointer to the semaphore • Pdata pointer to a data structure which will receive the information about the desired semaphore INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata) { INT8U i; INT8U *psrc; INT8U *pdest; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } pdata->OSEventGrp = pevent->OSEventGrp; (2) psrc = &pevent->OSEventTbl[0]; pdest = &pdata->OSEventTbl[0]; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { *pdest++ = *psrc++; } pdata->OSCnt = pevent->OSEventCnt; (3) OS_EXIT_CRITICAL(); return (OS_NO_ERR); }

  20. Message Mailboxes • Allow a task or an ISR to send a pointer-sized variable to another task • Five services to access mailboxes • OSMboxCreate(), OSMboxPend(), OSMboxPost(), OSMboxAccept(), OSMboxQuery Figure 6.6 Relationships between tasks, ISRs, and a message mailbox

  21. Creating a Mailbox -- OSMboxCreate() • Similar to OSSemCreate() • Use OSEventPtr to instead of the OSEventCnt • Return a pointer to the ECB, such as mailbox handle OS_EVENT *OSMboxCreate (void *msg) { OS_EVENT *pevent; OS_ENTER_CRITICAL(); pevent = OSEventFreeList; if (OSEventFreeList != (OS_EVENT *)0) { OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } OS_EXIT_CRITICAL(); if (pevent != (OS_EVENT *)0) { pevent->OSEventType = OS_EVENT_TYPE_MBOX; (1) pevent->OSEventPtr = msg; (2) OSEventWaitListInit(pevent); } return (pevent); (3) }

  22. Waiting for a Message at a MailboxOSMboxPend() • Similar to OSSemPend() void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) { void *msg; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1) OS_EXIT_CRITICAL(); *err = OS_ERR_EVENT_TYPE; return ((void *)0); } msg = pevent->OSEventPtr; if (msg != (void *)0) { (2) pevent->OSEventPtr = (void *)0; (3) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } else if (OSIntNesting > 0) { (4) OS_EXIT_CRITICAL(); *err = OS_ERR_PEND_ISR;

  23. Waiting for a message to arrive at a mailbox (cont’d) } else { OSTCBCur->OSTCBStat |= OS_STAT_MBOX; (5) OSTCBCur->OSTCBDly = timeout; OSEventTaskWait(pevent); OS_EXIT_CRITICAL(); OSSched(); OS_ENTER_CRITICAL(); if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { (6) OSTCBCur->OSTCBMsg = (void *)0; OSTCBCur->OSTCBStat = OS_STAT_RDY; OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) { (7) OSEventTO(pevent); (8) OS_EXIT_CRITICAL(); msg = (void *)0; (9) *err = OS_TIMEOUT; } else { msg = pevent->OSEventPtr; (10) pevent->OSEventPtr = (void *)0; OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } } return (msg); }

  24. Sending a Message to a MailboxOSMboxPost() INT8U OSMboxPost (OS_EVENT *pevent, void *msg) { OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } if (pevent->OSEventGrp) { (2) OSEventTaskRdy(pevent, msg, OS_STAT_MBOX); (3) OS_EXIT_CRITICAL(); OSSched(); (4) return (OS_NO_ERR); } else { if (pevent->OSEventPtr != (void *)0) { (5) OS_EXIT_CRITICAL(); return (OS_MBOX_FULL); } else { pevent->OSEventPtr = msg; (6) OS_EXIT_CRITICAL(); return (OS_NO_ERR); } } }

  25. Getting a Message without WaitingOSMboxAccept() void *OSMboxAccept (OS_EVENT *pevent) { void *msg; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1) OS_EXIT_CRITICAL(); return ((void *)0); } msg = pevent->OSEventPtr; (2) if (msg != (void *)0) { (3) pevent->OSEventPtr = (void *)0; (4) } OS_EXIT_CRITICAL(); return (msg); (5) }

  26. Obtaining the status of a MailboxOSMboxQuery() INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata) { INT8U i; INT8U *psrc; INT8U *pdest; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } pdata->OSEventGrp = pevent->OSEventGrp; (2) psrc = &pevent->OSEventTbl[0]; pdest = &pdata->OSEventTbl[0]; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { *pdest++ = *psrc++; } pdata->OSMsg = pevent->OSEventPtr; (3) OS_EXIT_CRITICAL(); return (OS_NO_ERR); }

  27. Using a Mailbox as a Binary Semaphore • Initializing the mailbox with a non-NULL pointer (ex void *1) as a binary semaphore OS_EVENT *MboxSem; void Task1 (void *pdata) { INT8U err; for (;;) { OSMboxPend(MboxSem, 0, &err); /* Obtain access to resource(s) */ . . /* Task has semaphore, access resource(s) */ . OSMboxPost(MboxSem, (void )1); /* Release access to resource(s) */ } }

  28. Using a Mailbox instead of OSTimeDly() OS_EVENT *MboxTimeDly; void Task1 (void *pdata) { INT8U err; for (;;) { OSMboxPend(MboxTimeDly, TIMEOUT, &err); /* Delay task */ . . /* Code executed after time delay */ . } } void Task2 (void *pdata) { INT8U err; for (;;) { OSMboxPost(MboxTimeDly, (void *)1); /* Cancel delay for Task1 */ . . } } • Task1() resumes execution after the time period expires if no message is received • Task2() post a “dummy” message to the mailbox before the timeout expires. • Same as calling OSTimeDlyResume()

  29. Message Queue • Seven services to access message queues • OSQCreate(), OSQPend(), OSQPost(), OSQPostFront(), OSQAccept(), OSQFlush(), and OSQQuery Figure 6.7 Relationships between tasks, ISRs, and a message queue

  30. Figure 6.8 Data structures used in a message queue

  31. Figure 6.9 List of free queue control blocks Figure 6.10 A message queue is a circular buffer of pointers

  32. OS_EVENT *OSQCreate (void **start, INT16U size) { OS_EVENT *pevent; OS_Q *pq; OS_ENTER_CRITICAL(); pevent = OSEventFreeList; (1) if (OSEventFreeList != (OS_EVENT *)0) { OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; (2) } OS_EXIT_CRITICAL(); if (pevent != (OS_EVENT *)0) { OS_ENTER_CRITICAL(); pq = OSQFreeList; (3) if (OSQFreeList != (OS_Q *)0) { OSQFreeList = OSQFreeList->OSQPtr; } OS_EXIT_CRITICAL(); if (pq != (OS_Q *)0) { pq->OSQStart = start; (4) pq->OSQEnd = &start[size]; pq->OSQIn = start; pq->OSQOut = start; pq->OSQSize = size; pq->OSQEntries = 0; pevent->OSEventType = OS_EVENT_TYPE_Q; (5) pevent->OSEventPtr = pq; (6) OSEventWaitListInit(pevent); (7) } else { OS_ENTER_CRITICAL(); pevent->OSEventPtr = (void *)OSEventFreeList; (8) OSEventFreeList = pevent; OS_EXIT_CRITICAL(); pevent = (OS_EVENT *)0; } } return (pevent); (9) } Creating a queue, OSQCreate()

  33. Waiting for a Message at a Queue, OSQPend() void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) { void *msg; OS_Q *pq; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1) OS_EXIT_CRITICAL(); *err = OS_ERR_EVENT_TYPE; return ((void *)0); } pq = pevent->OSEventPtr; if (pq->OSQEntries != 0) { (2) msg = *pq->OSQOut++; (3) pq->OSQEntries--; (4) if (pq->OSQOut == pq->OSQEnd) { (5) pq->OSQOut = pq->OSQStart; (6) } OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } else if (OSIntNesting > 0) { (7) OS_EXIT_CRITICAL(); *err = OS_ERR_PEND_ISR;

  34. } else { OSTCBCur->OSTCBStat |= OS_STAT_Q; (8) OSTCBCur->OSTCBDly = timeout; OSEventTaskWait(pevent); OS_EXIT_CRITICAL(); OSSched(); (9) OS_ENTER_CRITICAL(); if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { (10) OSTCBCur->OSTCBMsg = (void *)0; OSTCBCur->OSTCBStat = OS_STAT_RDY; OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } else if (OSTCBCur->OSTCBStat & OS_STAT_Q) { (12) OSEventTO(pevent); (13) OS_EXIT_CRITICAL(); msg = (void *)0; (14) *err = OS_TIMEOUT; } else { msg = *pq->OSQOut++; (15) pq->OSQEntries--; if (pq->OSQOut == pq->OSQEnd) { pq->OSQOut = pq->OSQStart; } OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (16) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; } } return (msg); (17) }

  35. 6.23 Depositing a message in a queue (FIFO) INT8U OSQPost (OS_EVENT *pevent, void *msg) { OS_Q *pq; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } if (pevent->OSEventGrp) { (2) OSEventTaskRdy(pevent, msg, OS_STAT_Q); (3) OS_EXIT_CRITICAL(); OSSched(); return (OS_NO_ERR); } else { pq = pevent->OSEventPtr; if (pq->OSQEntries >= pq->OSQSize) { (4) OS_EXIT_CRITICAL(); return (OS_Q_FULL); } else { *pq->OSQIn++ = msg; (5) pq->OSQEntries++; if (pq->OSQIn == pq->OSQEnd) { pq->OSQIn = pq->OSQStart; } OS_EXIT_CRITICAL(); } return (OS_NO_ERR); } }

  36. Sending a message to a queue (LIFO), OSQPostFront() INT8U OSQPostFront (OS_EVENT *pevent, void *msg) { OS_Q *pq; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } if (pevent->OSEventGrp) { OSEventTaskRdy(pevent, msg, OS_STAT_Q); OS_EXIT_CRITICAL(); OSSched(); return (OS_NO_ERR); } else { pq = pevent->OSEventPtr; if (pq->OSQEntries >= pq->OSQSize) { OS_EXIT_CRITICAL(); return (OS_Q_FULL); } else { if (pq->OSQOut == pq->OSQStart) { (1) pq->OSQOut = pq->OSQEnd; (2) } pq->OSQOut--; (3) *pq->OSQOut = msg; pq->OSQEntries++; OS_EXIT_CRITICAL(); } return (OS_NO_ERR); } }

  37. Getting a message without waiting, OSQAccept() void *OSQAccept (OS_EVENT *pevent) { void *msg; OS_Q *pq; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1) OS_EXIT_CRITICAL(); return ((void *)0); } pq = pevent->OSEventPtr; if (pq->OSQEntries != 0) { (2) msg = *pq->OSQOut++; (3) pq->OSQEntries--; if (pq->OSQOut == pq->OSQEnd) { pq->OSQOut = pq->OSQStart; } } else { msg = (void *)0; (4) } OS_EXIT_CRITICAL(); return (msg); }

  38. Flushing a queue, OSQFlush() INT8U OSQFlush (OS_EVENT *pevent) { OS_Q *pq; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } pq = pevent->OSEventPtr; pq->OSQIn = pq->OSQStart; (2) pq->OSQOut = pq->OSQStart; pq->OSQEntries = 0; OS_EXIT_CRITICAL(); return (OS_NO_ERR); }

  39. Using a message queue when reading analog inputs

  40. Using a queue as a counting semaphore OS_EVENT *QSem; void *QMsgTbl[N_RESOURCES] void main (void) { OSInit(); . QSem = OSQCreate(&QMsgTbl[0], N_RESOURCES); for (i = 0; i < N_RESOURCES; i++) { OSQPost(Qsem, (void *)1); } . OSTaskCreate(Task1, .., .., ..); . OSStart(); } void Task1 (void *pdata) { INT8U err; for (;;) { OSQPend(&QSem, 0, &err); /* Obtain access to resource(s) */ . . /* Task has semaphore, access resource(s) */ . OSMQPost(QSem, (void )1); /* Release access to resource(s) */ } }

  41. Obtaining the status of a queue, OSQQuery() INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata) { OS_Q *pq; INT8U i; INT8U *psrc; INT8U *pdest; OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1) OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } pdata->OSEventGrp = pevent->OSEventGrp; (2) psrc = &pevent->OSEventTbl[0]; pdest = &pdata->OSEventTbl[0]; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { *pdest++ = *psrc++; } pq = (OS_Q *)pevent->OSEventPtr; if (pq->OSQEntries > 0) { (3) pdata->OSMsg = pq->OSQOut; (4) } else { pdata->OSMsg = (void *)0; (5) } pdata->OSNMsgs = pq->OSQEntries; (6) pdata->OSQSize = pq->OSQSize; OS_EXIT_CRITICAL(); return (OS_NO_ERR); }

More Related