#include "../h/syscall.h" extern pcb_t* currentProcess; // pointer to the current executing process extern int softBlockCount; // number of soft blocked processes extern int device_semaphores[49]; extern pcb_t* readyQueue; // tail pointer to the queue of ready pcbs extern int processCount; // number of started but not terminated processes extern cpu_t startTime; // start time state_t* savedException; void SyscallExceptionHandler(state_t* exception_state) { savedException = exception_state; savedException->pc_epc += 4; // increment by 4B to avoid repeat unsigned int sysCallCode = 0; sysCallCode = (unsigned int) savedException->reg_a0; switch (sysCallCode) { case CREATEPROCESS: Create_Process_SYS1(); break; case TERMPROCESS: Terminate_Process_SYS2(); break; case PASSEREN: // Requests the Nucleus to perform a P operation on a semaphore Passeren_SYS3((int*) exception_state->reg_a1); break; case VERHOGEN: Verhogen_SYS4((int*) exception_state->reg_a1); break; case IOWAIT: Wait_For_IO_Device_SYS5(); break; case GETTIME: Get_CPU_Time_SYS6(); break; case CLOCKWAIT: Wait_For_Clock_SYS7(); break; case GETSUPPORTPTR: Get_Support_Data_SYS8(exception_state); break; default: PassUpOrDie(GENERALEXCEPT, exception_state); break; } } void Create_Process_SYS1() { // Create local copies of reg_a1 and reg_a2 state_t a1Copy = *((state_t*) savedException->reg_a1); support_t* a2Copy = (support_t*) savedException->reg_a2; pcb_t* allocatedPcb = allocPcb(); if(allocatedPcb != NULL){ // the pcb for the process is successfully created // PCB tree and queue fields are set to null in allocPcb process insertProcQ(&readyQueue, allocatedPcb); insertChild(currentProcess, allocatedPcb); currentProcess->p_s.reg_v0 = OK; processCount++; allocatedPcb->p_semAdd = NULL; allocatedPcb->p_time = 0; allocatedPcb->p_s = a1Copy; allocatedPcb->p_supportStruct = a2Copy; } else { // process creation was unsuccessful currentProcess->p_s.reg_v0 = NOPROC; } LDST(savedException); } /* * This services causes the executing process to cease to exist. In addition, * recursively, all progeny of this process are terminated as well. */ void Terminate_Process_SYS2() { if (currentProcess != NULL) { // If the current process exists outChild(currentProcess); TerminateTree(currentProcess); currentProcess = NULL; Scheduler(); } } /* * This method will terminate all children of the current process (referred to as to_terminate) and * should finally terminate the to_terminate itself. */ void TerminateTree(pcb_t* to_terminate) { if (to_terminate == NULL) { return; } while (!emptyChild(to_terminate)) { // terminated process has a child process pcb_t* removedChild = removeChild(to_terminate); TerminateTree(removedChild); // recursively remove all children } TerminateSingleProcess(to_terminate); // terminate the current process } void TerminateSingleProcess(pcb_t* to_terminate) // declared static so it can only be called in this file's scope. { outProcQ(&readyQueue, to_terminate); processCount--; if (to_terminate->p_semAdd != NULL) { if (to_terminate->p_semAdd >= &(device_semaphores[0]) && to_terminate->p_semAdd <= &(device_semaphores[48])) { softBlockCount--; } else { *(to_terminate->p_semAdd) = *(to_terminate->p_semAdd) + 1; } outBlocked(to_terminate); } freePcb(to_terminate); } void Passeren_SYS3(int* semAddr) { (*semAddr) = (*semAddr) - 1; // Decrement the semaphore value if (*semAddr < 0) { currentProcess->p_s = *savedException; int result = insertBlocked(semAddr, currentProcess); switch (result) { case 0: // false case Scheduler(); break; case 1: // true case PANIC(); } } else { LDST(savedException); } } void Verhogen_SYS4(int* semAddr) { (*semAddr) = (*semAddr) + 1; // Increment the semaphore value pcb_t* removedPcb = removeBlocked(semAddr); if(removedPcb != NULL){ // The process was in a blocked state removedPcb->p_semAdd = NULL; insertProcQ(&readyQueue, removedPcb); } LDST(savedException); } void Wait_For_IO_Device_SYS5() { int deviceNumber; // Access the saved exception state if (savedException->reg_a1 == 7) { // Terminal device deviceNumber = 2 * savedException->reg_a2 + savedException->reg_a3; } else { // Non-terminal device deviceNumber = savedException->reg_a2; } // Calculate semaphore index int semIndex = (savedException->reg_a1 - 3) * 8 + deviceNumber; // Increment soft block count softBlockCount++; // Perform the P operation on the device semaphore Passeren_SYS3(&device_semaphores[semIndex]); } /* This service requests that the accumulated processor * (in microseconds) used by the requesting process be placed/returned in the caller’s v0. */ void Get_CPU_Time_SYS6() { currentProcess->p_time += (CURRENT_TOD - startTime); savedException->reg_v0 = currentProcess->p_time; STCK(startTime); LDST(savedException); } /* * This service performs a P operation on the Nucleus maintained pseudo-clock semaphore */ void Wait_For_Clock_SYS7() { softBlockCount++; Passeren_SYS3(&device_semaphores[48]); // call SYS3 } /* * This service requests a pointer to the current process's support structure. * If no value for p_supportStruct was provided for the current process when it was created, * return NULL. */ void Get_Support_Data_SYS8() { savedException->reg_v0 = (unsigned int) currentProcess->p_supportStruct; LDST(savedException); }