Semaphore
Semaphore
Process P Process C
wait(consumed) signal(consumed)
disable(ps); interrupts are disabled disable(ps); interrupts are disabled
sptr = &semaph[sem]; sptr = &semaph[sem];
if (--sptr->semcnt < 0 ) { if (sptr->semcnt++ < 0 ) {
(pptr = &proctab[currpid])->pstate = PRWAIT; ready(getfirst (sptr->sqhead));
pptr->psem = sem; resched( ); }
enquue(currpid, sptr->sqtail); restore(ps); interrupts are enabled
resched( ); } return;
restore(ps); interrupts are enabled
return;
/* sem.h - isbadsem */
#ifndef NSEM
#define NSEM 45 /* number of semaphores, if not defined */
#endif
#include "conf.h"
#include "kernel.h"
#include "proc.h"
#include "q.h"
#include "sem.h"
/*------------------------------------------------------------------------*/
/* newsem -- allocate an unused semaphore and return its index */
/*------------------------------------------------------------------------*/
int newsem(void)
{
int sem;
int i;
ps = disable();
if ( count<0 || (sem=newsem())==SYSERR ) {
restore(ps);
return(SYSERR);
}
semaph[sem].semcnt = count;
/* sqhead and sqtail were initialized at system startup */
restore(ps);
return(sem);
}
/*------------------------------------------------------------------------
* sdelete -- delete a semaphore by releasing its table entry
*------------------------------------------------------------------------
*/
SYSCALL sdelete(int sem)
{
short ps;
int pid;
struct sentry *sptr; /* address of sem to free */
ps = disable();
if (isbadsem(sem) || semaph[sem].sstate==SFREE) {
restore(ps);
return(SYSERR);
}
sptr = &semaph[sem];
sptr->sstate = SFREE;
if (nonempty(sptr->sqhead)) { /* free waiting processes */
while( (pid=getfirst(sptr->sqhead)) != EMPTY)
ready(pid,RESCHNO);
resched();
}
restore(ps);
return(OK);
}
/*------------------------------------------------------------------------*/
/* signal -- signal a semaphore, releasing one waiting process */
/*------------------------------------------------------------------------*/
ps = disable();
if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) {
restore(ps);
return(SYSERR);
}
if ((sptr->semcnt++) < 0)
ready(getfirst(sptr->sqhead), RESCHYES);
restore(ps);
return(OK);
}
/*------------------------------------------------------------------------*/
/* wait -- make current process wait on a semaphore */
/*------------------------------------------------------------------------*/
ps = disable();
if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) {
restore(ps);
return(SYSERR);
}
if (--(sptr->semcnt) < 0) {
(pptr = &proctab[currpid])->pstate = PRWAIT;
pptr->psem = sem;
enqueue(currpid,sptr->sqtail);
resched();
}
restore(ps);
return(OK);
}