Chapter 07
Chapter 07
Semaphore Management
1
Semaphores
• A 16-bit unsigned integer used to hold the
semaphore count (0 to 65535)
– Counting semaphore
2
Semaphore Management
• OSSemCreate()
Creating a semaphore
• OSSemDel()
Deleting a semaphore
• OSSemPend
Waiting on a semaphore
• OSSemPost
Signaling a semaphore
• OSSemAccept()
Getting a Semaphore without waiting
3
Relationships between tasks,ISR, and a
semaphore
OSSemPend()
OSSemAccept() Task
Task OSSemPost() OSSemQuery()
N
OR
4
OSSemCreate()
5
OSSemDel()
• pevent is a pointer to the ECB associated with
the desired semaphore.
• opt determines delete options as follows:
– OS_DEL_NO_PEND
Delete semaphore ONLY if no task pending
– OS_DEL_ALWAYS
Deletes the semaphore even if tasks are waiting. In this
case, all the tasks pending will be readied.
6
OSSemDel()
Event Control Block
opt =?
N
EventGrp = 0 EventGrp = 0
Y
1
EventTbl N Y
1 1
EventTaskRdy
EventTaskRdy Free(Sem)
N
EventGrp ==00
EventGrp
reterun err
Y 7
OSSemDel()
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err) {
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { See if any tasks waiting on semaphore
tasks_waiting = TRUE;
} else tasks_waiting = FALSE; Delete semaphore only if no task waiting
switch (opt) {
case OS_DEL_NO_PEND: Return Event
if (tasks_waiting == FALSE) { Control Block to
pevent->OSEventType = OS_EVENT_TYPE_UNUSED; free list
pevent->OSEventPtr = OSEventFreeList;
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_EVENT *)0);
} else {
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pevent); 8
}
OSSemDel()
case OS_DEL_ALWAYS: Always delete the semaphore
while (pevent->OSEventGrp != 0x00) { Ready ALL
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); tasks waiting
} for semaphore
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList;
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE) {
OS_Sched();
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0);
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
9
}
OSSemDel()
• This call can potentially disable interrupts for a
long time.
– The interrupt disable time is directly proportional
to the number of tasks waiting on the semaphore.
• Because all tasks pending on the semaphore
will be readied, you must be careful in
applications where the semaphore is used for
mutual exclusion.
10
OSSemPend()
Example 1: OSEventCnt=1
task1() {
/*…*/
OSSemPend();
/*…*/
}
User mode
?(OSEventCnt>0)
return;
11
OSSemPend()
Example 2: OSEventCnt=0
task1() {
/*…*/ task2() {
OSSemPend(); /*…*/
/*…*/ OSSemPost();
} /*…*/
}
OSSemPend() {
OSSemPost() { Kernel mode
?(OSEventCnt>0) EventTaskRdy()
wait(pevent); OS_Sched()
sched(); return;
?(status == Rdy)
return; }
}
User mode
OSSemPend() {
?(OSEventCnt>0) OSSemPost() { Kernel mode
TCBDly=3; EventTaskRdy()
wait(pevent); OS_Sched()
sched() return;
?(status != Rdy)
OS_EventTO() }
return;
}
Task Running
OS_STAT_SEM
0
1
2
3
13
OSSemPend()
14
OSSemPend()
The semaphore is not
available.
Timeout
15
OSSemPost()
Increment the
semaphore
count 16
OSSemAccept()
17
OSSemQuery()
.
.
.
18