#include "simulator.h" /* Name: accessMemory Process: checks offset from the PCB Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) Function Output/Parameters: none Function Output/Returned: none? Device Input/Device: none Device Output/Device: none Dependencies: ??? */ void accessMemory(ProcessControlBlock *singlePCB, int offset, int size) { // no return, void (temp) } /* Name: addProcess Process: allocates the memory for the pcb, grabs the data from the created PCB, dumps the data so that the node can be linked correctly. Function Input/Parameters: source PCB (ProcessControlBlock) Function Output/Parameters: none Function Output/Returned: filled PCB (ProcessControlBlock *) Device Input/Device: none Device Output/Device: none Dependencies: malloc, sizeof, ??? */ ProcessControlBlock *addProcess(const ProcessControlBlock source) { // declare a pointer to working node ProcessControlBlock *workingNode; // make some space that the pointer is pointing to workingNode = malloc(sizeof(ProcessControlBlock)); // get each value from the source, and set their values workingNode->uniquePid = source.uniquePid; workingNode->cpuCycles = source.cpuCycles; workingNode->ioCycles = source.ioCycles; workingNode->nextOpCode = source.nextOpCode; workingNode->process_state = source.process_state; workingNode->timeLeft = source.timeLeft; workingNode->totalCycles = source.totalCycles; workingNode->allocatedMemOffsets = (int *) malloc(sizeof(int) * source.memArraySize); workingNode->allocatedMemSizes = (int *) malloc(sizeof(int) * source.memArraySize); workingNode->memArraySize = source.memArraySize; // make sure to set the next pointer to NULL! workingNode->nextPtr = NULL; // return workingNode return workingNode; } /* Name: allocMemory Process: 'allocates' memory within the PCB, stores offset and size within it's PCB Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) Function Output/Parameters: none Function Output/Returned: none? Device Input/Device: none Device Output/Device: none Dependencies: ??? */ void allocMemory(ProcessControlBlock *singlePCB, int offset, int size) { // no return, void (temp) } /* Name: createProcessList Process: reads through the opcode struct to fill out the linked list of PCBs Function Input/Parameters: none Function Output/Parameters: none Function Output/Returned: head pointer to the PCBs Device Input/Device: none Device Output/Device: none Dependencies: malloc, sizeof, ??? */ ProcessControlBlockLL *createProcessList() { // allocate and create the ProcessControlBlockLL using malloc and size of ProcessControlBlockLL *headBlock; headBlock = malloc(sizeof(ProcessControlBlockLL)); // set the head pointer to NULL headBlock->headPtr = NULL; // return headBlock return headBlock; } /* Name: deallocMemory Process: 'deallocates' memory within the PCB, removes offset and size within it's PCB Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) Function Output/Parameters: none Function Output/Returned: none? Device Input/Device: none Device Output/Device: none Dependencies: ??? */ void deallocMemory(ProcessControlBlock *singlePCB, int offset, int size) { // no return, void (temp) } /* Name: destroyProcessList Process: deallocates memory used for the linked list struct Function Input/Parameters: head pointer to linked list (ProcessControlBlockLL *) Function Output/Parameters: none Function Output/Returned: NULL Device Input/Device: none Device Output/Device: none Dependencies: free, destroyProcessListHelper, ??? */ ProcessControlBlockLL *destroyProcessList(ProcessControlBlockLL *linkedListPtr) { // call the first destroyProcessListHelper destroyProcessListHelper(linkedListPtr->headPtr); // free the rest of the struct free(linkedListPtr); // return null return NULL; } /* Name: destroyProcessListHelper Process: recursively clears the PCB linked list struct, freeing the struct Function Input/Parameters: head pointer to linked list (ProcessControlBlockLL *) Function Output/Parameters: none Function Output/Returned: NULL Device Input/Device: none Device Output/Device: none Dependencies: free, destroyProcessListHelper(recursively), ??? */ ProcessControlBlock *destroyProcessListHelper(ProcessControlBlock *nodePtr) { // check to see if the pointer is NOT null if(nodePtr != NULL) { free(nodePtr->allocatedMemOffsets); free(nodePtr->allocatedMemSizes); // if not null, move to the next pointer (recurse) nodePtr->nextPtr = destroyProcessListHelper(nodePtr->nextPtr); } // free the 'parent' node free(nodePtr); // return null return NULL; } /* Name: fillProcessList Process: iterates through the metadata LL, fills out each process as needed. Function Input/Parameters: metadata (OpCodeType *), headPointer (ProcessControlBlockLL *) Function Output/Parameters: none Function Output/Returned: pointer to filled PCB (ProcessControlBlockLL *) Device Input/Device: none Device Output/Device: none Dependencies: ??? */ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *metadataPtr, ProcessControlBlockLL *headPointer) { // initialize function/variables // need a working pointer for the metadata OpCodeType *wkgMetaPtr; ProcessControlBlock currentPCB; ProcessControlBlock *wkgPCBPtr; OpCodeType *wkgInsPtr; // need a variable to count how many IO cycles are in the process int ioCycleCount = 0; // need a variable to count how many CPU cycles are in the process int cpuCycleCount = 0; // need a variable to calculate the time left in ms for a process double timeLeftCount = 0.0; // need a variable that fills PIDs, starting at 0 int processId = 0; // need a variable that checks how many allocate statements there are. int memAllocation = 0; // process variables? char *command; char *argument; char *inOutArg; int integerArgumentOne; // unused as of current //int integerArgumentTwo; // set the working pointer to the first part of the metadata pointer wkgMetaPtr = metadataPtr; wkgInsPtr = metadataPtr; // set another working pointer to the first part of the PCB list wkgPCBPtr = headPointer->headPtr; // grab the first command and argument command = wkgMetaPtr->command; argument = wkgMetaPtr->strArg1; inOutArg = wkgMetaPtr->inOutArg; // integer argument two is unused atm //integerArgumentTwo = wkgMetaPtr->intArg3; // loop through the process list, until you hit a sys end. while(wkgMetaPtr != NULL && !(compareString(argument, "end") == EQUIV && compareString(command, "sys") == EQUIV)) { currentPCB.nextOpCode = wkgInsPtr->nextNode; integerArgumentOne = wkgMetaPtr->intArg2; // if app start, if (compareString(command, "app") && compareString(argument, "start")) { // set the unique ID for both PCB and Metadata wkgMetaPtr->pid = processId; currentPCB.uniquePid = processId; // set the process state to PROCESS_STATE_NEW currentPCB.process_state = PROCESS_STATE_NEW; } // count number of io cycles if(compareString(command, "dev") == EQUIV) { integerArgumentOne = wkgMetaPtr->intArg2; if(compareString(inOutArg, "in") == EQUIV) { // add up the IO cycle ioCycleCount = ioCycleCount + integerArgumentOne; } else { // add up the IO cycle ioCycleCount = ioCycleCount + integerArgumentOne; } } // count number of cpu cycles if ((compareString(argument, "process") == EQUIV && compareString(command, "cpu") == EQUIV)) { integerArgumentOne = wkgMetaPtr->intArg2; cpuCycleCount = cpuCycleCount + integerArgumentOne; } // count number of times memory is done, sub checks for how many allocates, accesses, etc. if ((compareString(argument, "allocate") == EQUIV && compareString(command, "mem") == EQUIV)) { // allocate the memory memAllocation = memAllocation + 1; } if ((compareString(argument, "end") == EQUIV && compareString(command, "app") == EQUIV)) { // set the ioCycles from variable currentPCB.ioCycles = ioCycleCount; // set the cpuCycles from variable currentPCB.cpuCycles = cpuCycleCount; // set totalCycles from adding both IO/CPU currentPCB.totalCycles = ioCycleCount + cpuCycleCount; // set number of allocations from variable, then reset. currentPCB.memArraySize = memAllocation; memAllocation = 0; // currentPCB must have the starting instruction from wkgInsPtr wkgInsPtr = wkgMetaPtr; // set the time left from (ioCycles * ioCycleRate) + (cpuCycles * procCyclesRate) // this gets the number of ms in the process. timeLeftCount = (ioCycleCount * configPtr->ioCycleRate) + (cpuCycleCount * configPtr->procCycleRate); currentPCB.timeLeft = timeLeftCount; // increment the PID counter processId = processId + 1; ioCycleCount = 0; cpuCycleCount = 0; timeLeftCount = 0.0; // needs to add nodes to the end and all data once parsed // do both the metadata and PCBs if(headPointer->headPtr == NULL) { headPointer->headPtr = addProcess(currentPCB); wkgPCBPtr = headPointer->headPtr; } else { wkgPCBPtr->nextPtr = addProcess(currentPCB); wkgPCBPtr = wkgPCBPtr->nextPtr; } } // move to the next bit of data wkgMetaPtr = wkgMetaPtr->nextNode; command = wkgMetaPtr->command; argument = wkgMetaPtr->strArg1; inOutArg = wkgMetaPtr->inOutArg; } // return headPointer return headPointer; } /* Name: findMin Process: compares two values, returns the smaller of the two. Function Input/Parameters: two integer values (int) Function Output/Parameters: none Function Output/Returned: minimum of the two input integer values (int) Device Input/Device: none Device Output/Device: none Dependencies: none */ int findMin(int one, int another) { int minimumVal = one; if(another < minimumVal) { minimumVal = another; } // return zero(temp) return minimumVal; } /* Name: logOutput Process: Takes in a string, and then outputs it to monitor AND/OR file Function Input/Parameters: string (char *), file pointer (FILE *), configuration data (ConfigDataType *), end of simulator (bool) Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: fprintf, ??? */ void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd) { if(configPtr->logToCode == LOGTO_BOTH_CODE) { // FILE *fileWritePtr; fileWritePtr = fopen(configPtr->logToFileName, "w+"); if (fileWritePtr != NULL) { fprintf(fileWritePtr, "%s", logStr); fprintf(stdout, "%s", logStr); } // no return, void // close the file, if at the end. if (isEnd) { fclose(fileWritePtr); } // fclose(fileWritePtr); } else if(configPtr->logToCode == LOGTO_FILE_CODE) { // printf("\nSimulator will output to a file.\n"); FILE *fileWritePtr; fileWritePtr = fopen(configPtr->logToFileName, "w+"); if (fileWritePtr != NULL) { fprintf(fileWritePtr, "%s", logStr); } // no return, void // close the file, if at the end. if (isEnd) { fclose(fileWritePtr); } // fclose(fileWritePtr); } else { fprintf(stdout, "%s", logStr); } } /* Name: memManager Process: checks to make sure an allocate will be successful, makes sure that an access will not segfault (or return segfault if it does), and initializes memory and deallocates memory Function Input/Parameters: PCBList (ProcessControlBlockLL *), memory code (MEMORY_SIGNALS), offset (int), size (int), configuration data (ConfigDataType *) Function Output/Parameters: none Function Output/Returned: none? Device Input/Device: none Device Output/Device: none Dependencies: ??? */ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr) { bool memDisplay = configPtr->memDisplay; ProcessControlBlock *wkgPtr; int availableMem = configPtr->memAvailable; int usedMem = 0; int currentOffset = 0; int currentSize = 0; int memIterator; wkgPtr = pcbList->headPtr; while(wkgPtr != NULL) { // count up the total used memory within each process control block. for(memIterator = 0; memIterator < wkgPtr->memArraySize; memIterator++) { // grab how much memory is used by that process usedMem = usedMem + wkgPtr->allocatedMemSizes[memIterator]; } // move to the next pointer wkgPtr = wkgPtr->nextPtr; } // switch case for each memory code switch (memCode) { case MEMORY_INITIALIZE: if(memDisplay) { // printf("--------------------------------------------------\n"); printf("After memory initialization\n"); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } break; case MEMORY_ALLOCATE: if (memDisplay) { // printf("--------------------------------------------------\n"); printf("After memory allocation\n"); printf("%d [ Used, P%d: x, %d-%d ] %d\n", usedMem, wkgPtr->uniquePid, offset, size, availableMem - 1); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } break; case MEMORY_ACCESS: if (memDisplay) { // printf("--------------------------------------------------\n"); printf("After access success/failure\n"); printf("%d [ Used, P%d: x, %d-%d ] %d\n", usedMem, wkgPtr->uniquePid, offset, size, availableMem - 1); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } break; case MEMORY_DEALLOCATE: if (memDisplay) { // printf("--------------------------------------------------\n"); printf("After memory clear\n"); printf("No memory configured"); printf("--------------------------------------------------\n"); } break; default: break; } // no return, void (temp) } /* Name: runCPU Process: runs the CPU operations for however long it takes Function Input/Parameters: ??? Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) { char timeStringy[MAX_STR_LEN]; // char *command = workingMeta->command; // char *argument = workingMeta->strArg1; // int intArg = workingMeta->intArg2; char cpuOutput[MAX_STR_LEN]; int cpuTime = 0; cpuTime = intArg * configPtr->procCycleRate; sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); logOutput(configPtr, cpuOutput, false); // run timer for intArg * procCycleRate pthread_t cpuThread; pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)cpuTime); pthread_join(cpuThread, NULL); sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); logOutput(configPtr, cpuOutput, false); // pthread_exit(NULL); } /* Name: runIO Process: runs the IO operations for however long it takes Function Input/Parameters: ??? Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) { char timeStringy[MAX_STR_LEN]; char ioOutput[MAX_STR_LEN]; int ioTime = 0; ioTime = intArg * configPtr->ioCycleRate; sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); logOutput(configPtr, ioOutput, false); pthread_t ioThread; pthread_create(&ioThread, NULL, (void *)&simThread, (void *)ioTime); pthread_join(ioThread, NULL); sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); logOutput(configPtr, ioOutput, false); } /* Name: runProcess Process: runs the process that was selected Function Input/Parameters: ??? Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList) { // run over the entire process, running the CPU when a CPU cycle comes up // or a run IO when an IO cycle comes up char timeStringy[MAX_STR_LEN]; // grab the next operation code for the OpCodeType *workingMeta = singlePCB->nextOpCode; char *command; char *argument; int intArg; char *inOutArg; command = workingMeta->command; argument = workingMeta->strArg1; intArg = workingMeta->intArg2; inOutArg = workingMeta->inOutArg; while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV)) { // check to see what operation will be performed if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV) { // run the CPU for the required amount of time. runCPU(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); } if(compareString(command, "dev") == EQUIV) { // run IO operations for the required amount of time. runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); } workingMeta = workingMeta->nextNode; command = workingMeta->command; argument = workingMeta->strArg1; intArg = workingMeta->intArg2; } } /* Name: runSim Process: primary simulation driver Function Input/Parameters: configuration data (ConfigDataType *), metadata (OpCodeType *) Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: pthreads, accessTimer, sprintf, logOutput, runProcess, destroyProcessList, ??? */ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) { // initialize function/variables // need two working pointers, one for master loop, one for internal loop OpCodeType *wkgPtrMaster; // currentTime variable that stores the time. [now unsure if needed] // need a variable for headPointer to point ProcessControlBlockLL *pcbList; ProcessControlBlock *pcbPtr; // string variable for nextCode, temp unused // char *nextCode; // string variable for the timer stuff char simulatorOutput[MAX_STR_LEN]; char timeStringy[MAX_STR_LEN]; int processCount = 0; int processIterator; int memoryOffset = 0; int memorySize = 1; accessTimer(ZERO_TIMER, timeStringy); // Operating System start timer goes here, log it. sprintf(simulatorOutput, "%f, OS: Simulator start\n", accessTimer(LAP_TIMER, timeStringy)); logOutput(configPtr, simulatorOutput, false); // int variable for process to run int currentPid; // create the process list with createProcessList, store the pointed to address pcbList = createProcessList(); // fill the process list given the metadata pcbList = fillProcessList(configPtr, metaDataMstrPtr, pcbList); pcbPtr = pcbList->headPtr; // calculate pcb total time, number of processes int totalPCBTime = 0; while(pcbPtr != NULL) { totalPCBTime = totalPCBTime + pcbPtr->timeLeft; pcbPtr = pcbPtr->nextPtr; processCount = processCount + 1; } pcbPtr = pcbList->headPtr; pthread_t cpuThread; pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)totalPCBTime); // int processTimeLeft = pcbPtr->timeLeft; // set the current process id to the first scheduled process currentPid = scheduleProcess(pcbList, configPtr); // initialize memory with the memManager memManager(pcbList, MEMORY_INITIALIZE, memoryOffset, memorySize, configPtr); // loop until current process is hit for(processIterator = 0; processIterator < processCount; processIterator++) { while (pcbPtr != NULL) { // printf("Current Process Number is: %d\n", pcbPtr->uniquePid); // printf("Process Status is: %d\n", pcbPtr->process_state); // printf("Scheduled Process is: %d\n", currentPid); if (pcbPtr->process_state != PROCESS_STATE_TERMINATED && pcbPtr->uniquePid == currentPid) { // needs to set from READY to RUNNING pcbPtr->process_state = PROCESS_STATE_RUNNING; sprintf(simulatorOutput, "%f, OS: Process %d set to RUNNING state from READY state\n\n", accessTimer(LAP_TIMER, timeStringy), pcbPtr->uniquePid); logOutput(configPtr, simulatorOutput, false); pthread_t runThread; pthread_create(&runThread, NULL, (void *)&simThread, (void *)processTimeLeft); runProcess(pcbPtr, configPtr, pcbList); // when finished, set to terminated sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", accessTimer(LAP_TIMER, timeStringy), pcbPtr->uniquePid); logOutput(configPtr, simulatorOutput, false); pcbPtr->process_state = PROCESS_STATE_TERMINATED; pthread_join(runThread, NULL); } processTimeLeft = pcbPtr->timeLeft; pcbPtr = pcbPtr->nextPtr; } currentPid = scheduleProcess(pcbList, configPtr); pcbPtr = pcbList->headPtr; } pthread_join(cpuThread, NULL); sprintf(simulatorOutput, "%f, OS: System Stop\n", accessTimer(LAP_TIMER, timeStringy)); logOutput(configPtr, simulatorOutput, false); sprintf(simulatorOutput, "%f, OS: Simulation End\n", accessTimer(LAP_TIMER, timeStringy)); logOutput(configPtr, simulatorOutput, true); // deallocate the process list with destroyProcessList destroyProcessList(pcbList); // once complete, log the output to FILE if required logOutput(configPtr, "", true); // pthread_exit(NULL); // this line seems to make the program execution stop short... no warning either // void function, no return. } /* Name: scheduleProcess Process: takes in the scheduling data, and then returns which process is to be ran Function Input/Parameters: head pointer of PCB List (ProcessControlBlockLL *), configuration data (ConfigDataType *) Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: sprintf, logOutput, ??? */ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr) { ProcessControlBlock *wkgPtr; int returnPid = -1; wkgPtr = headPointer->headPtr; char loggingStr[MAX_STR_LEN]; char timeStringy[MAX_STR_LEN]; int processCount = 0; while (wkgPtr != NULL) { if(wkgPtr->process_state != PROCESS_STATE_TERMINATED) { // processCount = processCount + 1; } wkgPtr = wkgPtr->nextPtr; } wkgPtr = headPointer->headPtr; // switch case for each scheduling algorithm switch (configPtr->cpuSchedCode) { case CPU_SCHED_FCFS_N_CODE: // First Come, First Served, Non-preemptive Scheduling // need to find whichever process is first, AND the state is NEW. // will set the state to READY, return the pid of the process which // was set to ready. // set every process in the list to READY from NEW while(wkgPtr != NULL) { // if(wkgPtr->process_state == PROCESS_STATE_NEW) { // set the process within the PCB to the ready state, report in ready state. wkgPtr->process_state = PROCESS_STATE_READY; // printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid); sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", accessTimer(LAP_TIMER, timeStringy), wkgPtr->uniquePid); logOutput(configPtr, loggingStr, false); } // move to the next pointer wkgPtr = wkgPtr->nextPtr; } // reset the pointer to get ready for selection of process wkgPtr = headPointer->headPtr; while(wkgPtr != NULL && (returnPid == -1)) { // check if the process is NOT terminated if (wkgPtr->process_state != PROCESS_STATE_RUNNING && wkgPtr->process_state != PROCESS_STATE_TERMINATED) { //printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft); sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", accessTimer(LAP_TIMER, timeStringy), wkgPtr->uniquePid, wkgPtr->timeLeft); logOutput(configPtr, loggingStr, false); returnPid = wkgPtr->uniquePid; } // move to next pointer wkgPtr = wkgPtr->nextPtr; } break; case CPU_SCHED_FCFS_P_CODE: // TODO: First Come, First Served, Preemptive Scheduling break; case CPU_SCHED_RR_P_CODE: // TODO: Round Robin Scheduling break; case CPU_SCHED_SJF_N_CODE: // Shortest Job First Scheduling // need to find shortest job, maybe using a find min function? // reuse the previous code to set each process to READY from NEW // will select the process that is in the READY state, with the shortest time. int shortestJob = 0; int shortestJobProcNum = 0; while (wkgPtr != NULL) { // if (wkgPtr->process_state == PROCESS_STATE_NEW) { // set the process within the PCB to the ready state, report in ready state. wkgPtr->process_state = PROCESS_STATE_READY; // printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid); sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", accessTimer(LAP_TIMER, timeStringy), wkgPtr->uniquePid); logOutput(configPtr, loggingStr, false); } // move to the next pointer wkgPtr = wkgPtr->nextPtr; } // reset the pointer to get ready for selection of process wkgPtr = headPointer->headPtr; // load in the first process time shortestJob = wkgPtr->timeLeft; // move to the next pointer. wkgPtr = wkgPtr->nextPtr; while (wkgPtr != NULL && (returnPid == -1)) { // check if the process is NOT terminated // now, ALSO needs to check which process takes the least time. if (wkgPtr->process_state != PROCESS_STATE_RUNNING && wkgPtr->process_state != PROCESS_STATE_TERMINATED) { // check to see if the working pointer job is shorter than the current shortest job shortestJob = findMin(shortestJob, wkgPtr->timeLeft); // check to see if the shortest job time changed, if it did, change the process number if(shortestJob == wkgPtr->timeLeft) { // change process number, or leave it unchanged. shortestJobProcNum = wkgPtr->uniquePid; } } // move to next pointer wkgPtr = wkgPtr->nextPtr; } // check the number of processes, if there is one left, then wkgPtr = headPointer->headPtr; if(processCount == 1) { // find the last process that is READY but not TERMINATED, set it's PID as the return. while(wkgPtr != NULL) { // if (wkgPtr->process_state != PROCESS_STATE_TERMINATED) { // shortestJobProcNum = wkgPtr->uniquePid; shortestJob = wkgPtr->timeLeft; } wkgPtr = wkgPtr->nextPtr; } } if(processCount != 0) { // printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft); sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", accessTimer(LAP_TIMER, timeStringy), shortestJobProcNum, (double)shortestJob); logOutput(configPtr, loggingStr, false); } returnPid = shortestJobProcNum; break; case CPU_SCHED_SRTF_P_CODE: // TODO: Shortest Run-time First Scheduling break; } // return returnPid return returnPid; } /* Name: simThread Process: wrapper functions for threading in the simulator Function Input/Parameters: milliseconds (int) Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: pthreads, runTimer */ void *simThread(int milSec) { runTimer(milSec); pthread_exit(NULL); }