SYSCALL wait(int sem) { if(trace) wait_count[currpid]++; STATWORD ps; struct sentry *sptr; struct pentry *pptr; disable(ps); 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); pptr->pwaitret = OK; resched(); restore(ps); return pptr->pwaitret; } restore(ps); return(OK); }
/*------------------------------------------------------------------------ * wait -- make current process wait on a semaphore *------------------------------------------------------------------------ */ SYSCALL wait(int sem) { unsigned long timer_start_value=ctr1000; if(start_summary==1) { summary_tab[currpid][26].syscall_name="sys_wait"; summary_tab[currpid][26].frequency+=1; } STATWORD ps; struct sentry *sptr; struct pentry *pptr; disable(ps); if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) { restore(ps); summary_tab[currpid][26].time+=ctr1000-timer_start_value; return(SYSERR); } if (--(sptr->semcnt) < 0) { (pptr = &proctab[currpid])->pstate = PRWAIT; pptr->psem = sem; enqueue(currpid,sptr->sqtail); pptr->pwaitret = OK; resched(); restore(ps); summary_tab[currpid][26].time+=ctr1000-timer_start_value; return pptr->pwaitret; } restore(ps); summary_tab[currpid][26].time+=ctr1000-timer_start_value; return(OK); }
/*------------------------------------------------------------------------ * semreset - Reset a semaphore's count and release waiting processes *------------------------------------------------------------------------ */ syscall semreset( sid32 sem, /* ID of semaphore to reset */ int32 count /* New count (must be >= 0) */ ) { intmask mask; /* Saved interrupt mask */ struct sentry *semptr; /* Ptr to semaphore table entry */ qid16 semqueue; /* Semaphore's process queue ID */ pid32 pid; /* ID of a waiting process */ mask = disable(); if (count < 0 || isbadsem(sem) || semtab[sem].sstate==S_FREE) { restore(mask); return SYSERR; } semptr = &semtab[sem]; semqueue = semptr->squeue; /* Free any waiting processes */ resched_cntl(DEFER_START); while ((pid=getfirst(semqueue)) != EMPTY) ready(pid); semptr->scount = count; /* Reset count as specified */ resched_cntl(DEFER_STOP); restore(mask); return OK; }
/** * @ingroup semaphores * * Wait on a semaphore. * * If the semaphore's count is positive, it will be decremented and this * function will return immediately. Otherwise, the currently running thread * will be put to sleep until the semaphore is signaled with signal() or * signaln(), or freed with semfree(). * * @param sem * Semaphore to wait on. * * @return * ::OK on success; ::SYSERR on failure. This function can only fail if @p * sem did not specify a valid semaphore. */ syscall wait(semaphore sem) { register struct sement *semptr; register struct thrent *thrptr; irqmask im; im = disable(); if (isbadsem(sem)) //SDEFER is checked for inside this function in include/semaphore.h { restore(im); return SYSERR; } thrptr = &thrtab[thrcurrent]; semptr = &semtab[sem]; if (--(semptr->count) < 0) { thrptr->state = THRWAIT; thrptr->sem = sem; enqueue(thrcurrent, semptr->queue); resched(); } restore(im); return OK; }
/*------------------------------------------------------------------------ * wait - Cause current process to wait on a semaphore *------------------------------------------------------------------------ */ syscall wait( sid32 sem /* Semaphore on which to wait */ ) { intmask mask; /* Saved interrupt mask */ struct procent *prptr; /* Ptr to process's table entry */ struct sentry *semptr; /* Ptr to sempahore table entry */ mask = disable(); if (isbadsem(sem)) { restore(mask); return SYSERR; } semptr = &semtab[sem]; if (semptr->sstate == S_FREE) { restore(mask); return SYSERR; } if (--(semptr->scount) < 0) { /* If caller must block */ prptr = &proctab[currpid]; prptr->prstate = PR_WAIT; /* Set state to waiting */ prptr->prsem = sem; /* Record semaphore ID */ enqueue(currpid,semptr->squeue);/* Enqueue on semaphore */ resched(); /* and reschedule */ } restore(mask); return OK; }
/*------------------------------------------------------------------------ * signal -- signal a semaphore, releasing one waiting process *------------------------------------------------------------------------ */ SYSCALL signal(int sem) { //changes for incrementing count on syscall int start_time; if(call_active == 1) { call_used[currpid] = 1; call_frequency[currpid][3]++;//id for signal()=3 start_time = ctr1000; } STATWORD ps; register struct sentry *sptr; disable(ps); if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) { restore(ps); return(SYSERR); } if ((sptr->semcnt++) < 0) ready(getfirst(sptr->sqhead), RESCHYES); restore(ps); if(call_active == 1) { call_duration[currpid][3] += ctr1000 - start_time; } return(OK); }
/*------------------------------------------------------------------------ * wait -- make current process wait on a semaphore *------------------------------------------------------------------------ */ SYSCALL wait(int sem) { STATWORD ps; struct sentry *sptr; struct pentry *pptr; unsigned long stime = ctr1000; UPDATE_SCALL_FREQ(currpid, SCALL_WAIT); disable(ps); if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) { restore(ps); UPDATE_SCALL_TIME(currpid, SCALL_WAIT, stime); return(SYSERR); } if (--(sptr->semcnt) < 0) { (pptr = &proctab[currpid])->pstate = PRWAIT; pptr->psem = sem; enqueue(currpid,sptr->sqtail); pptr->pwaitret = OK; resched(); restore(ps); UPDATE_SCALL_TIME(currpid, SCALL_WAIT, stime); return pptr->pwaitret; } restore(ps); UPDATE_SCALL_TIME(currpid, SCALL_WAIT, stime); return(OK); }
/** * Deallocate a semaphore. * Reset the semaphore count, releasing any threads * in the waiting queue. Deallocate entry in global * semaphore table. * @param sem target semaphore * @return OK on success, SYSERR on failure */ syscall semfree(semaphore sem) { register struct sement *semptr; irqmask im; tid_typ tid; im = disable(); if (isbadsem(sem)) { restore(im); return SYSERR; } semptr = &semtab[sem]; while (nonempty(semptr->queue)) { tid = dequeue(semptr->queue); /* free waiting threads */ ready(tid, RESCHED_NO); } semptr->count = 0; semptr->state = SFREE; restore(im); return OK; }
/*------------------------------------------------------------------------ * sreset -- reset the count and queue of a semaphore *------------------------------------------------------------------------ */ SYSCALL sreset(int sem, int count) { int start; if(activated == 1) start = ctr1000; STATWORD ps; struct sentry *sptr; int pid; int slist; disable(ps); if (isbadsem(sem) || count<0 || semaph[sem].sstate==SFREE) { restore(ps); return(SYSERR); } sptr = &semaph[sem]; slist = sptr->sqhead; while ((pid=getfirst(slist)) != EMPTY) ready(pid,RESCHNO); sptr->semcnt = count; resched(); restore(ps); if(activated == 1) { Info[currpid][SRESET].freq++; Info[currpid][SRESET].time += (ctr1000 - start); } return(OK); }
/*------------------------------------------------------------------------ * scount -- return a semaphore count *------------------------------------------------------------------------ */ SYSCALL scount(int sem) { // added for PA0 tracing int start_time; int curridx = 10; if(syscall_trace_on == 1) { syscall_used[currpid] = 1; syscall_cnt[currpid][curridx]++; start_time = ctr1000; } extern struct sentry semaph[]; if (isbadsem(sem) || semaph[sem].sstate==SFREE) { // added for PA0 tracing if(syscall_trace_on == 1) { syscall_time[currpid][curridx] += ctr1000 - start_time; } return(SYSERR); } // added for PA0 tracing if(syscall_trace_on == 1) { syscall_time[currpid][curridx] += ctr1000 - start_time; } return(semaph[sem].semcnt); }
/* delete a semaphore by releasing its table entry */ SYSCALL KERNsdelete(int *ERRNO, int sem) { int mpid; struct sentry *sptr; /* address of sem to free */ disableps(); if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { enableps(); *ERRNO = EINVAL; return SYSERR; } sptr->sstate = SFREE; if (nonempty(sptr->squeue)) { while ((mpid = _getfirst(sptr->squeue)) != SYSERR) { /* _ready(kp->procTable[mpid].flpid,RESCHNO); */ if (kp->procTable[mpid].processState != procUNUSED) kp->procTable[mpid].processState = procREADY; } Qdispose(sptr->squeue); enableps(); _resched(); return OK; } Qdispose(sptr->squeue); enableps(); return OK; }
/*------------------------------------------------------------------------ * scount -- return a semaphore count *------------------------------------------------------------------------ */ SYSCALL scount(int sem) { extern struct sentry semaph[]; if (isbadsem(sem) || semaph[sem].sstate==SFREE) return(SYSERR); return(semaph[sem].semcnt); }
/* Cleanup semaphore due to signal causing EINTR */ void semINTR(int sem, int mpid) { struct sentry *sptr; if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) return; _dequeueitem(mpid, sptr->squeue); sptr->semcnt++; PROC->psem = -1; }
bool8 test_checkSemCount(sid32 s, short c, bool8 verbose) { char msg[50]; if (!isbadsem(s) && c != semcount(s)) { sprintf(msg, "count = %d, not %d", semcount(s), c); testFail(verbose, msg); return FALSE; } return TRUE; }
/*------------------------------------------------------------------------ * signal -- signal a semaphore, releasing one waiting process *------------------------------------------------------------------------ */ SYSCALL signal(register int sem) { register struct sentry *sptr; sigset_t ps; disable(ps); 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); }
SYSCALL Kscount(int *ERRNO, int sem) { struct sentry *sptr; int c; disableps(); if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { enableps(); *ERRNO = EINVAL; return SYSERR; } c = sptr->semcnt; enableps(); return c; /* BAH! This could be == SYSERR */ }
/*------------------------------------------------------------------------ * semcount - Return the count of a semaphore (because any integer is * possible, return of SYSERR may be ambiguous) *------------------------------------------------------------------------ */ syscall semcount( sid32 semid /* ID of semaphore to use */ ) { intmask mask; /* Saved interrupt mask */ int32 count; /* Current sempahore count */ mask = disable(); if (isbadsem(semid) || semtab[semid].sstate == S_FREE) { restore(mask); return SYSERR; } count = semtab[semid].scount; restore(mask); return count; }
//------------------------------------------------------------------------ // signal -- signal a semaphore, releasing one waiting process //------------------------------------------------------------------------ SYSCALL signal(int sem) { struct sentry *sptr; int ps; ps = disable(); if (isbadsem(sem) || (sptr = &semaph[sem])->sstate == SFREE) { restore(ps); return SYSERR; } if ((sptr->semcnt++) < 0) readysched(getfirst(sptr->sqhead)); restore(ps); return OK; }
/*------------------------------------------------------------------------ * signal -- signal a semaphore, releasing one waiting process *------------------------------------------------------------------------ */ SYSCALL signal(int sem) { STATWORD ps; register struct sentry *sptr; int curridx = 3; if(syscalltrace == 1) { syscallused[currpid] = 1; syscallcnt[currpid][curridx]++;} disable(ps); 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); }
SYSCALL sreset(int sem, int count) { STATWORD ps; struct sentry *sptr; int pid; int slist; disable(ps); if (isbadsem(sem) || count<0 || semaph[sem].sstate==SFREE) { restore(ps); return(SYSERR); } sptr = &semaph[sem]; slist = sptr->sqhead; while ((pid=getfirst(slist)) != EMPTY) ready(pid,RESCHNO); sptr->semcnt = count; resched(); restore(ps); return(OK); }
/*------------------------------------------------------------------------ * signal -- signal a semaphore, releasing one waiting process *------------------------------------------------------------------------ */ SYSCALL signal(int sem) { STATWORD ps; register struct sentry *sptr; disable(ps); if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) { restore(ps); return(SYSERR); } if ((sptr->semcnt++) < 0) ready(getfirst(sptr->sqhead), RESCHYES); restore(ps); if( syscalls_trace ) { signal_freq[currpid]++; } return(OK); }
/*------------------------------------------------------------------------ * wait -- make current process wait on a semaphore *------------------------------------------------------------------------ */ SYSCALL wait( int sem ) { register struct sentry *sptr; register struct pentry *pptr; sigset_t PS; disable( &PS ); if ( isbadsem( sem ) || ( sptr = &semaph[sem] )->sstate == SFREE ) { restore( &PS ); handle_error( "semwait: " ); return (SYSERR ); } if ( --( sptr->semcnt ) < 0 ) { ( pptr = &proctab[currpid] )->pstate = PRWAIT; pptr->psem = sem; enqueue( currpid, sptr->sqtail ); resched( ); } restore( &PS ); return (OK ); }
/* signal a semaphore, releasing one waiting process */ SYSCALL KERNssignal(int *ERRNO, int sem) { struct sentry *sptr; int mpid; disableps(); if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { enableps(); *ERRNO = EINVAL; return SYSERR; } if ((sptr->semcnt++) < 0) { if ((mpid = _getfirst(sptr->squeue)) == SYSERR) PANIC("ssignal: _getfirst FAILED!"); /* _ready(kp->procTable[mpid].flpid,RESCHNO); */ if (kp->procTable[mpid].processState != procUNUSED) kp->procTable[mpid].processState = procREADY; } enableps(); return OK; }
/* make current process wait on a semaphore */ SYSCALL commonSwait(int *ERRNO, int sem, int blockas, int waitdone) { struct sentry *sptr; struct pentry *pptr; if (blockas != procBLOCKED) PANIC("commonSwait() only supports procBLOCKED now"); disableps(); if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { enableps(); *ERRNO = EINVAL; return SYSERR; } if (--(sptr->semcnt) < 0) { PROC->processState = blockas; if (blockas == procBLOCKED) PROC->waitdone = waitdone; PROC->psem = sem; _enqueue(Kgetpid(),sptr->squeue); sleepbusy(); if (blockas == procBLOCKED && PROC->waitdone == waitdone) goto gotit; if (sptr->sstate != SFREE) { if (_dequeueitem(Kgetpid(),sptr->squeue) != SYSERR) PANIC("pentry still on queue in commonSwait()"); } /* else sem was deallocated */ enableps(); *ERRNO = EINTR; return SYSERR; } gotit: PROC->psem = 0; enableps(); return OK; }
/*------------------------------------------------------------------------ * signal -- signal a semaphore, releasing one waiting process *------------------------------------------------------------------------ */ SYSCALL signal(int sem) { // added for PA0 tracing int start_time; int curridx = 16; if(syscall_trace_on == 1) { syscall_used[currpid] = 1; syscall_cnt[currpid][curridx]++; start_time = ctr1000; } STATWORD ps; register struct sentry *sptr; disable(ps); if (isbadsem(sem) || (sptr= &semaph[sem])->sstate==SFREE) { restore(ps); // added for PA0 tracing if(syscall_trace_on == 1) { syscall_time[currpid][curridx] += ctr1000 - start_time; } return(SYSERR); } if ((sptr->semcnt++) < 0) ready(getfirst(sptr->sqhead), RESCHYES); restore(ps); // added for PA0 tracing if(syscall_trace_on == 1) { syscall_time[currpid][curridx] += ctr1000 - start_time; } return(OK); }
/*------------------------------------------------------------------------ * sdelete -- delete a semaphore by releasing its table entry *------------------------------------------------------------------------ */ SYSCALL sdelete(int sem) { STATWORD ps; int pid; struct sentry *sptr; disable(ps); if (isbadsem(sem) || semaph[sem].sstate==SFREE) { restore(ps); return(SYSERR); } sptr = &semaph[sem]; sptr->sstate = SFREE; if (nonempty(sptr->sqhead)) { while( (pid=getfirst(sptr->sqhead)) != EMPTY) { proctab[pid].pwaitret = DELETED; ready(pid,RESCHNO); } resched(); } restore(ps); return(OK); }
thread test_semaphore3(bool verbose) { #if NSEM tid_typ atid, btid; bool passed = TRUE; semaphore s; uchar testResult = 0; char msg[50]; testPrint(verbose, "Semaphore creation: "); s = semcreate(1); if (isbadsem(s)) { passed = FALSE; sprintf(msg, "%d", s); testFail(verbose, msg); } else if (test_checkSemCount(s, 1)) { testPass(verbose, ""); } else { passed = FALSE; } /* We use a higher priority for thread A to ensure it is not rescheduled to * thread B before it is even able to wait on the semaphore. */ ready(atid = create((void *)test_semWaiter, INITSTK, 32, "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_NO); ready(btid = create((void *)test_semWaiter, INITSTK, 31, "SEMAPHORE-B", 3, s, 1, &testResult), RESCHED_YES); testPrint(verbose, "Wait on semaphore: "); /* Process A should be admitted, but B should wait. */ if (test_checkProcState(atid, THRFREE) && test_checkProcState(btid, THRWAIT) && test_checkSemCount(s, -1) && test_checkResult(testResult, 1)) { testPass(verbose, ""); } else { passed = FALSE; } signal(s); /* Process B waited, so signal should release it. */ testPrint(verbose, "Signal waiting semaphore: "); if (test_checkProcState(btid, THRFREE) && test_checkSemCount(s, 0) && test_checkResult(testResult, 2)) { testPass(verbose, ""); } else { passed = FALSE; } if (TRUE == passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } /* Processes should be dead, but in case the test failed. */ kill(atid); kill(btid); semfree(s); #else /* NSEM */ testSkip(TRUE, ""); #endif /* NSEM == 0 */ return OK; }
process test_semaphore(bool8 verbose) { pid32 apid; bool8 passed = TRUE; sid32 s; byte testResult = 0; char msg[50]; /* Single semaphore tests */ testPrint(verbose, "Semaphore creation: "); s = semcreate(0); if (isbadsem(s)) { passed = FALSE; sprintf(msg, "%d", s); testFail(verbose, msg); } else if (test_checkSemCount(s, 0, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on semaphore: "); if ((SYSERR != resume(apid = create((void *)test_semWaiter, INITSTK, 31, "SEMAPHORE-A", 3, s, 1, &testResult))) && test_checkProcState(apid, PR_WAIT, verbose) && test_checkSemCount(s, -1, verbose) && test_checkResult(testResult, 0, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal semaphore: "); if ((OK == signal(s)) && test_checkProcState(apid, PR_FREE, verbose) && test_checkSemCount(s, 0, verbose) && test_checkResult(testResult, 1, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln semaphore (valid count): "); if ((OK == signaln(s, 5)) && test_checkProcState(apid, PR_FREE, verbose) && test_checkSemCount(s, 5, verbose) && test_checkResult(testResult, 1, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln semaphore (invalid count): "); if (SYSERR == signaln(s, -5)) { testPass(verbose, ""); } else { passed = FALSE; } /* Free semaphore, single semaphore tests */ testPrint(verbose, "Delete valid semaphore: "); if ((OK == semdelete(s)) && (semtab[s].sstate == S_FREE) && isempty(semtab[s].squeue)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Delete invalid semaphore: "); if (SYSERR == semdelete(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Delete free semaphore: "); if (SYSERR == semdelete(s)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal bad semaphore id: "); if (SYSERR == signal(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal free semaphore: "); if (SYSERR == signal(s)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln bad semaphore id: "); if (SYSERR == signaln(-1, 4)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln free semaphore: "); if (SYSERR == signaln(s, 4)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on bad semaphore id: "); if (SYSERR == wait(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on free semaphore: "); if (SYSERR == wait(s)) { testPass(verbose, ""); } else { passed = FALSE; } /* Process A should be dead, but in case the test failed. */ kill(apid); /* General semaphore pass/fail */ if (TRUE == passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * scount - return a semaphore count * @param sem id of semaphore to query * @return count from semtab entry on success, SYSERR on failure */ syscall scount(semaphore sem) { if ( isbadsem(sem) ) { return SYSERR; } return (semtab[sem].count); }
process test_semaphore5(bool8 verbose) { pid32 atid; bool8 passed = TRUE; sid32 s; byte testResult = 0; char msg[50]; testPrint(verbose, "Semaphore creation: "); s = semcreate(0); if (isbadsem(s)) { passed = FALSE; sprintf(msg, "%d", s); testFail(verbose, msg); } else if (test_checkSemCount(s, 0)) { testPass(verbose, ""); } else { passed = FALSE; } ready(atid = create((void *)test_semWaiter, INITSTK, getprio(getpid()) + 10, "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_YES); testPrint(verbose, "Wait on semaphore: "); if (test_checkProcState(atid, PR_WAIT) && test_checkSemCount(s, -1) && test_checkResult(testResult, 0)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Reset semaphore: "); if ((OK == semreset(s, 0)) && test_checkProcState(atid, PR_FREE) && test_checkSemCount(s, 0) && test_checkResult(testResult, 1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Reset semaphore (invalid count): "); if (SYSERR == semreset(s, -5)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Reset invalid semaphore: "); if (SYSERR == semreset(-1, 0)) { testPass(verbose, ""); } else { passed = FALSE; } semdelete(s); testPrint(verbose, "Reset free semaphore: "); if (SYSERR == semreset(s, 0)) { testPass(verbose, ""); } else { passed = FALSE; } if (TRUE == passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }