1 / 11

Chapter7 Semaphore Management

Chapter7 Semaphore Management. 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)

tess
Télécharger la présentation

Chapter7 Semaphore Management

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. Chapter7 Semaphore Management

  2. 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 7.1 Relationships between tasks, ISRs, and a semaphore

  3. 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); //semaphore address or say descriptor (7) }

  4. Figure 7.2 ECB just before OSSemCreate() returns OS_EVENT pevent OSEventType OS_Evnet_Type_SEM OSEventCnt Cnt OSEventPtr (void *)0 OSEvnetGrp=0x00 OSEventGrp 7 6 5 4 3 2 1 0 All initialized to 0x00 63 62 61 60 59 58 57 56

  5. Deleting a Semaphore, OSSemDel() #if OS_SEM_DEL_EN > 0 OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif BOOLEAN tasks_waiting; if (OSIntNesting > 0) { /* See if called from ISR ... */ *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *err = OS_ERR_PEVENT_NULL; return (pevent); } if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *err = OS_ERR_EVENT_TYPE; return (pevent); } #endif

  6. OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on semaphore */ tasks_waiting = TRUE; /* Yes */ } else { tasks_waiting = FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ if (tasks_waiting == FALSE) { pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return ((OS_EVENT *)0); /* Semaphore has been deleted */ } else { OS_EXIT_CRITICAL(); *err = OS_ERR_TASK_WAITING; return (pevent); }

  7. case OS_DEL_ALWAYS: /* Always delete the semaphore */ while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for semaphore */ OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); } pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *err = OS_NO_ERR; return ((OS_EVENT *)0); /* Semaphore has been deleted */ default: OS_EXIT_CRITICAL(); *err = OS_ERR_INVALID_OPT; return (pevent); } } #endif

  8. 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; return; 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; return; } OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; }

  9. 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); } if (pevent->OSEventCnt < 65535) { pevent->OSEventCnt++; (5) OS_EXIT_CRITICAL(); return (OS_NO_ERR); } OS_EXIT_CRITICAL(); return (OS_SEM_OVF); }

  10. 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); //original value (5) }

  11. 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); }

More Related