Struct Cours6 e 4
Struct Cours6 e 4
158 159
Implementing Semaphores
Mutual exclusion with semaphores • Semaphores are implemented in the system kernel.
Semaphores make a very simple implementation of mutual exclusion – The semaphore values are kept in a table stored in kernel memory.
possible. A semaphore is identified by a number corresponding to a position
in this table.
semaphore s = 1; – There are system calls for creating or freeing semaphores, as well
as for executing the wait and signal operations. These operations
are executed in supervisor mode and hence atomically (interrupts
Process 1 : Process 2 :
are disabled in supervisor mode).
while (True) while (True)
{ nc1: /* non critical { nc2: /* non critical • In ULg03, to execute for instance a wait operation, the arguments of
section */ ; section */ the system call, i.e. the semaphore number and a code WAIT, are
wait(s); wait(s); placed on the stack. Assuming that the semaphore number is
crit1: /* critical section */ ; crit2: /* critical section */ contained in r0, this can be done as follows.
signal(s); signal(s) PUSH(r0) | 2nd argument
} } CMOVE(WAIT,r1) | 1st argument
PUSH(r1)
SVC() | system call
160 161
The SVC handler
Before getting into the details of the handlers for semaphore operations,
we will look at the general handler needed for the SVC instruction. The
The SVC handler (continued)
handler is reached through the following stub.
h_stub: ST(r0, User, r31) | save • The program Svc_handler identifies the nature of the call and switches
ST(r1, User+4, r31) | the registers to the corresponding routine.
. . .
ST(r30, User+30*4, r31)
• One difficulty is that the arguments of SVC are on the stack of the
CMOVE(KStack, SP) | Load the system SP
process that has executed the system call, i.e. in its virtual space.
BR(Svc_handler,LP) | Call the handler
LD(r31, User, r0) | restore
LD(r31, User+4, r1) • These addresses must thus be translated before being used.
LD(r31, User+30*4, r30)
JMP(XP) | return to application
Note that the address saved in XP is that of the instruction following SVC.
162 163
The SVC handler extracts the code identifying the call and switches to the
The handlers Wait_h and Signal_h: first version
corresponding function.
Signal_h(int semno)
{ for (i = 0; i<N; i++) {
The handlers Wait_h and Signal_h: second version
if (Proctbl[i].status == WAIT && Proctbl[i].semwait == semno)
Proctbl[i].status = RUN; Wait_h(int semno)
} { if (sem[semno] <= 0) {
sem[semno] = sem[semno] + 1; Proctbl[Cur].status = WAIT; Proctbl[Cur].semwait = semno;
} scheduler();
} else
sem[semno] = sem[semno] - 1;
The processes that are waiting on the semaphore are reactivated and the
}
semaphore is incremented.
The system call is not reexecuted when a process leaves its wait state.
All the waiting processes will reexecute the system call wait; the one that
Indeed, the handler for signal will take care of reactivating a waiting
will find a nonzero value for the semaphore can be anyone of these.
process if there is one, without the semaphore being incremented and
decremented.
For mutual exclusion, this implementation will not guarantee that each
process can access its critical section.
168 169
Signal_h(int semno) Implementing semaphores on a multiprocessor
{ int i,wokeup = 0;
for (i = 0; i<N; i++) {
if (Proctbl[i].status == WAIT && Proctbl[i].semwait == semno) { • On a multiprocessor machine, execution in supervisor mode does not
Proctbl[i].status = RUN; guarantee mutual exclusion since it can occur simultaneously on more
wokeup = 1; break; than one processor.
}
} • Another mechanism for implementing mutual exclusion is thus needed.
if (wokeup == 0) sem[semno] = sem[semno] + 1;
}
• Atomic memory reads and writes are not sufficient for a practical
This implementation guarantees that, if only two processes use the solution.
semaphore, none will wait indefinitely.
170 171
172 173
The ”buffer” or ”producer-consumer” problem
Mutual exclusion with TCLR
A Producer process sends a stream of information to a Consumer process.
It is quite simple to implement mutual exclusion with TCLR.
This stream of information goes through a buffer modeled as a table in
shared memory accessed with the two functions (append and take).
wait: TCLR(r31,lock,r0)
BEQ(r0,wait) /* shared memory */
int in = 0, out = 0;
... section critique ... int buf[N];
174 175
176 177
The buffer problem:
Mutual exclusion of the operations
Conclusions on semaphores
184