/* * 0 >= bytes write * -1 = invalid args * -2 = no message */ int P2_MboxCondReceive(int mbox, void *msg, int *size){ if(mbox < 0 || mbox >= P2_MAX_MBOX || mailboxes[mbox].inUse != 1 || permissionCheck()){ return -1; } mailbox *cur = &(mailboxes[mbox]); P1_P(cur->mutex); if(cur->activeSlots != 0){ P1_P(cur->fulls); //Never blocks message *m = queuePop(&(cur->queue)); int retVal = 0; if(*size > m->bufSize){ retVal = m->bufSize; }else{ retVal = *size; } memcpy(msg,m->buf,retVal); free(m->buf); free(m); cur->activeSlots--; P1_V(cur->mutex); P1_V(cur->empties); return retVal; } P1_V(cur->mutex); return -2; }
int P2_MboxRelease(int mbox){ if(permissionCheck()){ return -1; } P1_P(mBoxSemaphore); int i; for(i = 0; i < P2_MAX_MBOX;i++){ if(mailboxes[i].inUse && mailboxes[i].id == mbox){ if(P1_SemFree(mailboxes[i].mutex) != 0){ USLOSS_Console("Processes waiting on mailbox. Halting.\n"); USLOSS_Halt(1); } if(P1_SemFree(mailboxes[i].fulls) != 0){ USLOSS_Console("Processes waiting on mailbox. Halting.\n"); USLOSS_Halt(1); } if(P1_SemFree(mailboxes[i].empties) != 0){ USLOSS_Console("Processes waiting on mailbox. Halting.\n"); USLOSS_Halt(1); } while(mailboxes[i].queue != NULL){ message *m = queuePop(&(mailboxes[i].queue)); free(m->buf); free(m); } mailboxes[i].inUse = 0; P1_V(mBoxSemaphore); return 0; } } P1_V(mBoxSemaphore); return -1; }
int P2_MboxCreate(int slots, int size){ if(permissionCheck()){ return -1; } P1_P(mBoxSemaphore); if(slots <= 0 || size < 0){ P1_V(mBoxSemaphore); return -2; } int i; for(i = 0; i < P2_MAX_MBOX;i++){ if(mailboxes[i].inUse == 0){ mailboxes[i].inUse = 1; mailboxes[i].maxSlots = slots; mailboxes[i].maximumMessageSize = size; mailboxes[i].mutex = P1_SemCreate(1); mailboxes[i].empties = P1_SemCreate(slots); mailboxes[i].fulls = P1_SemCreate(0); mailboxes[i].queue = NULL; mailboxes[i].activeSlots = 0; P1_V(mBoxSemaphore); return i; } } P1_V(mBoxSemaphore); return -1; }
int validSem(int id){ P1_P(semGuard); if(id < 0 || id >= P1_MAXSEM){ P1_V(semGuard); return 0; } P1_V(semGuard); return userSemList[id].inUse == 1; }
void wakeUpProcesses(void){ P1_P(clockListSemaphore); int i; long now = USLOSS_Clock(); for(i = 0; i < P1_MAXPROC;i++){ if(clockList[i].inUse == 1){ if((now - clockList[i].startTime) >= clockList[i].waitingTime){ P1_V(clockList[i].sem); clockList[i].inUse = 0; } } } P1_V(clockListSemaphore); }
int semAdd(P1_Semaphore s){ int i; P1_P(semGuard); for(i = 0; i < P1_MAXSEM;i++){ if(userSemList[i].inUse == 0){ userSemList[i].inUse = 1; userSemList[i].sem = s; P1_V(semGuard); return i; } } P1_V(semGuard); return -1; }
int P2_MboxSend(int mbox, void *msg, int *size){ if(mbox < 0 || mbox >= P2_MAX_MBOX || mailboxes[mbox].inUse != 1 || mailboxes[mbox].maximumMessageSize < *size || permissionCheck()){ return -1; } mailbox *cur = &(mailboxes[mbox]); P1_P(cur->empties); P1_P(cur->mutex); void *m = malloc(*size); memcpy(m,msg,*size); queueInsert(m,*size,&(cur->queue)); cur->activeSlots++; P1_V(cur->mutex); P1_V(cur->fulls); return 0; }
int semDelete(int id){ P1_P(semGuard); int ret = P1_SemFree(userSemList[id].sem); userSemList[id].inUse = 0; P1_V(semGuard); return ret; }
int TermReader(void *arg){ int unit = (int) arg; char buffer[P2_MAX_LINE] = { 0 }; int i = 0; int status; P1_V(termRunningSem[unit]); while(1){ P2_MboxReceive(termReaderMB[unit],&status,&INT_SIZE); if(done != 0){ break; } char c = USLOSS_TERM_STAT_CHAR(status); if(i < P2_MAX_LINE){ buffer[i] = c; i++; } if(c == '\n'){ if(i > P2_MAX_LINE){ i = P2_MAX_LINE; } P2_MboxCondSend(termLookAhead[unit],buffer,&i); i = 0; memset(buffer,0,MAX_LINE); } } return unit; }
void clockHandler(){ int lastTime = USLOSS_Clock(); ++timeTracker; if(USLOSS_Clock()-lastTime >= 5){ // USLOSS_Console("Clock Fun at %d\n",USLOSS_Clock()); // clock semaphore timeTracker = 0; // clock semaphore!!!!!! P1_V(&semTable[Clock_Sema]); dispatcher(); } }
int TermDriver(void *arg){ int unit = (int) arg; termReaderMB[unit] = P2_MboxCreate(1,INT_SIZE); termLookAhead[unit] = P2_MboxCreate(10,MAX_LINE); termCharToWrite[unit] = P2_MboxCreate(1,INT_SIZE); termWriteSem[unit] = P1_SemCreate(1); termRunningSem[unit] = P1_SemCreate(0); P1_Fork("Term Reader", TermReader, (void *) unit,USLOSS_MIN_STACK, 2); P1_P(termRunningSem[unit]); /*Turn on Terminal interrupts*/ int ctrl = 0; int ctrl2 = 0; ctrl = USLOSS_TERM_CTRL_RECV_INT(ctrl); USLOSS_DeviceOutput(USLOSS_TERM_DEV,unit,(void *)ctrl); P1_V(running); int status = 0; int c = 0; int result; while(1){ result = P1_WaitDevice(USLOSS_TERM_DEV,unit,&status); if(result != 0 || done != 0){ break; } if(USLOSS_TERM_STAT_RECV(status) == USLOSS_DEV_BUSY){ P2_MboxSend(termReaderMB[unit],&status,&INT_SIZE); } if(USLOSS_TERM_STAT_XMIT(status) == USLOSS_DEV_READY){ if(P2_MboxCondReceive(termCharToWrite[unit],&c,&INT_SIZE) != -2){ ctrl2 = 0; ctrl2 = USLOSS_TERM_CTRL_XMIT_INT(ctrl2); ctrl2 = USLOSS_TERM_CTRL_RECV_INT(ctrl2); ctrl2 = USLOSS_TERM_CTRL_CHAR(ctrl2, c); ctrl2 = USLOSS_TERM_CTRL_XMIT_CHAR(ctrl2); USLOSS_DeviceOutput(USLOSS_TERM_DEV, unit, (void *)ctrl2); }else{ ctrl2 = 0; ctrl2 = USLOSS_TERM_CTRL_RECV_INT(ctrl2); USLOSS_DeviceOutput(USLOSS_TERM_DEV, unit, (void *)ctrl2); } } } status = 0; P2_MboxCondSend(termReaderMB[unit],&ctrl,&status); P1_Join(&status); return unit; }
/*P2_DiskSize() returns info about the size of the disk indicated by unit*/ int P2_DiskSize(int unit, int *sector, int *track, int *disk) { if(permissionCheck() || unit < 0 || unit > 1){ return -1; } P1_P(diskSem[unit]); int status; *sector = USLOSS_DISK_SECTOR_SIZE; *track = USLOSS_DISK_TRACK_SIZE; // Make device request for finding number of tracks in disk USLOSS_DeviceRequest request; request.opr = USLOSS_DISK_TRACKS; //reg1 contains pointer to integer where number of disk tracks will be stored request.reg1 = disk; USLOSS_DeviceOutput(USLOSS_DISK_DEV,unit,&request); P1_WaitDevice(USLOSS_DISK_DEV,unit,&status); P1_V(diskSem[unit]); return 0; }
//write a 512 byte sector to the current track int P2_DiskWrite(int unit, int track, int first, int sectors, void *buffer) { if(permissionCheck() || track < 0 || track >= DISK_TRACKS[unit] || first < 0 || first > 15 || unit < 0 || unit > 1 || sectors <= 0){ return -1; } P1_P(diskSem[unit]); int status = 0; //first make a device request struct for a seek USLOSS_DeviceRequest seekRequest; seekRequest.opr = USLOSS_DISK_SEEK; seekRequest.reg1 = (void *)track; //track number where the r/w head should be moved //make device request struct for write USLOSS_DeviceRequest writeRequest; writeRequest.opr = USLOSS_DISK_WRITE; USLOSS_DeviceOutput(USLOSS_DISK_DEV,unit,&seekRequest); P1_WaitDevice(USLOSS_DISK_DEV,unit,&status); int i = 0; while (sectors != 0 && status == 0) { writeRequest.reg1 = (void *)first; writeRequest.reg2 = buffer + (i * USLOSS_DISK_SECTOR_SIZE); USLOSS_DeviceOutput(USLOSS_DISK_DEV,unit,&writeRequest); P1_WaitDevice(USLOSS_DISK_DEV,unit,&status); if (status == USLOSS_DEV_ERROR) { USLOSS_Console("Error with disk write request, unit %d, track %d, sector %d\n",unit, track, first); } first++; sectors--; if (first == 16 && sectors > 0) { //need to move on to next track. track++; seekRequest.reg1 = (void *) track; USLOSS_DeviceOutput(USLOSS_DISK_DEV,unit,&seekRequest); P1_WaitDevice(USLOSS_DISK_DEV,unit,&status); first = 0; //set first to 0 sector of new track } writeRequest.reg1 = (void *)first; i++; } P1_V(diskSem[unit]); return status; }
int P2_Sleep(int seconds){ if(permissionCheck() || seconds < 0){ return -1; } P1_Semaphore s = P1_SemCreate(0); P1_P(clockListSemaphore); int i; for(i = 0; i < P1_MAXPROC;i++){ if(clockList[i].inUse == 0){ clockList[i].inUse = 1; clockList[i].sem = s; clockList[i].startTime = USLOSS_Clock(); clockList[i].waitingTime = seconds * US_IN_S; break; } } P1_V(clockListSemaphore); P1_P(s); P1_SemFree(s); return 0; }
/* ------------------------------------------------------------------------ Name - P1_Quit Purpose - Causes the process to quit and wait for its parent to call P1_Join. Parameters - quit status Returns - nothing Side Effects - the currently running process quits ------------------------------------------------------------------------ */ void P1_Quit(int status) { Check_Your_Privilege(); // USLOSS_Console("In quit PID -- before: %d\n", currPid); int i; for (i = 0; i < P1_MAXPROC; i++) { if(procTable[i].parent==currPid){ procTable[i].isOrphan = 1; // orphanize the children } } // USLOSS_Console("Process: %s Quitting pid=%d\n",procTable[currPid].name,currPid); procTable[currPid].state = 3; procTable[currPid].status = status; numProcs--; // USLOSS_Console("Process state: %d\n", procTable[currPid].state); // USLOSS_Console("PID : %d\n", currPid); /*Remove from Ready List*/ removeFromList(currPid); /*Add to blocked List*/ addToQuitList(currPid); // USLOSS_Console("Orphan Status: %d",procTable[currPid].isOrphan); /*remove if orphan*/ if(procTable[currPid].isOrphan){//||procTable[currPid].parent==-1){ removeProc(currPid); }else{ P1_Semaphore semi = &semTable[procTable[currPid].parent]; // USLOSS_Console("Quit P1_V for %d",currPid); P1_V(semi); } //USLOSS_Console("In quit PID -- after: %d\n", currPid); // USLOSS_Console("Number of processes: %d\n", numProcs); dispatcher(); }
int P2_TermWrite(int unit, int size, char *text){ if(unit >= USLOSS_TERM_UNITS || unit < 0 || size < 0){ return -1; } int ctrl = 0; if(size > P2_MAX_LINE){ size = P2_MAX_LINE; } P1_P(termWriteSem[unit]); int i = 0; int cSize = sizeof(char); int c; while(i < size){ ctrl = USLOSS_TERM_CTRL_XMIT_INT(0); ctrl = USLOSS_TERM_CTRL_RECV_INT(ctrl); USLOSS_DeviceOutput(USLOSS_TERM_DEV, unit, (void *)ctrl); c = *(text + i); P2_MboxSend(termCharToWrite[unit],&c,&cSize); i++; } P1_V(termWriteSem[unit]); P2_Sleep(1); return size; }
static int ClockDriver(void *arg) { interruptsOn(); int result; int status; int rc = 0; /* * Let the parent know we are running and enable interrupts. */ P1_V(running); while (1) { result = P1_WaitDevice(USLOSS_CLOCK_DEV, 0, &status); if (result != 0) { rc = 1; goto done; } /* * Compute the current time and wake up any processes * whose time has come. */ wakeUpProcesses(); } wakeUpProcesses(); done: return rc; }
int child(void *arg) { USLOSS_Console(" %d \n", 0); P1_V(sem1); P1_Quit(0); }
void sysHandler(int type,void *arg) { if(arg == NULL){ USLOSS_Console("USLOSS_Sysargs is NULL!\n"); return; } USLOSS_Sysargs *sysArgs = (USLOSS_Sysargs *) arg; int retVal = 0; int retVal2 = 0; int sectSize = 0; int sectors = 0; int tracks = 0; interruptsOn(); switch (sysArgs->number) { case SYS_TERMREAD: retVal = P2_TermRead((int)sysArgs->arg3, (int)sysArgs->arg2, sysArgs->arg1); if(retVal >= 0){ sysArgs->arg4 = (void *)0; sysArgs->arg2 = (void *)retVal; }else{ sysArgs->arg4 = (void *)-1; } break; case SYS_TERMWRITE: retVal = P2_TermWrite((int)sysArgs->arg3,(int)sysArgs->arg2,(char *)sysArgs->arg1); if(retVal >= 0){ sysArgs->arg4 = (void *)0; sysArgs->arg2 = (void *)retVal; }else{ sysArgs->arg4 = (void *)-1; } break; case SYS_SPAWN: //Part 1 retVal = P2_Spawn(sysArgs->arg5, sysArgs->arg1, sysArgs->arg2, (int) sysArgs->arg3, (int) sysArgs->arg4); if (retVal == -3 || retVal == -2) { sysArgs->arg4 = (void *) -1; sysArgs->arg1 = (void *) -1; } else { sysArgs->arg1 = (void *) retVal; sysArgs->arg4 = (void *) 0; } break; case SYS_WAIT: //Part 1 retVal = P2_Wait(&retVal2); if(retVal == -1){ sysArgs->arg1 = (void *)-1; sysArgs->arg4 = (void *)-1; sysArgs->arg2 = (void *)-1; }else{ sysArgs->arg1 = (void *)retVal; sysArgs->arg2 = (void *)retVal2; sysArgs->arg4 = (void *)0; } break; case SYS_TERMINATE: //Part 1 P2_Terminate((int)sysArgs->arg1); break; case SYS_SLEEP: // Part 1 retVal = P2_Sleep((int)sysArgs->arg1); sysArgs->arg4 = (void *) retVal; break; case SYS_DISKREAD: retVal = P2_DiskRead((int)sysArgs->arg5,(int)sysArgs->arg3,(int) sysArgs->arg4,(int)sysArgs->arg2,(void *)sysArgs->arg1); if (retVal == -1) { sysArgs->arg1 = (void *)retVal; sysArgs->arg4 = (void *)-1; } else if (retVal == 0) { sysArgs->arg1 = (void *)0; sysArgs->arg4 = (void *)0; }else { sysArgs->arg1 = (void *)retVal; //output is the disk's status register sysArgs->arg4 = (void *)0; } break; case SYS_DISKWRITE: retVal = P2_DiskWrite((int)sysArgs->arg5,(int)sysArgs->arg3,(int) sysArgs->arg4,(int)sysArgs->arg2,(void *)sysArgs->arg1); if (retVal == -1) { sysArgs->arg1 = (void *)retVal; sysArgs->arg4 = (void *)-1; } else if (retVal == 0) { sysArgs->arg1 = (void *)0; sysArgs->arg4 = (void *)0; }else { sysArgs->arg1 = (void *)retVal; //output is the disk's status register sysArgs->arg4 = (void *)0; } break; case SYS_DISKSIZE: retVal = P2_DiskSize((int)sysArgs->arg1,§Size,§ors,&tracks); if (retVal == -1) { sysArgs->arg4 = (void *)-1; }else { sysArgs->arg4 = (void *)0; sysArgs->arg1 = (void *)sectSize; sysArgs->arg2 = (void *)sectors; sysArgs->arg3 = (void *)tracks; } break; case SYS_GETTIMEOFDAY: //Part 1 sysArgs->arg1 = (void *)USLOSS_Clock(); break; case SYS_CPUTIME: //Part 1 sysArgs->arg1 = (void *)P1_ReadTime(); break; case SYS_DUMPPROCESSES: //Part 1 P1_DumpProcesses(); break; case SYS_GETPID: //Part 1 sysArgs->arg1 = (void *) P1_GetPID(); break; case SYS_SEMCREATE: //Part 1 retVal = (int)sysArgs->arg1; if(retVal < 0){ sysArgs->arg4 = (void *)-1; }else{ sysArgs->arg4 = (void *)0; sysArgs->arg1 = (void *) semAdd(P1_SemCreate(retVal)); } break; case SYS_SEMP: // Part 1 if(validSem((int)sysArgs->arg1) == 0){ sysArgs->arg4 = (void *) -1; return; } retVal = P1_P(userSemList[(int)sysArgs->arg1].sem); if(retVal < 0){ sysArgs->arg4 = (void *) -1; } else{ sysArgs->arg4 = (void *) 0; } break; case SYS_SEMV: // Part 1 if(validSem((int)sysArgs->arg1) == 0){ sysArgs->arg4 = (void *) -1; return; } retVal = P1_V(userSemList[(int)sysArgs->arg1].sem); if(retVal < 0){ sysArgs->arg4 = (void *) -1; } else{ sysArgs->arg4 = (void *) 0; } break; case SYS_SEMFREE: // Part 1 if(validSem((int)sysArgs->arg1) == 0){ sysArgs->arg4 = (void *) -1; return; } retVal = semDelete((int)sysArgs->arg1); if(retVal < 0){ sysArgs->arg4 = (void *) -1; } else{ sysArgs->arg4 = (void *) 0; } break; case SYS_MBOXCREATE: //Part 1 retVal = P2_MboxCreate((int)sysArgs->arg1,(int)sysArgs->arg2); if(retVal == -2){ sysArgs->arg1 = (void *) -1; sysArgs->arg4 = (void *) -1; }else{ sysArgs->arg1 = (void *) retVal; sysArgs->arg4 = (void *) 0; } break; case SYS_MBOXRELEASE: // Part 1 retVal = P2_MboxRelease((int)sysArgs->arg1); if(retVal < 0){ sysArgs->arg4 = (void *) -1; }else{ sysArgs->arg4 = (void *) 0; } break; case SYS_MBOXSEND: // Part 1 retVal = P2_MboxSend((int)sysArgs->arg1,sysArgs->arg2,(int *)&sysArgs->arg3); if(retVal < 0){ sysArgs->arg4 = (void *) -1; }else{ sysArgs->arg4 = (void *) 0; } break; case SYS_MBOXRECEIVE: // Part 1 retVal = P2_MboxReceive((int)sysArgs->arg1,sysArgs->arg2,(int *)&sysArgs->arg3); if(retVal < 0){ sysArgs->arg4 = (void *) -1; }else{ sysArgs->arg4 = (void *) 0; sysArgs->arg2 = (void *) retVal; } break; case SYS_MBOXCONDSEND: // Part 1 retVal = P2_MboxCondSend((int)sysArgs->arg1,sysArgs->arg2,(int *)&sysArgs->arg3); if(retVal == -1){ sysArgs->arg4 = (void *) -1; }else if(retVal == -2){ sysArgs->arg4 = (void *) 1; } else{ sysArgs->arg4 = (void *) 0; } break; case SYS_MBOXCONDRECEIVE: // Part 1 retVal = P2_MboxCondReceive((int)sysArgs->arg1,sysArgs->arg2,(int *)&sysArgs->arg3); if(retVal == -1){ sysArgs->arg4 = (void *) -1; }else if(retVal == -2){ sysArgs->arg4 = (void *) 1; } else{ sysArgs->arg4 = (void *) 0; sysArgs->arg2 = (void *) retVal; } break; default: P1_Quit(1); } }