From 67df0ceeaf48f21e1f6f1cbc111a59286cbebe1b Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 18 Mar 2024 15:55:32 -0700 Subject: [PATCH 01/11] Savepoint for memory operations. --- Sim03/sim03 | Bin 66808 -> 68112 bytes Sim03/simulator.c | 190 +++++++++++++++++++++++++++++++++++++++------- Sim03/simulator.h | 13 ++++ 3 files changed, 174 insertions(+), 29 deletions(-) diff --git a/Sim03/sim03 b/Sim03/sim03 index 6b254d6179639ea4730c68cea368b2eecc9ff3aa..b4cb1a282ad0fcfd2b56ee8644d30ba817d19205 100755 GIT binary patch delta 20853 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 Q0!x3@z`N^Tprocess_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 @@ -52,6 +85,21 @@ ProcessControlBlockLL *createProcessList() 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 @@ -87,6 +135,8 @@ 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); } @@ -123,6 +173,8 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me 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; @@ -181,6 +233,12 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me 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 @@ -189,6 +247,9 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me 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; @@ -304,6 +365,97 @@ void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd) } } +/* +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 @@ -369,7 +521,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ -void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr) +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 @@ -431,6 +583,8 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) 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. @@ -455,6 +609,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) } pcbPtr = pcbList->headPtr; + pthread_t cpuThread; pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)totalPCBTime); @@ -463,34 +618,11 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // 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 - // while(pcbPtr->process_state != PROCESS_STATE_TERMINATED && pcbPtr != NULL && processCount != 0) - // { - // if(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); - // // 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; - // processCount = processCount - 1; - // pthread_join(runThread, NULL); - // } - // processTimeLeft = pcbPtr->timeLeft; - // pcbPtr = pcbPtr->nextPtr; - // currentPid = scheduleProcess(pcbList, configPtr); - // if(configPtr->cpuSchedCode == CPU_SCHED_SJF_N_CODE && pcbPtr == NULL) - // { - // // - // pcbPtr = pcbList->headPtr; - // } - // } for(processIterator = 0; processIterator < processCount; processIterator++) { while (pcbPtr != NULL) @@ -506,7 +638,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) logOutput(configPtr, simulatorOutput, false); pthread_t runThread; pthread_create(&runThread, NULL, (void *)&simThread, (void *)processTimeLeft); - runProcess(pcbPtr, configPtr); + 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); diff --git a/Sim03/simulator.h b/Sim03/simulator.h index 4ccba46..f75f791 100644 --- a/Sim03/simulator.h +++ b/Sim03/simulator.h @@ -17,6 +17,13 @@ typedef enum{ PROCESS_STATE_TERMINATED } PROCESS_STATES; +typedef enum{ + MEMORY_INITIALIZE = 0, + MEMORY_ACCESS, + MEMORY_ALLOCATE, + MEMORY_DEALLOCATE + } MEMORY_SIGNALS; + typedef struct ProcessControlBlockStruct { int uniquePid; @@ -37,6 +44,12 @@ typedef struct ProcessControlBlockStruct // see how many are left. // also need a time left state here? double timeLeft; + // allocated memory array (stores the offsets) + int *allocatedMemOffsets; + // allocated memory array sizes (stores the sizes for each offset) + int *allocatedMemSizes; + // size of memory array + int memArraySize; // connect to the next process control block here struct ProcessControlBlockStruct *nextPtr; } ProcessControlBlock; From 6446272063cc19cea216cca2cfb403338aa056fe Mon Sep 17 00:00:00 2001 From: Cdez Date: Mon, 18 Mar 2024 16:40:32 -0700 Subject: [PATCH 02/11] Savepoint available --- Sim03/logfile_1.lgf | 2 +- Sim03/sim03 | Bin 68112 -> 68136 bytes Sim03/simulator.c | 18 +++++++++++++++--- Sim03/simulator.h | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index 0a374fe..52b0e91 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -1,4 +1,4 @@ -0.000001, OS: Simulator start +0.000000, OS: Simulator start READY state from NEW state ate diff --git a/Sim03/sim03 b/Sim03/sim03 index b4cb1a282ad0fcfd2b56ee8644d30ba817d19205..be5b47cd3b36b6874b79bab5f112fdcbca4c7eea 100755 GIT binary patch delta 13860 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 KRBhud>i+<&SwPSL delta 13695 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 X{f#V_<<&2yuDO06b(89uH%tB>headPtr; } pthread_join(cpuThread, NULL); + // deallocate all the memory for each process. + memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr); 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)); diff --git a/Sim03/simulator.h b/Sim03/simulator.h index f75f791..4ce4906 100644 --- a/Sim03/simulator.h +++ b/Sim03/simulator.h @@ -21,6 +21,7 @@ typedef enum{ MEMORY_INITIALIZE = 0, MEMORY_ACCESS, MEMORY_ALLOCATE, + MEMORY_CLEAR, MEMORY_DEALLOCATE } MEMORY_SIGNALS; From bb6d8ac0afcc9230422fcb5f46cf25a255fcb690 Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 18 Mar 2024 21:28:38 -0700 Subject: [PATCH 03/11] Savepoint, have most everything in place for the memory functions, will just need to fill them in. +- Simulator.c --- Sim03/logfile_1.lgf | 2 +- Sim03/sim03 | Bin 68136 -> 68600 bytes Sim03/simulator.c | 174 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 142 insertions(+), 34 deletions(-) diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index 52b0e91..0a374fe 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -1,4 +1,4 @@ -0.000000, OS: Simulator start +0.000001, OS: Simulator start READY state from NEW state ate diff --git a/Sim03/sim03 b/Sim03/sim03 index be5b47cd3b36b6874b79bab5f112fdcbca4c7eea..e58449eb06cbc18acd465c37bff685bf97c2ad90 100755 GIT binary patch delta 20118 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 IxT?ngFN5`LN&o-= delta 18055 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[] = offset; + // return true (temp) + return true; } /* @@ -90,14 +93,15 @@ 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? +Function Output/Returned: boolean to indicate success or failure of allocated memory Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void deallocMemory(ProcessControlBlock *singlePCB, int offset, int size) +bool deallocMemory(ProcessControlBlock *singlePCB, int offset, int size) { - // no return, void (temp) + // return true (temp) + return true; } /* @@ -378,7 +382,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr) +void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) { bool memDisplay = configPtr->memDisplay; ProcessControlBlock *wkgPtr; @@ -387,8 +391,12 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs int currentOffset = 0; int currentSize = 0; int memIterator; + int *memorySizeArray; + int totalArraySize = 0; + bool subFunctionSuccess = true; wkgPtr = pcbList->headPtr; + // grab how much memory is being used total, then count how big the total memory array should be while(wkgPtr != NULL) { // count up the total used memory within each process control block. @@ -396,15 +404,47 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs { // grab how much memory is used by that process usedMem = usedMem + wkgPtr->allocatedMemSizes[memIterator]; + totalArraySize = totalArraySize + 1; } // move to the next pointer wkgPtr = wkgPtr->nextPtr; } + // reset the working pointer + wkgPtr = pcbList->headPtr; + + // declare the array for the memory + memorySizeArray = malloc(sizeof(int) * totalArraySize); + + // grab the entire memory structure, so that the memory can be contiguous + while (wkgPtr != NULL) + { + // count up the total used memory within each process control block. + for (memIterator = 0; memIterator < totalArraySize; memIterator++) + { + // grab how much memory is used by that process + memorySizeArray[memIterator] = wkgPtr->allocatedMemSizes[memIterator]; + } + // move to the next pointer + wkgPtr = wkgPtr->nextPtr; + } + + // grab the size of the + // while() + // { + // // + // } + // switch case for each memory code switch (memCode) { case MEMORY_INITIALIZE: + for(memIterator = 0; memIterator < singlePCB->memArraySize; memIterator++) + { + // initialize the arrays with all '-1' to 'nullify' the memory, make it easier to iterate through later + singlePCB->allocatedMemOffsets[memIterator] = -1; + singlePCB->allocatedMemSizes[memIterator] = -1; + } if(memDisplay) { // @@ -416,44 +456,83 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs break; case MEMORY_ALLOCATE: + // grab the offset and size, store it, using the allocate memory function. + // if the function returns true, then it successfully did the operation, display as such. + subFunctionSuccess = allocMemory(singlePCB, offset, size); 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"); + if(subFunctionSuccess) + { + // + printf("--------------------------------------------------\n"); + printf("After memory allocation\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // + printf("--------------------------------------------------\n"); + printf("After memory allocation failure\n"); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } } break; case MEMORY_ACCESS: + subFunctionSuccess = accessMemory(singlePCB, offset, size); 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"); + if (subFunctionSuccess) + { + // + printf("--------------------------------------------------\n"); + printf("After access success\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // + printf("--------------------------------------------------\n"); + printf("After access failure\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } } break; case MEMORY_DEALLOCATE: + subFunctionSuccess = deallocMemory(singlePCB, offset, size); if (memDisplay) { - // - printf("--------------------------------------------------\n"); - printf("After memory deallocate\n"); - printf("Deallocated memory chunk.\n"); - printf("--------------------------------------------------\n"); + if (subFunctionSuccess) + { + // THIS SHOULD ALWAYS HAPPEN. + printf("--------------------------------------------------\n"); + printf("After clear process %d success\n", singlePCB->uniquePid); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // THIS SHOULD NEVER HAPPEN. + printf("--------------------------------------------------\n"); + printf("After clear process %d failure\n", singlePCB->uniquePid); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } } break; case MEMORY_CLEAR: if (memDisplay) { - // + // this will happen regardless. Will always be cleaning up memory with dealloc. printf("--------------------------------------------------\n"); printf("After memory clear\n"); printf("No memory configured\n"); @@ -464,6 +543,8 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs default: break; } + // clear out the dynamic array + free(memorySizeArray); // no return, void (temp) } @@ -537,16 +618,19 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce // 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]; + char processOutput[HUGE_STR_LEN]; // grab the next operation code for the OpCodeType *workingMeta = singlePCB->nextOpCode; char *command; char *argument; int intArg; - char *inOutArg; + int intArgTwo; + // char *inOutArg; command = workingMeta->command; argument = workingMeta->strArg1; intArg = workingMeta->intArg2; - inOutArg = workingMeta->inOutArg; + intArgTwo = workingMeta->intArg3; + // 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 @@ -560,11 +644,35 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce // run IO operations for the required amount of time. runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); } + if(compareString(command, "mem") == EQUIV) + { + // run memory operations with the memory manager + if(compareString(argument, "allocate") == EQUIV) + { + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + // run the memory manager in allocate mode + memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + } + else if(compareString(argument, "access") == EQUIV) + { + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + // run the memory manager in access mode + memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); + } + } workingMeta = workingMeta->nextNode; command = workingMeta->command; argument = workingMeta->strArg1; intArg = workingMeta->intArg2; + intArgTwo = workingMeta->intArg3; } + // display the process exited + sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + logOutput(configPtr, processOutput, false); + // deallocate the memory for the process + memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB); } /* @@ -582,7 +690,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) { // initialize function/variables // need two working pointers, one for master loop, one for internal loop - OpCodeType *wkgPtrMaster; + // OpCodeType *wkgPtrMaster; // currentTime variable that stores the time. [now unsure if needed] // need a variable for headPointer to point ProcessControlBlockLL *pcbList; @@ -630,7 +738,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) currentPid = scheduleProcess(pcbList, configPtr); // initialize memory with the memManager - memManager(pcbList, MEMORY_INITIALIZE, memoryOffset, memorySize, configPtr); + memManager(pcbList, MEMORY_INITIALIZE, memoryOffset, memorySize, configPtr, pcbList->headPtr); // loop until current process is hit for(processIterator = 0; processIterator < processCount; processIterator++) @@ -663,7 +771,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) } pthread_join(cpuThread, NULL); // deallocate all the memory for each process. - memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr); + memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr); 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)); From d7bb439a2a8d0b4b9e566e3e83de2101523521b8 Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 18 Mar 2024 22:08:55 -0700 Subject: [PATCH 04/11] Savepoint, started the allocate memory management stuff. +- simulator.c --- Sim03/logfile_1.lgf | 2 +- Sim03/sim03 | Bin 68600 -> 68680 bytes Sim03/simulator.c | 74 +++++++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index 0a374fe..52b0e91 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -1,4 +1,4 @@ -0.000001, OS: Simulator start +0.000000, OS: Simulator start READY state from NEW state ate diff --git a/Sim03/sim03 b/Sim03/sim03 index e58449eb06cbc18acd465c37bff685bf97c2ad90..b426ccf781e83b4b681544122b26144cff88bde2 100755 GIT binary patch delta 17495 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 delta 17275 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 diff --git a/Sim03/simulator.c b/Sim03/simulator.c index a91f9c8..1583ecb 100644 --- a/Sim03/simulator.c +++ b/Sim03/simulator.c @@ -2,7 +2,8 @@ /* Name: accessMemory -Process: checks offset from the PCB +Process: checks that the memory is between the offset and the size. + checks that the memory is ??? Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) Function Output/Parameters: none Function Output/Returned: boolean to indicate success or failure of accessed memory @@ -90,15 +91,15 @@ ProcessControlBlockLL *createProcessList() /* 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) +Process: 'deallocates' memory within the PCB, removes every offset and size within it's PCB +Function Input/Parameters: source PCB (ProcessControlBlock *) Function Output/Parameters: none Function Output/Returned: boolean to indicate success or failure of allocated memory Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -bool deallocMemory(ProcessControlBlock *singlePCB, int offset, int size) +bool deallocMemory(ProcessControlBlock *singlePCB) { // return true (temp) return true; @@ -377,12 +378,12 @@ Process: checks to make sure an allocate will be successful, Function Input/Parameters: PCBList (ProcessControlBlockLL *), memory code (MEMORY_SIGNALS), offset (int), size (int), configuration data (ConfigDataType *) Function Output/Parameters: none -Function Output/Returned: none? +Function Output/Returned: boolean for success or failure of memory management Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) +bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) { bool memDisplay = configPtr->memDisplay; ProcessControlBlock *wkgPtr; @@ -402,8 +403,11 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // 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]; + if(wkgPtr->allocatedMemSizes[memIterator] != -1) + { + // grab how much memory is used by that process + usedMem = usedMem + wkgPtr->allocatedMemSizes[memIterator]; + } totalArraySize = totalArraySize + 1; } // move to the next pointer @@ -456,9 +460,19 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs break; case MEMORY_ALLOCATE: - // grab the offset and size, store it, using the allocate memory function. + // check if the memory allocation can happen before storing it. + if(size <= availableMem - usedMem + 1) + { + // grab the offset and size, store it, using the allocate memory function. + subFunctionSuccess = allocMemory(singlePCB, offset, size); + usedMem = usedMem + size; + } + else + { + // set the subfunction success to false. + subFunctionSuccess = false; + } // if the function returns true, then it successfully did the operation, display as such. - subFunctionSuccess = allocMemory(singlePCB, offset, size); if (memDisplay) { if(subFunctionSuccess) @@ -507,7 +521,7 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs break; case MEMORY_DEALLOCATE: - subFunctionSuccess = deallocMemory(singlePCB, offset, size); + subFunctionSuccess = deallocMemory(singlePCB); if (memDisplay) { if (subFunctionSuccess) @@ -545,7 +559,8 @@ void memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs } // clear out the dynamic array free(memorySizeArray); - // no return, void (temp) + // return if the subfunction succeeded, if applicable + return subFunctionSuccess; } /* @@ -625,13 +640,14 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce char *argument; int intArg; int intArgTwo; + bool memManagerSuccess = true; // char *inOutArg; command = workingMeta->command; argument = workingMeta->strArg1; intArg = workingMeta->intArg2; intArgTwo = workingMeta->intArg3; // inOutArg = workingMeta->inOutArg; - while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV)) + while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV) && memManagerSuccess) { // check to see what operation will be performed if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV) @@ -652,14 +668,26 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); // run the memory manager in allocate mode - memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + memManagerSuccess = memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + if(!memManagerSuccess) + { + // + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + } } else if(compareString(argument, "access") == EQUIV) { sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); // run the memory manager in access mode - memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); + memManagerSuccess = memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); + if (!memManagerSuccess) + { + // + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + } } } workingMeta = workingMeta->nextNode; @@ -668,9 +696,19 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce intArg = workingMeta->intArg2; intArgTwo = workingMeta->intArg3; } - // display the process exited - sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); - logOutput(configPtr, processOutput, false); + // display the process exited, if not segfaulted. + if(memManagerSuccess) + { + // + sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + logOutput(configPtr, processOutput, false); + } + else + { + // + sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + logOutput(configPtr, processOutput, false); + } // deallocate the memory for the process memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB); } From 240190bea405bdf612a50115954d09a2879b6ccb Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 18 Mar 2024 22:59:27 -0700 Subject: [PATCH 05/11] Will submit this if there is no time left to spend on the project. +- simulator.c --- Sim03/sim03 | Bin 68680 -> 68880 bytes Sim03/simulator.c | 32 +++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Sim03/sim03 b/Sim03/sim03 index b426ccf781e83b4b681544122b26144cff88bde2..393e6bac23dbda6a4f9ac90183d2c1d2562293f4 100755 GIT binary patch delta 16400 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 E0ZfoGtN;K2 delta 16096 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 diff --git a/Sim03/simulator.c b/Sim03/simulator.c index 1583ecb..5699961 100644 --- a/Sim03/simulator.c +++ b/Sim03/simulator.c @@ -61,9 +61,18 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size) +bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int arraySize) { - // singlePCB->allocatedMemOffsets[] = offset; + int allocateIterator = 0; + // while until a '-1' is hit, then store the value. + while(singlePCB->allocatedMemSizes[allocateIterator] != -1 && allocateIterator < arraySize) + { + // + singlePCB->allocatedMemOffsets[allocateIterator] = offset; + singlePCB->allocatedMemSizes[allocateIterator] = size; + allocateIterator = allocateIterator + 1; + printf("Alloc Iter: %d\n", allocateIterator); + } // return true (temp) return true; } @@ -99,8 +108,16 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -bool deallocMemory(ProcessControlBlock *singlePCB) +bool deallocMemory(ProcessControlBlock *singlePCB, int arraySize) { + int deallocateIterator; + // while until a '-1' is hit, then store the value. + for (deallocateIterator = 0; deallocateIterator < arraySize; deallocateIterator++) + { + // + singlePCB->allocatedMemOffsets[deallocateIterator] = -1; + singlePCB->allocatedMemSizes[deallocateIterator] = -1; + } // return true (temp) return true; } @@ -464,7 +481,7 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs if(size <= availableMem - usedMem + 1) { // grab the offset and size, store it, using the allocate memory function. - subFunctionSuccess = allocMemory(singlePCB, offset, size); + subFunctionSuccess = allocMemory(singlePCB, offset, size, singlePCB->memArraySize); usedMem = usedMem + size; } else @@ -496,6 +513,7 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs break; case MEMORY_ACCESS: + // printf("Used memory at current: %d\n", usedMem); subFunctionSuccess = accessMemory(singlePCB, offset, size); if (memDisplay) { @@ -521,7 +539,7 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs break; case MEMORY_DEALLOCATE: - subFunctionSuccess = deallocMemory(singlePCB); + subFunctionSuccess = deallocMemory(singlePCB, singlePCB->memArraySize); if (memDisplay) { if (subFunctionSuccess) @@ -529,7 +547,7 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // THIS SHOULD ALWAYS HAPPEN. printf("--------------------------------------------------\n"); printf("After clear process %d success\n", singlePCB->uniquePid); - printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem - usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } else @@ -537,7 +555,7 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // THIS SHOULD NEVER HAPPEN. printf("--------------------------------------------------\n"); printf("After clear process %d failure\n", singlePCB->uniquePid); - printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem - usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } } From 5d8edb82713eb279d0ea5a9c0363e3b5ec81a4e0 Mon Sep 17 00:00:00 2001 From: cdez Date: Thu, 21 Mar 2024 01:28:28 -0700 Subject: [PATCH 06/11] Adding Grading form --- Sim03/Sim03_GradingForm_413499.xlsx | Bin 0 -> 22830 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Sim03/Sim03_GradingForm_413499.xlsx diff --git a/Sim03/Sim03_GradingForm_413499.xlsx b/Sim03/Sim03_GradingForm_413499.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5d4670dbd09d264c143ba68e1ea173b8a3f18301 GIT binary patch literal 22830 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 Date: Mon, 8 Apr 2024 13:19:52 -0700 Subject: [PATCH 07/11] Modified timer function and such to stop the warnings. --- Sim03/sim03 | Bin 68880 -> 68856 bytes Sim03/simtimer.c | 41 +++++++++++++++++++++++++++++++++++++++-- Sim03/simtimer.h | 2 +- Sim03/simulator.c | 23 ++++++++++++++--------- Sim03/simulator.h | 2 +- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/Sim03/sim03 b/Sim03/sim03 index 393e6bac23dbda6a4f9ac90183d2c1d2562293f4..047dfc94eb1c60c256796c4f11a1315ea5916ffe 100755 GIT binary patch delta 20018 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 E0PfintArg2; char cpuOutput[MAX_STR_LEN]; int cpuTime = 0; + int *cpuTimePtr = &cpuTime; 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_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); 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); @@ -626,11 +627,12 @@ void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, char timeStringy[MAX_STR_LEN]; char ioOutput[MAX_STR_LEN]; int ioTime = 0; + int *ioTimePtr = &ioTime; 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_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); 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); @@ -782,13 +784,15 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) processCount = processCount + 1; } pcbPtr = pcbList->headPtr; + int *totalPCBTimePtr = &totalPCBTime; pthread_t cpuThread; - pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)totalPCBTime); + pthread_create(&cpuThread, NULL, runTimer, (void *)totalPCBTimePtr); // int processTimeLeft = pcbPtr->timeLeft; + int *processTimeLeftPtr = &processTimeLeft; // set the current process id to the first scheduled process currentPid = scheduleProcess(pcbList, configPtr); @@ -811,7 +815,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) 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); + pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr); 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); @@ -820,6 +824,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) pthread_join(runThread, NULL); } processTimeLeft = pcbPtr->timeLeft; + processTimeLeftPtr = &processTimeLeft; pcbPtr = pcbPtr->nextPtr; } currentPid = scheduleProcess(pcbList, configPtr); @@ -1007,8 +1012,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, runTimer */ -void *simThread(int milSec) -{ - runTimer(milSec); - pthread_exit(NULL); -} \ No newline at end of file +// void *simThread(int milSec) +// { +// runTimer(milSec); +// pthread_exit(NULL); +// } \ No newline at end of file diff --git a/Sim03/simulator.h b/Sim03/simulator.h index 4ce4906..9e9e59f 100644 --- a/Sim03/simulator.h +++ b/Sim03/simulator.h @@ -229,6 +229,6 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void *simThread(int milSec); +// void *simThread(int milSec); #endif // SIMULATORX \ No newline at end of file From e3441e9fbdc3420598effd137f58527930a30c65 Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 8 Apr 2024 13:36:29 -0700 Subject: [PATCH 08/11] Trying out how to fix the sjf errors. --- Sim03/logfile_1.lgf | 7 ------- Sim03/sim03 | Bin 68856 -> 68832 bytes Sim03/simulator.c | 6 ++++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index 52b0e91..e69de29 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -1,7 +0,0 @@ -0.000000, OS: Simulator start - READY state from NEW state -ate - -ate - - diff --git a/Sim03/sim03 b/Sim03/sim03 index 047dfc94eb1c60c256796c4f11a1315ea5916ffe..8d57268ffd620d83d43bbb2b19f7340172bd0c87 100755 GIT binary patch delta 5265 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 delta 5323 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 Pm?m21GNa-|NAmlB`{#%4 diff --git a/Sim03/simulator.c b/Sim03/simulator.c index 5aeda88..db2ba8f 100644 --- a/Sim03/simulator.c +++ b/Sim03/simulator.c @@ -865,6 +865,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt char timeStringy[MAX_STR_LEN]; int processCount = 0; + int shortestJob = 0; + int shortestJobProcNum = 0; + while (wkgPtr != NULL) { if(wkgPtr->process_state != PROCESS_STATE_TERMINATED) @@ -928,8 +931,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt // 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) { // From fda57566d88c65538f58f5e40fbe43625fe87e82 Mon Sep 17 00:00:00 2001 From: cdez Date: Sun, 14 Apr 2024 18:41:58 -0700 Subject: [PATCH 09/11] Refuse to work on this anymore right now. --- Sim03/logfile_1.lgf | 1 + Sim03/sim03 | Bin 68832 -> 73896 bytes Sim03/sim03_mf | 2 +- Sim03/simulator.c | 335 +++++++++--- Sim03/simulator.h | 171 ++++++- Sim04/OS_SimDriver.c | 246 +++++++++ Sim04/OS_SimDriver.h | 74 +++ Sim04/StandardConstants.h | 79 +++ Sim04/StringUtils.c | 454 +++++++++++++++++ Sim04/StringUtils.h | 176 +++++++ Sim04/config0.cnf | 13 + Sim04/configops.c | 608 ++++++++++++++++++++++ Sim04/configops.h | 168 ++++++ Sim04/logfile_1.lgf | 0 Sim04/metadata5.mdf | 75 +++ Sim04/metadataops.c | 729 ++++++++++++++++++++++++++ Sim04/metadataops.h | 207 ++++++++ Sim04/sim03 | Bin 0 -> 68832 bytes Sim04/sim03_mf | 32 ++ Sim04/simtimer.c | 270 ++++++++++ Sim04/simtimer.h | 49 ++ Sim04/simulator.c | 1021 +++++++++++++++++++++++++++++++++++++ Sim04/simulator.h | 234 +++++++++ Sim04/testfile-dnw.mdf | 86 ++++ Sim04/testfile.cnf | 12 + Sim04/testfile.mdf | 40 ++ 26 files changed, 4988 insertions(+), 94 deletions(-) create mode 100644 Sim04/OS_SimDriver.c create mode 100644 Sim04/OS_SimDriver.h create mode 100644 Sim04/StandardConstants.h create mode 100644 Sim04/StringUtils.c create mode 100644 Sim04/StringUtils.h create mode 100644 Sim04/config0.cnf create mode 100644 Sim04/configops.c create mode 100644 Sim04/configops.h create mode 100644 Sim04/logfile_1.lgf create mode 100644 Sim04/metadata5.mdf create mode 100644 Sim04/metadataops.c create mode 100644 Sim04/metadataops.h create mode 100755 Sim04/sim03 create mode 100644 Sim04/sim03_mf create mode 100644 Sim04/simtimer.c create mode 100644 Sim04/simtimer.h create mode 100644 Sim04/simulator.c create mode 100644 Sim04/simulator.h create mode 100644 Sim04/testfile-dnw.mdf create mode 100644 Sim04/testfile.cnf create mode 100644 Sim04/testfile.mdf diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index e69de29..fea283a 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -0,0 +1 @@ +0.000001, OS: Simulator start diff --git a/Sim03/sim03 b/Sim03/sim03 index 8d57268ffd620d83d43bbb2b19f7340172bd0c87..9e0361fd5bba974d25da940b6bc90bd959a3dbc8 100755 GIT binary patch delta 25562 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

*A$S{(QJ~r#|ATjc;~+2&&Glrk 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 delta 23693 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 diff --git a/Sim03/sim03_mf b/Sim03/sim03_mf index d6d51fb..243d1d9 100644 --- a/Sim03/sim03_mf +++ b/Sim03/sim03_mf @@ -5,7 +5,7 @@ OBJECTS = OS_SimDriver.o simulator.o metadataops.o configops.o StringUtils.o sim all: Simulator Simulator: $(OBJECTS) - $(CC) $(OBJECTS) -o sim03 + $(CC) $(OBJECTS) -lpthread -o sim03 StringUtils.o: StringUtils.c $(CC) -c StringUtils.c -o StringUtils.o diff --git a/Sim03/simulator.c b/Sim03/simulator.c index db2ba8f..67e218a 100644 --- a/Sim03/simulator.c +++ b/Sim03/simulator.c @@ -17,6 +17,32 @@ bool accessMemory(ProcessControlBlock *singlePCB, int offset, int size) return true; } +/* +Name: addLog +Process: allocates the memory for the log, ... +Function Input/Parameters: source log (logFile) +Function Output/Parameters: none +Function Output/Returned: filled PCB (logFile *) +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, sizeof, ??? +*/ +logFile *addLog(const logFile source) +{ + // declare a pointer to working node + logFile *workingNode; + // make some space that the pointer is pointing to + workingNode = malloc(sizeof(logFile)); + // make some space for the string data + // workingNode->stringData = malloc(sizeof(source.stringData)); + // get each value from the source, and set their values + copyString(workingNode->stringData, source.stringData); + // make sure to set the next pointer to NULL! + workingNode->nextPtr = NULL; + // return workingNode + return workingNode; +} + /* Name: addProcess Process: allocates the memory for the pcb, grabs the data from the created PCB, @@ -71,12 +97,33 @@ bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int array singlePCB->allocatedMemOffsets[allocateIterator] = offset; singlePCB->allocatedMemSizes[allocateIterator] = size; allocateIterator = allocateIterator + 1; - printf("Alloc Iter: %d\n", allocateIterator); + // printf("Alloc Iter: %d\n", allocateIterator); } // return true (temp) return true; } +/* +Name: createFileLogList +Process: initializes the logging file struct +Function Input/Parameters: none +Function Output/Parameters: none +Function Output/Returned: head pointer to the logfile struct +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, sizeof, ??? +*/ +logFileLL *createFileLogList() +{ + // allocate and create the logFileLL using malloc and size of + logFileLL *headBlock; + headBlock = malloc(sizeof(logFileLL)); + // set the head pointer to NULL + headBlock->headPtr = NULL; + // return headBlock + return headBlock; +} + /* Name: createProcessList Process: reads through the opcode struct to fill out the linked list of PCBs @@ -122,6 +169,26 @@ bool deallocMemory(ProcessControlBlock *singlePCB, int arraySize) return true; } +/* +Name: destroyFileLogList +Process: deallocates memory used for the linked list struct +Function Input/Parameters: head pointer to linked list (logFileLL *) +Function Output/Parameters: none +Function Output/Returned: NULL +Device Input/Device: none +Device Output/Device: none +Dependencies: free, destroyFileLogHelper, ??? +*/ +logFileLL *destroyFileLogList(logFileLL *linkedListPtr) +{ + // call the first destroyFileLogHelper + destroyFileLogHelper(linkedListPtr->headPtr); + // free the rest of the struct + free(linkedListPtr); + // return null + return NULL; +} + /* Name: destroyProcessList Process: deallocates memory used for the linked list struct @@ -142,6 +209,30 @@ ProcessControlBlockLL *destroyProcessList(ProcessControlBlockLL *linkedListPtr) return NULL; } +/* +Name: destroyFileLogHelper +Process: recursively clears the logfile linked list struct, freeing the struct +Function Input/Parameters: head pointer to logfile list (logFile *) +Function Output/Parameters: none +Function Output/Returned: NULL +Device Input/Device: none +Device Output/Device: none +Dependencies: free, destroyFileLogHelper(recursively), ??? +*/ +logFile *destroyFileLogHelper(logFile *nodePtr) +{ + // check to see if the pointer is NOT null + if (nodePtr != NULL) + { + // if not null, move to the next pointer (recurse) + nodePtr->nextPtr = destroyFileLogHelper(nodePtr->nextPtr); + } + // free the 'parent' node + free(nodePtr); + // return null + return NULL; +} + /* Name: destroyProcessListHelper Process: recursively clears the PCB linked list struct, freeing the struct @@ -343,48 +434,156 @@ Device Input/Device: none Device Output/Device: none Dependencies: fprintf, ??? */ -void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd) +logFileLL *logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd, logFileLL *logPtr) { - if(configPtr->logToCode == LOGTO_BOTH_CODE) + logFile toLog; + // toLog.stringData = malloc(sizeof(*logStr)); + logFile *wkgLogPtr; + wkgLogPtr = logPtr->headPtr; + if (configPtr->logToCode == LOGTO_BOTH_CODE) { - // - FILE *fileWritePtr; - fileWritePtr = fopen(configPtr->logToFileName, "w+"); - if (fileWritePtr != NULL) + // close the file, if at the end. + if (isEnd) { - fprintf(fileWritePtr, "%s", logStr); + FILE *fileWritePtr; + fileWritePtr = fopen(configPtr->logToFileName, "w"); + if (fileWritePtr != NULL) + { + // + while(wkgLogPtr != NULL) + { + // + printf("Data being written."); + fprintf(fileWritePtr, "%s", wkgLogPtr->stringData); + wkgLogPtr = wkgLogPtr->nextPtr; + } + } + fclose(fileWritePtr); + } + else + { + // need to add the string to the end of the LL. + // fprintf(fileWritePtr, "%s", logStr); + copyString(toLog.stringData, logStr); + toLog.nextPtr = NULL; + while(wkgLogPtr != NULL) //wkgLogPtr->nextPtr != NULL + { + // need to add at the end of the LL. + // if (logPtr->headPtr == NULL) + // { + // printf("Added to log."); + // logPtr->headPtr = addLog(toLog); + // // wkgLogPtr = logPtr->headPtr; + // } + // else + // { + // while(wkgLogPtr != NULL) + // { + // printf("Added to log at end."); + // wkgLogPtr->nextPtr = addLog(toLog); + // wkgLogPtr = addLog(toLog); + // wkgLogPtr = wkgLogPtr->nextPtr; + // + // } + // } + wkgLogPtr = wkgLogPtr->nextPtr; + } + // if (wkgLogPtr == NULL) + // { + // // + // printf("Added to end of log."); + // wkgLogPtr = addLog(toLog); + // } + if (logPtr->headPtr == NULL) + { + printf("Added to log."); + logPtr->headPtr = addLog(toLog); + // wkgLogPtr = logPtr->headPtr; + } + // wkgLogPtr->nextPtr = addLog(toLog); 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) + 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); + // if (isEnd) + // { + // printf("\nSimulator will output to a file.\n"); + // FILE *fileWritePtr; + // fileWritePtr = fopen(configPtr->logToFileName, "w"); + // if (fileWritePtr != NULL) + // { + // // + // while(wkgLogPtr->nextPtr != NULL) + // { + // // + // fprintf(fileWritePtr, "%s", wkgLogPtr->stringData); + // wkgLogPtr = wkgLogPtr->nextPtr; + // } + // } + // fclose(fileWritePtr); + // } + // else + // { + // // need to add the string to the end of the LL. + // // fprintf(fileWritePtr, "%s", logStr); + // copyString(toLog.stringData, logStr); + // toLog.nextPtr = NULL; + // while(wkgLogPtr->nextPtr != NULL) + // { + // // + // wkgLogPtr = wkgLogPtr->nextPtr; + // } + // wkgLogPtr->nextPtr = addLog(toLog); + // // fprintf(stdout, "%s", logStr); + // } } else { fprintf(stdout, "%s", logStr); } + // 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); + // } + return logPtr; } /* @@ -400,7 +599,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) +bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB, logFileLL *logList) { bool memDisplay = configPtr->memDisplay; ProcessControlBlock *wkgPtr; @@ -591,7 +790,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId, logFileLL *logList) { char timeStringy[MAX_STR_LEN]; // char *command = workingMeta->command; @@ -602,13 +801,13 @@ void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr int *cpuTimePtr = &cpuTime; 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); + logOutput(configPtr, cpuOutput, false, logList); // run timer for intArg * procCycleRate pthread_t cpuThread; pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); 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); + logOutput(configPtr, cpuOutput, false, logList); // pthread_exit(NULL); } @@ -622,7 +821,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId, logFileLL *logList) { char timeStringy[MAX_STR_LEN]; char ioOutput[MAX_STR_LEN]; @@ -630,12 +829,12 @@ void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int *ioTimePtr = &ioTime; 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); + logOutput(configPtr, ioOutput, false, logList); pthread_t ioThread; pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); 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); + logOutput(configPtr, ioOutput, false, logList); } /* @@ -648,7 +847,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ -void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList) +void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList, logFileLL *logList) { // run over the entire process, running the CPU when a CPU cycle comes up // or a run IO when an IO cycle comes up @@ -673,12 +872,12 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce 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); + runCPU(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, logList); } if(compareString(command, "dev") == EQUIV) { // run IO operations for the required amount of time. - runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); + runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, logList); } if(compareString(command, "mem") == EQUIV) { @@ -686,27 +885,27 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce if(compareString(argument, "allocate") == EQUIV) { sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); // run the memory manager in allocate mode - memManagerSuccess = memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + memManagerSuccess = memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB, logList); if(!memManagerSuccess) { // sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); } } else if(compareString(argument, "access") == EQUIV) { sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); // run the memory manager in access mode - memManagerSuccess = memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); + memManagerSuccess = memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB, logList); if (!memManagerSuccess) { // sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); } } } @@ -721,16 +920,16 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce { // sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); } else { // sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); - logOutput(configPtr, processOutput, false); + logOutput(configPtr, processOutput, false, logList); } // deallocate the memory for the process - memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB, logList); } /* @@ -753,6 +952,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // need a variable for headPointer to point ProcessControlBlockLL *pcbList; ProcessControlBlock *pcbPtr; + logFileLL *loggingList; // string variable for nextCode, temp unused // char *nextCode; // string variable for the timer stuff @@ -763,10 +963,13 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) int memoryOffset = 0; int memorySize = 1; + // create the file list with createFileLogList, store the pointed to address + loggingList = createFileLogList(); + 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); + logOutput(configPtr, simulatorOutput, false, loggingList); // int variable for process to run int currentPid; // create the process list with createProcessList, store the pointed to address @@ -795,10 +998,10 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) int *processTimeLeftPtr = &processTimeLeft; // set the current process id to the first scheduled process - currentPid = scheduleProcess(pcbList, configPtr); + currentPid = scheduleProcess(pcbList, configPtr, loggingList); // initialize memory with the memManager - memManager(pcbList, MEMORY_INITIALIZE, memoryOffset, memorySize, configPtr, pcbList->headPtr); + memManager(pcbList, MEMORY_INITIALIZE, memoryOffset, memorySize, configPtr, pcbList->headPtr, loggingList); // loop until current process is hit for(processIterator = 0; processIterator < processCount; processIterator++) @@ -813,13 +1016,13 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // 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); + logOutput(configPtr, simulatorOutput, false, loggingList); pthread_t runThread; pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr); - runProcess(pcbPtr, configPtr, pcbList); + runProcess(pcbPtr, configPtr, pcbList, loggingList); // 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); + logOutput(configPtr, simulatorOutput, false, loggingList); pcbPtr->process_state = PROCESS_STATE_TERMINATED; pthread_join(runThread, NULL); } @@ -827,20 +1030,22 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) processTimeLeftPtr = &processTimeLeft; pcbPtr = pcbPtr->nextPtr; } - currentPid = scheduleProcess(pcbList, configPtr); + currentPid = scheduleProcess(pcbList, configPtr, loggingList); pcbPtr = pcbList->headPtr; } pthread_join(cpuThread, NULL); // deallocate all the memory for each process. - memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr); + memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr, loggingList); sprintf(simulatorOutput, "%f, OS: System Stop\n", accessTimer(LAP_TIMER, timeStringy)); - logOutput(configPtr, simulatorOutput, false); + logOutput(configPtr, simulatorOutput, false, loggingList); sprintf(simulatorOutput, "%f, OS: Simulation End\n", accessTimer(LAP_TIMER, timeStringy)); - logOutput(configPtr, simulatorOutput, true); + logOutput(configPtr, simulatorOutput, true, loggingList); // deallocate the process list with destroyProcessList destroyProcessList(pcbList); // once complete, log the output to FILE if required - logOutput(configPtr, "", true); + // logOutput(configPtr, "", true, loggingList); + // deallocate the file log list with destroyFileLogList + destroyFileLogList(loggingList); // pthread_exit(NULL); // this line seems to make the program execution stop short... no warning either // void function, no return. } @@ -856,7 +1061,7 @@ Device Input/Device: none Device Output/Device: none Dependencies: sprintf, logOutput, ??? */ -int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr) +int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr, logFileLL *logList) { ProcessControlBlock *wkgPtr; int returnPid = -1; @@ -898,7 +1103,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt 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); + logOutput(configPtr, loggingStr, false, logList); } // move to the next pointer wkgPtr = wkgPtr->nextPtr; @@ -913,7 +1118,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt { //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); + logOutput(configPtr, loggingStr, false, logList); returnPid = wkgPtr->uniquePid; } // move to next pointer @@ -941,7 +1146,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt 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); + logOutput(configPtr, loggingStr, false, logList); } // move to the next pointer wkgPtr = wkgPtr->nextPtr; @@ -992,7 +1197,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt { // 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); + logOutput(configPtr, loggingStr, false, logList); } returnPid = shortestJobProcNum; break; diff --git a/Sim03/simulator.h b/Sim03/simulator.h index 9e9e59f..4851092 100644 --- a/Sim03/simulator.h +++ b/Sim03/simulator.h @@ -25,6 +25,19 @@ typedef enum{ MEMORY_DEALLOCATE } MEMORY_SIGNALS; +typedef struct logFileStruct +{ + char stringData[HUGE_STR_LEN]; + // connect to the next process control block here + struct logFileStruct *nextPtr; +} logFile; + +typedef struct logFileLLStruct +{ + // holds the head ptr for PCBs + logFile *headPtr; +} logFileLL; + typedef struct ProcessControlBlockStruct { int uniquePid; @@ -83,6 +96,31 @@ Device Output/Device: none Dependencies: ??? */ +/* +Name: accessMemory +Process: checks that the memory is between the offset and the size. + checks that the memory is ??? +Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) +Function Output/Parameters: none +Function Output/Returned: boolean to indicate success or failure of accessed memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool accessMemory(ProcessControlBlock *singlePCB, int offset, int size); + +/* +Name: addLog +Process: allocates the memory for the log, ... +Function Input/Parameters: source log (logFile) +Function Output/Parameters: none +Function Output/Returned: filled PCB (logFile *) +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, sizeof, ??? +*/ +logFile *addLog(const logFile source); + /* Name: addProcess Process: allocates the memory for the pcb, grabs the data from the created PCB, @@ -96,9 +134,33 @@ Dependencies: malloc, sizeof, ??? */ ProcessControlBlock *addProcess(const ProcessControlBlock source); +/* +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: boolean to indicate success or failure of allocated memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int arraySize); + +/* +Name: createFileLogList +Process: initializes the logging file struct +Function Input/Parameters: none +Function Output/Parameters: none +Function Output/Returned: head pointer to the logfile struct +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, sizeof, ??? +*/ +logFileLL *createFileLogList(); + /* Name: createProcessList -Process: initializes head pointer to the PCBs +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 @@ -108,6 +170,30 @@ Dependencies: malloc, sizeof, ??? */ ProcessControlBlockLL *createProcessList(); +/* +Name: deallocMemory +Process: 'deallocates' memory within the PCB, removes every offset and size within it's PCB +Function Input/Parameters: source PCB (ProcessControlBlock *) +Function Output/Parameters: none +Function Output/Returned: boolean to indicate success or failure of allocated memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool deallocMemory(ProcessControlBlock *singlePCB, int arraySize); + +/* +Name: destroyFileLogList +Process: deallocates memory used for the linked list struct +Function Input/Parameters: head pointer to linked list (logFileLL *) +Function Output/Parameters: none +Function Output/Returned: NULL +Device Input/Device: none +Device Output/Device: none +Dependencies: free, destroyFileLogHelper, ??? +*/ +logFileLL *destroyFileLogList(logFileLL *linkedListPtr); + /* Name: destroyProcessList Process: deallocates memory used for the linked list struct @@ -120,6 +206,18 @@ Dependencies: free, destroyProcessListHelper, ??? */ ProcessControlBlockLL *destroyProcessList(ProcessControlBlockLL *linkedListPtr); +/* +Name: destroyFileLogHelper +Process: recursively clears the logfile linked list struct, freeing the struct +Function Input/Parameters: head pointer to logfile list (logFile *) +Function Output/Parameters: none +Function Output/Returned: NULL +Device Input/Device: none +Device Output/Device: none +Dependencies: free, destroyFileLogHelper(recursively), ??? +*/ +logFile *destroyFileLogHelper(logFile *nodePtr); + /* Name: destroyProcessListHelper Process: recursively clears the PCB linked list struct, freeing the struct @@ -160,16 +258,31 @@ int findMin(int one, int another); /* Name: logOutput Process: Takes in a string, and then outputs it to monitor AND/OR file -Function Input/Parameters: string (char *), file pointer (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: sprintf, ??? +Dependencies: fprintf, ??? */ -void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd); +logFileLL *logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd, logFileLL *logPtr); + +/* +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: boolean for success or failure of memory management +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB, logFileLL *logList); /* Name: runCPU @@ -179,9 +292,9 @@ Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none -Dependencies: ??? +Dependencies: pthreads, sprintf, logOutput, ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId, logFileLL *logList); /* Name: runIO @@ -191,44 +304,46 @@ Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Device: none -Dependencies: ??? +Dependencies: pthreads, sprintf, logOutput, ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId, logFileLL *logList); + /* -Name: runSim -Process: primary simulation driver -Function Input/Parameters: configuration data (ConfigDataType *), - metadata (OpCodeType *) +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: ??? +Dependencies: accessTimer, compareString, runCPU, runIO, ??? +*/ +void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList, logFileLL *logList); + +/* +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); /* 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 *) +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: ??? +Dependencies: sprintf, logOutput, ??? */ -int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr); - -/* -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: ??? -*/ -// void *simThread(int milSec); +int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr, logFileLL *logList); #endif // SIMULATORX \ No newline at end of file diff --git a/Sim04/OS_SimDriver.c b/Sim04/OS_SimDriver.c new file mode 100644 index 0000000..7d1fbf0 --- /dev/null +++ b/Sim04/OS_SimDriver.c @@ -0,0 +1,246 @@ +// header files +#include "OS_SimDriver.h" + +int main(int argc, char **argv) +{ + // initialize program (variables and title) + ConfigDataType *configDataPtr = NULL; + OpCodeType *metaDataPtr = NULL; + char errorMsg[MAX_STR_LEN]; + CmdLineData cmdLineData; + bool configUploadSuccess = false; + + // show title + // fct: printf + printf("\nSimulator Program\n"); + printf("=================\n\n"); + + // process command line arguments + // check for at least one correct switch and config file name verified + // fct: processCmdLine + if(processCmdLine(argc, argv, &cmdLineData)) + { + // upload config file, check for success + // fct: getConfigData + if(getConfigData(cmdLineData.fileName, &configDataPtr, errorMsg)) + { + // check for config display flag + if(cmdLineData.configDisplayFlag) + { + // display config display flag + // fct: displayConfigData + displayConfigData(configDataPtr); + } + // set config upload success flag + configUploadSuccess = true; + } + // otherwise, assume config file upload failure + else + { + // show error message, end program + // fct: printf + printf("\nConfig Upload Error: %s, program aborted\n\n", errorMsg); + } + + // check for config success and need for metadata + if(configUploadSuccess && + (cmdLineData.mdDisplayFlag || cmdLineData.runSimFlag)) + { + // upload metadata file, check for success + // fct: getMetaData + if(getMetaData(configDataPtr->metaDataFileName, + &metaDataPtr, errorMsg)) + { + // check metadata display flag + if(cmdLineData.mdDisplayFlag) + { + // display metadata + // fct: displayMetaData + displayMetaData(metaDataPtr); + } + // check run simulator flag + if(cmdLineData.runSimFlag) + { + // run simulator + // fct: runSim + runSim(configDataPtr, metaDataPtr); + } + + } + // otherwise, assume metadata upload failure + else + { + // show error message, end program + // fct: printf + printf("\nMetadata Upload Error: %s, program aborted\n", + errorMsg); + } + } + // end check for config success and need for metadata + + // clean up config data as needed + // fct: clearConfigData + configDataPtr = clearConfigData(configDataPtr); + + // clean up metadata as needed + // fct: clearMetaDataList + metaDataPtr = clearMetaDataList(metaDataPtr); + } + // end process command line arguments + + // otherwise, assume command line failure + else + { + // show command line argument requirements + // fct: showCommandLineFormat + showCommandLineFormat(); + } + // show program end + // fct: printf + printf("\nSimulator Program End.\n"); + + // return program success + return 0; +} + +/* +Name: clearCmdLineStruct +Process: sets command line structure data to defaults + Booleans to false, fileName to empty string +Function Input/Parameters: pointer to command line structure (CmdLineData *) +Function Output/Parameters: pointer to command line structure (CmdLineData *) + with updated members +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +void clearCmdLineStruct(CmdLineData *clDataPtr) +{ + // set all struct members to default + clDataPtr->programRunFlag = false; + clDataPtr->configDisplayFlag = false; + clDataPtr->mdDisplayFlag = false; + clDataPtr->runSimFlag = false; + clDataPtr->fileName[0] = NULL_CHAR; + // void function, no return. +} + +/* +Name: processCmdLine +Process: checks for at least two arguments, + then sets Booleans depending on command line switches + which can be in any order, + also captures config file name which must be last arugment +Function Input/Parameters: number of arguments (int), + vector of arguments (char **) +Function Output/Parameters: pointer to command line structure (CmdLineData *) + with updated members, + set to default values if failure + to capture arguments +Function Output/Returned: Boolean result of argument capture + true if at least one switch and config file name, + false otherwise +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool processCmdLine(int numArgs, char **strVector, CmdLineData *clDataPtr) +{ + // initialize function and variables + + // initialize structure to defaults + // fct: clearCmdLineStruct + clearCmdLineStruct(clDataPtr); + // initialize success flags to false + bool atLeastOneSwitchFlag = false; + bool correctConfigFileFlag = false; + // initialize first arg index to one + int argIndex = 1; + // iniitialize file variables + int fileStrLen, fileStrSubLoc; + // must have program name, one switch, config file name at minimum + if(numArgs >= MIN_NUM_ARGS) + { + // loop across args (starting at 1) and program run flag + while(argIndex < numArgs) + { + // check for -dc + if(compareString(strVector[argIndex], "-dc") == 0) + { + // set config display flag + clDataPtr->configDisplayFlag = true; + // set at least one switch flag + atLeastOneSwitchFlag = true; + } + // otherwise, check for -dm + else if(compareString(strVector[argIndex], "-dm") == 0) + { + // set metadata display flag + clDataPtr->mdDisplayFlag = true; + // set at least one switch flag + atLeastOneSwitchFlag = true; + } + // otherwise, check for -rs + else if(compareString(strVector[argIndex], "-rs") == 0) + { + // set run simulator flag + clDataPtr->runSimFlag = true; + // set at least one switch flag + atLeastOneSwitchFlag = true; + } + // otherwise, check for file name, ending in .cfg (must be last) + else + { + // find lengths to verify file name + // file name must be last argument, have '.cnf' extension + fileStrLen = getStringLength(strVector[numArgs - 1]); + fileStrSubLoc = findSubString(strVector[numArgs - 1], ".cnf"); + // check for file existence and correct file format + if(fileStrSubLoc != SUBSTRING_NOT_FOUND && + fileStrSubLoc == fileStrLen - LAST_FOUR_LETTERS) + { + // set file name to variable + copyString(clDataPtr->fileName, strVector[numArgs - 1]); + // set success flag to true + correctConfigFileFlag = true; + } + // otherwise, assume bad config file name + else + { + // reset struct, correct config file flag stays false + // fct: clearCmdLineStruct + clearCmdLineStruct(clDataPtr); + } + } + // update arg index + argIndex = argIndex + 1; + } + // end loop across args and program run flag + } + // return verification of at least one switch and file name + return atLeastOneSwitchFlag && correctConfigFileFlag; +} + +/* +Name: showCommandLineFormat +Process: displays command line format as assistance to user +Function Input/Parameters: none +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Monitor: data displayed as spec'd +Dependencies: printf +*/ +void showCommandLineFormat() +{ + // display command line format + // fct: printf + printf("Command Line Format:\n"); + printf(" sim_01 [-dc] [-dm] [-rs] \n"); + printf(" -dc [optional] displays configuration data\n"); + printf(" -dm [optional] displays metadata\n"); + printf(" -rs [optional] runs the simulator\n"); + printf(" required configfile.cnf\n"); + // void function, no return. +} \ No newline at end of file diff --git a/Sim04/OS_SimDriver.h b/Sim04/OS_SimDriver.h new file mode 100644 index 0000000..27a3529 --- /dev/null +++ b/Sim04/OS_SimDriver.h @@ -0,0 +1,74 @@ +#ifndef OS_DRIVER +#define OS_DRIVER + +// header files +#include +#include "StringUtils.h" +#include "configops.h" +#include "metadataops.h" +#include "simulator.h" +// ??? #include "datatypes.h" + +// program constants +typedef enum {SUBSTRING_NOT_FOUND = 0, MIN_NUM_ARGS = 3, LAST_FOUR_LETTERS = 4} PRG_CONSTANTS; + +typedef struct CmdLineDataStruct +{ + bool programRunFlag; + bool configDisplayFlag; + bool mdDisplayFlag; + bool runSimFlag; + char fileName[STD_STR_LEN]; +} CmdLineData; + + +// function prototypes + +/* +Name: clearCmdLineStruct +Process: sets command line structure data to defaults + Booleans to false, fileName to empty string +Function Input/Parameters: pointer to command line structure (CmdLineData *) +Function Output/Parameters: pointer to command line structure (CmdLineData *) + with updated members +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +void clearCmdLineStruct(CmdLineData *clDataPtr); + +/* +Name: processCmdLine +Process: checks for at least two arguments, + then sets Booleans depending on command line switches + which can be in any order, + also captures config file name which must be last arugment +Function Input/Parameters: number of arguments (int), + vector of arguments (char **) +Function Output/Parameters: pointer to command line structure (CmdLineData *) + with updated members, + set to default values if failure + to capture arguments +Function Output/Returned: Boolean result of argument capture + true if at least one switch and config file name, + false otherwise +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool processCmdLine(int numArgs, char **strVector, CmdLineData *clDataPtr); + +/* +Name: showCommandLineFormat +Process: displays command line format as assistance to user +Function Input/Parameters: none +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Monitor: data displayed as spec'd +Dependencies: printf +*/ +void showCommandLineFormat(); + +#endif //OS_DRIVER \ No newline at end of file diff --git a/Sim04/StandardConstants.h b/Sim04/StandardConstants.h new file mode 100644 index 0000000..7b00d4c --- /dev/null +++ b/Sim04/StandardConstants.h @@ -0,0 +1,79 @@ +// Preprocessor directives +#ifndef STANDARD_CONSTANTS_H +#define STANDARD_CONSTANTS_H + +// Include Boolean +#include + +// global constants + +// constant for end of c-string null character +#define CARRIAGE_RETURN_CHAR '\r' + +//constant for a COLON +#define COLON ':' + +//constant for a SEMICOLON +#define SEMICOLON ';' + +//constant for a COMMA +#define COMMA ',' + +//Constant to print a dash +#define DASH '-' + +// constant for equivalent strings +#define EQUIV 0 + +// highest printable character +#define HIGHEST_PRINTABLE_CHAR '~' + +// constant for huge string length +#define HUGE_STR_LEN 256 + +// lowest printable character +#define LOWEST_PRINTABLE_CHAR ' ' + +// constant for small string length +#define MIN_STR_LEN 32 + +// constant for maximum string length +#define MAX_STR_LEN 128 + +// constant for end of c-string null character +#define NEWLINE_CHAR '\n' + +// first non-printable above ASCII +#define DELETE_KEY 127 + +// constant for end of c-string null character +#define NULL_CHAR '\0' + +// columns found in grade sheet before grading columns +#define NUM_BASE_COLS 5 + +// constant for number of grading frequency bins +#define NUM_FREQUENCY_BINS 10 + +//Constant for printing a pipe +#define PIPE '|' + +//Constant for a period +#define PERIOD '.' + +//Constant for PRECISION, 2 digits +#define PRECISION_2 2 + +//Constant for PRECISION, 4 digits +#define PRECISION_4 4 + +// constant for space character +#define SPACE ' ' + +// constant for standard string length +#define STD_STR_LEN 64 + +// constant for smallest string length +#define TINY_STR_LEN 16 + +#endif // STANDARD_CONSTANTS diff --git a/Sim04/StringUtils.c b/Sim04/StringUtils.c new file mode 100644 index 0000000..e0678c2 --- /dev/null +++ b/Sim04/StringUtils.c @@ -0,0 +1,454 @@ +// header files +#include "StringUtils.h" + +// global constants +const int SUBSTRING_NOT_FOUND = 0; + +// list of utils: + // string length + // getStringLength + // string copy + // copyString + // string concatenate + // catString + // string compare (<, >, =) + // compareString + // string substring get + // getSubString + // string substring find + // findSubString + // string set to lower + // toLowerCase + // string get to delimiter + // stringDelimiter + // string get to end of line + // stringEOL + +// function implementations + +/* +Name: catString +Process: concatenates two strings +Function input/parameters: c-style string (char *) +Function output/parameters: c-style string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: malloc, free, getStringLength +*/ +void catString(char *outString, const char *inString) +{ + // initialize variables + // set dest index + int destIndex = getStringLength(outString); + // set source str length + int sourceStrLen = getStringLength(inString); + // create temp string pointer + char *tempString; + int sourceIndex = 0; + + // copy source string in case of aliasing + tempString = (char *)malloc(sizeof(char) * sourceStrLen); + copyString(tempString, inString); + + // loop to end of source string + while(tempString[sourceIndex] != NULL_CHAR) + { + // assign characters to end of destination string + outString[destIndex] = inString[sourceIndex]; + // update indices + destIndex = destIndex + 1; + sourceIndex = sourceIndex + 1; + } + // end loop to end of source string + // set temporary end of destination string + outString[destIndex] = NULL_CHAR; + + // release memory used for temp string + free(tempString); + + // no return, void. +} + +/* +Name: compareString +Process: compares two strings as follows: + - if left string is alphabetically greater than the right string, + returns value greater than zero + - if left string is alphabetically less than the right string, + returns value less than zero + - if strings are alphabetically equal but one is longer, + longer one is greater + - otherwise, returns zero +Function input/parameters: c-style strings (char *) [first and second/left&right] +Function output/parameters: NONE +Function output/returned: results as specfifed above (int) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +int compareString(const char *firstString, const char *secondString) +{ + // initialize variables + int diff, index = 0; + + // loop to end of string (within bounds) + while(firstString[index] != NULL_CHAR && secondString[index] != NULL_CHAR) + { + // get diff of characters + diff = firstString[index] - secondString[index]; + // check diff of characters + if(diff != 0) + { + // return diff + return diff; + } + // increment index + index = index + 1; + } + // end loop to end of string + + // return difference in length of strings, if needed + return getStringLength(firstString) - getStringLength(secondString); +} + +/* +Name: copyString +Process: copies string into new string variable, overwrites destination. +Function input/parameters: c-style string (char *) +Function output/parameters: c-style string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +void copyString(char *outString, const char *inString) +{ + // initialize variables + int index = 0; + + // check to see if outString is not the same as inString. + if(outString != inString) + { + // loop to end of inString + while(inString[index] != NULL_CHAR) + { + // assign characters to end of outString + outString[index] = inString[index]; + // increment index + index = index + 1; + } + // end loop to end of inString + // set end of the outString + outString[index] = NULL_CHAR; + } + + // no return, void. +} + +/* +Name: findSubString +Process: linear search for given substring within another string +Function input/parameters: c-style test string (char *), + c-style source string (char *) +Function output/parameters: NONE +Function output/returned: index of found substring, or + SUBSTRING_NOT_FOUND constant + if string not found +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +int findSubString(const char *testStr, const char *searchSubStr) +{ + // initialize variables + // initialize test string length + int testStrLength = getStringLength(testStr); + // initialize master index (location of substring start point) + int masterIndex = 0; + int searchIndex, internalIndex; + + // loop across testStr + while(masterIndex < testStrLength) + { + // set internal loop index to current test string index + internalIndex = masterIndex; + // set internal search index to zero + searchIndex = 0; + // loop to end of testStr + // while testStr/searchSubStr characters are the same + while(internalIndex <= testStrLength && + testStr[internalIndex] == searchSubStr[searchIndex]) + { + // increment testStr and substring indices + internalIndex = internalIndex + 1; + searchIndex = searchIndex + 1; + // check for end of substring (search complete) + if(searchSubStr[searchIndex] == NULL_CHAR) + { + // return beginning location of substring + return masterIndex; + } + } + // end while testStr/searchSubStr characters are the same + // increment current location starting index + masterIndex = masterIndex + 1; + } + // end loop across testStr + + // return SUBSTRING_NOT_FOUND + return SUBSTRING_NOT_FOUND; +} + +/* +Name: getStringConstrained +Process: captures a string from the file stream with various constraints +Function input/parameters: input stream (FILE *), + clears leading non printable (bool), + clears leading space (bool), + stops at non printable (bool), + stops at specified delimiter (char) + will consume the delimiter. +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: fgetc +*/ +bool getStringConstrained(FILE *inStream, bool clearLeadingNonPrintable, + bool clearLeadingSpace, bool stopAtNonPrintable, + char delimiter, char *capString) +{ + // initialize variables + int intChar = EOF, index = 0; + + // initialize output string + capString[index] = NULL_CHAR; + // capture first value in stream using fgetc + intChar = fgetc(inStream); + // loop to clear non-printable or space if indicated + while((intChar != EOF) && + ((clearLeadingNonPrintable && intChar < (int)SPACE) + || (clearLeadingSpace && intChar == (int)SPACE))) + { + // get next character in stream using fgetc + intChar = fgetc(inStream); + } + // end loop to clear non-printable or space if indicated + // check for end of file found + if(intChar == EOF) + { + // return false (failed) + return false; + } + // loop to get input from file stream + while((intChar != EOF && index < MAX_STR_LEN - 1) && + ((stopAtNonPrintable && intChar >= (int)SPACE) || (!stopAtNonPrintable)) && + (intChar != (char)delimiter)) + { + // [continues if not at end of file and max string len not reached ] + // [AND continues if not printable flag set and characters printable ] + // [OR continues if not printable flag not set ] + // [AND continues if specified delimited is not found ] + + // place character in array element + capString[index] = (char)intChar; + // increment array index + index = index + 1; + // set next element to null character + capString[index] = NULL_CHAR; + // get next character as integer using fgetc + intChar = fgetc(inStream); + } + // end loop to get input from file stream + // return success + return true; +} + +/* +Name: getStringLength +Process: gets length of string from start to NULL_CHAR ('\0') +Function input/parameters: c-style string (char *) +Function output/parameters: NONE +Function output/returned: length of string (int) +Device input/---: NONE +Device output/---: NONE +Dependencies: included by standard libraries +*/ +int getStringLength(const char *stringIn) +{ + // define variables + int stringLength = 0, currentCharacter = 0; + // get user input (not needed) + // do calculations + while (currentCharacter < STD_STR_LEN && stringIn[currentCharacter] != NULL_CHAR) + { + // increment string length + stringLength = stringLength + 1; + // increment currentCharacter + currentCharacter = currentCharacter + 1; + } + // display results (not needed) + // return success + return stringLength; +} + +/* +Name: getStringToDelimiter +Process: captures a string from the input stream to a specified delimiter. + will consume the delimiter. +Function input/parameters: input stream (FILE *), + stops at specified character +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringConstrained +*/ +bool getStringToDelimiter(FILE *inStream, char delimiter, char *capString) +{ + // use getStringConstrained with delimiter to get string + return getStringConstrained(inStream, true, true, true, delimiter, capString); +} + +/* +Name: getStringToLineEnd +Process: captures a string from the input stream to the end of the line +Function input/parameters: input file stream (FILE *) +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringConstrained +*/ +bool getStringToLineEnd(FILE *inStream, char *capString) +{ + // use getStringConstrained with line end character to get string + return getStringConstrained(inStream, true, true, true, '\n', capString); +} + +/* +Name: getSubString +Process: captures sub string within larger string + between two inclusive indices. + returns empty string if either index is out of range, + assumes enough memory in dest string +Function input/parameters: c-style string (char *) + start and end indices (int) +Function output/parameters: c-style destination string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength, malloc, copyString, free +*/ +void getSubString(char *destStr, const char *sourceStr, + int startIndex, int endIndex) +{ + // initialize variables + // set length of source string using getStringLength + int sourceStrLen = getStringLength(sourceStr); + // initialize the destination index to zero + int destIndex = 0; + // initialize source index to start index (parameter) + int sourceIndex = startIndex; + // create pointer for temp string + char *tempStr; + + // check for indices within limits + if(startIndex >= 0 && startIndex <= endIndex && endIndex < sourceStrLen) + { + // create temp string using malloc and copyString + tempStr = (char *)malloc(sourceStrLen + 1); + copyString(tempStr, sourceStr); + // loop across requested substring indices + while(sourceIndex <= endIndex) + { + // assign source character to destination element + destStr[destIndex] = tempStr[sourceIndex]; + // increment indices + destIndex = destIndex + 1; + sourceIndex = sourceIndex + 1; + // set temporary end of destination string + destStr[destIndex] = NULL_CHAR; + } + // end loop across requested substring indices + // free temp string + free(tempStr); + } + + // no return, void. +} + +/* +Name: strToLowerCase +Process: iterates through string, sets any uppercase letter to lowercase + equivalent, does not affect any letter with an upper/lower diff. +Function input/parameters: c-style source string (char *) +Function output/parameters: c-style dest string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: toLowerCase +*/ +void strToLowerCase(char *outString, const char *inString) +{ + // initialize variables + // get source string length + int sourceStrLen = getStringLength(inString); + // create temporary string pointer + char *tempStr; + int index = 0; + + // copy source string in case of aliasing using malloc and copyString + tempStr = (char *)malloc((sizeof(char) * (sourceStrLen + 1))); + copyString(tempStr, inString); + // loop across source string + while(tempStr[index] != NULL_CHAR && index < MAX_STR_LEN) + { + // set individual character to lowercase as needed, assigning back + outString[index] = toLowerCase(tempStr[index]); + // update index + index = index + 1; + // set temporary end of destination string + outString[index] = NULL_CHAR; + } + // end loop across source string + // free temporary string + free(tempStr); + + // no return, void. +} + +/* +Name: toLowerCase +Process: sets character to lowercase letter if uppercase letter, + returns character +Function input/parameters: character input (char) +Function output/parameters: NONE +Function output/returned: character output (char) +Device input/---: NONE +Device output/---: NONE +Dependencies: none +*/ +char toLowerCase(char testChar) +{ + // check for uppercase letter + if(testChar >= 'A' && testChar <= 'Z') + { + // return lowercase letter + return testChar - 'A' + 'a'; + } + // otherwise, assume not uppercase letter, return unchanged + return testChar; +} + +/* +Name: ??? +Process: ??? +Function input/parameters: ??? +Function output/parameters: NONE +Function output/returned: ??? +Device input/---: NONE +Device output/---: NONE +Dependencies: included by standard libraries +*/ \ No newline at end of file diff --git a/Sim04/StringUtils.h b/Sim04/StringUtils.h new file mode 100644 index 0000000..0ff4f49 --- /dev/null +++ b/Sim04/StringUtils.h @@ -0,0 +1,176 @@ +#ifndef STRINGUTILS +#define STRINGUTILS + +// header files +#include +#include +#include +#include +#include +#include "StandardConstants.h" + +// data structures + +// program constants + +// function prototypes + +/* +Name: catString +Process: concatenates two strings +Function input/parameters: c-style string (char *) +Function output/parameters: c-style string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: malloc, free, getStringLength +*/ +void catString(char *outString, const char *inString); + +/* +Name: compareString +Process: compares two strings as follows: + - if left string is alphabetically greater than the right string, + returns value greater than zero + - if left string is alphabetically less than the right string, + returns value less than zero + - if strings are alphabetically equal but one is longer, + longer one is greater + - otherwise, returns zero +Function input/parameters: c-style strings (char *) [first and second/left&right] +Function output/parameters: NONE +Function output/returned: results as specfifed above (int) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +int compareString(const char *firstString, const char *secondString); + +/* +Name: copyString +Process: copies string into new string variable, overwrites destination. +Function input/parameters: c-style string (char *) +Function output/parameters: c-style string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +void copyString(char *outString, const char *inString); + +/* +Name: findSubString +Process: linear search for given substring within another string +Function input/parameters: c-style test string (char *), + c-style source string (char *) +Function output/parameters: NONE +Function output/returned: index of found substring, or + SUBSTRING_NOT_FOUND constant + if string not found +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength +*/ +int findSubString(const char *testStr, const char *searchSubStr); + +/* +Name: getStringConstrained +Process: captures a string from the file stream with various constraints +Function input/parameters: input stream (FILE *), + clears leading non printable (bool), + clears leading space (bool), + stops at non printable (bool), + stops at specified delimiter (char) + will consume the delimiter. +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: fgetc +*/ +bool getStringConstrained(FILE *inStream, bool clearLeadingNonPrintable, + bool clearLeadingSpace, bool stopAtNonPrintable, + char delimiter, char *capString); + +/* +Name: getStringLength +Process: gets length of string from start to NULL_CHAR ('\0') +Function input/parameters: c-style string (char *) +Function output/parameters: NONE +Function output/returned: length of string (int) +Device input/---: NONE +Device output/---: NONE +Dependencies: included by standard libraries +*/ +int getStringLength(const char *stringIn); + +/* +Name: getStringToDelimiter +Process: captures a string from the input stream to a specified delimiter. + will consume the delimiter. +Function input/parameters: input stream (FILE *), + stops at specified character +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringConstrained +*/ +bool getStringToDelimiter(FILE *inStream, char delimiter, char *capString); + +/* +Name: getStringToLineEnd +Process: captures a string from the input stream to the end of the line +Function input/parameters: input file stream (FILE *) +Function output/parameters: c-style string (char *) +Function output/returned: success of operation (bool) +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringConstrained +*/ +bool getStringToLineEnd(FILE *inStream, char *capString); + +/* +Name: getSubString +Process: captures sub string within larger string + between two inclusive indices. + returns empty string if either index is out of range, + assumes enough memory in dest string +Function input/parameters: c-style string (char *) + start and end indices (int) +Function output/parameters: c-style destination string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: getStringLength, malloc, copyString, free +*/ +void getSubString(char *destStr, const char *sourceStr, + int startIndex, int endIndex); + +/* +Name: strToLowerCase +Process: iterates through string, sets any uppercase letter to lowercase + equivalent, does not affect any letter with an upper/lower diff. +Function input/parameters: c-style source string (char *) +Function output/parameters: c-style dest string (char *) +Function output/returned: NONE +Device input/---: NONE +Device output/---: NONE +Dependencies: toLowerCase +*/ +void strToLowerCase(char *outString, const char *inString); + +/* +Name: toLowerCase +Process: sets character to lowercase letter if uppercase letter, + returns character +Function input/parameters: character input (char) +Function output/parameters: NONE +Function output/returned: character output (char) +Device input/---: NONE +Device output/---: NONE +Dependencies: none +*/ +char toLowerCase(char testChar); + +#endif // STRINGUTILS \ No newline at end of file diff --git a/Sim04/config0.cnf b/Sim04/config0.cnf new file mode 100644 index 0000000..9404729 --- /dev/null +++ b/Sim04/config0.cnf @@ -0,0 +1,13 @@ +Start Simulator Configuration File: +Version/Phase : 1.05 +File Path : metadata5.mdf +CPU Scheduling Code : SJF-N +Quantum Time (cycles) : 3 +Memory Available (KB) : 11100 +Memory Display (On/Off) : On +Processor Cycle Time (msec) : 10 +I/O Cycle Time (msec) : 20 +Log To : Both +Log File Path : logfile_1.lgf +End Simulator Configuration File. + diff --git a/Sim04/configops.c b/Sim04/configops.c new file mode 100644 index 0000000..ad604d7 --- /dev/null +++ b/Sim04/configops.c @@ -0,0 +1,608 @@ +#include "configops.h" +#include "StandardConstants.h" +#include "StringUtils.h" + +/* +Name: clearConfigData +Process: frees dynamically allocated config data structure + if it has not already been freed +Function Input/Parameters: pointer to config data structure (ConfigDataType *) +Function Output/Parameters: none +Function Output/Returned: NULL (ConfigDataType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: free +*/ +ConfigDataType *clearConfigData(ConfigDataType *configData) +{ + // initialize function and variables + // check that config data pointer is not null + if(configData != NULL) + { + // free data structure memory + // fct: free + free(configData); + // set config pointer to NULL + configData = NULL; + } + // set config data pointer to null + return NULL; +} + +/* +Name: configCodeToString +Process: utility fct converts configuration code numbers to string they represent +Function Input/Parameters: configuration code (int) +Function Output/Parameters: resulting output string (char *) +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: copyString +*/ +void configCodeToString(int code, char *outString) +{ + // define array with eight items, and short (10) lengths + char displayStrings[8][10] = {"SJF-N","SRTF-P","FCFS-P","RR-P", + "FCFS-N","Monitor", "File", "Both"}; + // copy string to return parameter + // fct: copyString + copyString(outString, displayStrings[code]); + // void function, no return. +} + +/* +Name: displayConfigData +Process: screen dump/display of all config data +Function Input/Parameters: pointer to config data structure (ConfigDataType *) +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Monitor: displayed as spec'd +Dependencies: configCodeToString, printf +*/ +void displayConfigData(ConfigDataType *configData) +{ + // initialize function and variables + char displayString[STD_STR_LEN]; + // print lines of display for all member values + // fct: printf, codeToString + printf("Config File Display\n"); + printf("-------------------\n"); + printf("Version : %3.2f\n", configData->version); + printf("Program File Name : %s\n", configData->metaDataFileName); + configCodeToString(configData->cpuSchedCode, displayString); + printf("CPU Schedule Selection: %s\n", displayString); + printf("Quantum Time : %d\n", configData->quantumCycles); + printf("Memory Display : "); + if(configData->memDisplay) + { + printf("On\n"); + } + else + { + printf("Off\n"); + } + printf("Memory Available : %d\n", configData->memAvailable); + printf("Process Cycle Rate : %d\n", configData->procCycleRate); + printf("I/O Cycle Rate : %d\n", configData->ioCycleRate); + configCodeToString(configData->logToCode, displayString); + printf("Log to Selection : %s\n", displayString); + printf("Log File Name : %s\n\n", configData->logToFileName); + // void function, no return. +} + +/* +Name: getConfigData +Process: driver function for capturing config data from config file +Function Input/Parameters: file name (const char *) +Function Output/Parameters: pointer to config data pointer (ConfigDataType **) + end/result state message pointer (char *) +Function Output/Returned: Boolean result of data access operation (bool) +Device Input/File: config data uploaded +Device Output/Device: none +Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, + malloc, free, stripTrailingSpaces, getDataLineCode, fscanf, + strToLowerCase, valueInRange, getCpuSchedCode, getLogToCode +*/ +bool getConfigData(const char *fileName, + ConfigDataType **configData, char *endStateMsg) +{ + // initialize function and variables + // set constant number of data lines + const int NUM_DATA_LINES = 10; + // set read only constant + const char READ_ONLY_FLAG[] = "r"; + // create pointer for data input + ConfigDataType *tempData; + // declare other variables + FILE *fileAccessPtr; + char dataBuffer[MAX_STR_LEN], lowerCaseDataBuffer[MAX_STR_LEN]; + int intData, dataLineCode, lineCtr = 0; + double doubleData; + // set endStateMsg to success + // fct: copyString + char testMsg[] = "Configuration file upload successful"; + copyString(endStateMsg, testMsg); + // initialize config data pointer in case of return error + *configData = NULL; + // open file + // fct: fopen + fileAccessPtr = fopen(fileName, READ_ONLY_FLAG); + // check for file open failure + if(fileAccessPtr == NULL) + { + // set end state message to config file access error + // fct: copyString + char testMsg[] = "Configuration file access error"; + copyString(endStateMsg, testMsg); + // return file access error + return false; + } + // get first line, check for failure + // fct: getStringToDelimiter, compareString + if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer) + || compareString(dataBuffer, "Start Simulator Configuration File") != 0) + { + // close file access + // fct: fclose + fclose(fileAccessPtr); + // set end state message to corrupt leader line error + // fct: copyString + copyString(endStateMsg, "Corrupt configuration leader line error"); + // return corrupt file data + return false; + } + // create temporary pointer to configuration data structure + // fct: malloc + tempData = (ConfigDataType *) malloc(sizeof(ConfigDataType)); + // loop to end of config data items + while(lineCtr < NUM_DATA_LINES) + { + // get line leader, check for failure + // fct: getStringToDelimiter + if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer)) + { + // free temp struct memory + // fct: free + free(tempData); + // close file access + // fct: fclose + fclose(fileAccessPtr); + // set end state message to line capture failure + // fct: copyString + copyString(endStateMsg, + "Configuration data leader line capture error"); + // return incomplete file error + return false; + } + // strip trailing spaces of config leader lines + // for use in other fcts + // fct: stripTrailingSpaces + stripTrailingSpaces(dataBuffer); + // find correct data line code number from string + // fct: getDataLineCode + dataLineCode = getDataLineCode(dataBuffer); + // check for data line found + if(dataLineCode != CFG_CORRUPT_PROMPT_ERR) + { + // get data value + // check for version number (double value) + if(dataLineCode == CFG_VERSION_CODE) + { + // get version number + // fct: fscanf + fscanf(fileAccessPtr, "%lf", &doubleData); + } + // otherwise, check for metaData, fileNames, + // CPU Scheduling names, or memory display setting (strings) + else if(dataLineCode == CFG_MD_FILE_NAME_CODE || + dataLineCode == CFG_LOG_FILE_NAME_CODE || + dataLineCode == CFG_CPU_SCHED_CODE || + dataLineCode == CFG_LOG_TO_CODE || + dataLineCode == CFG_MEM_DISPLAY_CODE) + { + // get string input + // fct: fscanf + fscanf(fileAccessPtr, "%s", dataBuffer); + // set string to lower case for testing in valueInRange + // fct: strToLowerCase + strToLowerCase(lowerCaseDataBuffer, dataBuffer); + } + // otherwise, assume integer data + else + { + // get integer input + // fct: fscanf + fscanf(fileAccessPtr, "%d", &intData); + } + // check for data value in range + // fct: valueInRange + if(valueInRange(dataLineCode, intData, + doubleData, lowerCaseDataBuffer)) + { + // assign to data pointer depending on config item + // (all config line possibilities) + // fct: copyString, getCpuSchedCode, + // compareString, getLogToCode, as needed + switch(dataLineCode) + { + case CFG_VERSION_CODE: + tempData->version = doubleData; + break; + case CFG_MD_FILE_NAME_CODE: + copyString(tempData->metaDataFileName, dataBuffer); + break; + case CFG_CPU_SCHED_CODE: + tempData->cpuSchedCode = + getCpuSchedCode(lowerCaseDataBuffer); + break; + case CFG_QUANT_CYCLES_CODE: + tempData->quantumCycles = intData; + break; + case CFG_MEM_DISPLAY_CODE: + tempData->memDisplay = + compareString(lowerCaseDataBuffer, "on") == 0; + break; + case CFG_MEM_AVAILABLE_CODE: + tempData->memAvailable = intData; + break; + case CFG_PROC_CYCLES_CODE: + tempData->procCycleRate = intData; + break; + case CFG_IO_CYCLES_CODE: + tempData->ioCycleRate = intData; + break; + case CFG_LOG_TO_CODE: + tempData->logToCode = getLogToCode(lowerCaseDataBuffer); + break; + case CFG_LOG_FILE_NAME_CODE: + copyString(tempData->logToFileName, dataBuffer); + break; + } + } + // otherwise, assume data value not in range + else + { + // free temp struct memory + // fct: free + free(tempData); + // close file access + // fct: fclose + fclose(fileAccessPtr); + // set end state message to configuration data out of range + // fct: copyString + copyString(endStateMsg, "Configuration item out of range"); + // return data out of range + return false; + } + } + // otherwise, check for data line not found + else + { + // free temp struct memory + // fct: free + free(tempData); + // close file access + // fct: fclose + fclose(fileAccessPtr); + // set end state message to configuration corrupt prompt error + // fct: copyString + copyString(endStateMsg, "Corrupted configuration prompt"); + // return corrupt config file code + return false; + } + // increment line counter + lineCtr = lineCtr + 1; + } + // end loop to end of config data items + // acquire end of sim config string + // fct: getStringToDelimiter, compareString + if(!getStringToDelimiter(fileAccessPtr, PERIOD, dataBuffer) || + compareString(dataBuffer, "End Simulator Configuration File") != 0) + { + // free temp struct memory + // fct: free + free(tempData); + // close file access + // fct: fclose + fclose(fileAccessPtr); + // set end state message to corrupt configuration end line + // fct: copyString + copyString(endStateMsg, "Configuration end line capture error"); + // return corrupt file data + return false; + } + // test for "file only" output so memory diagnostics do not display + tempData->memDisplay = tempData->memDisplay && + tempData->logToCode != LOGTO_FILE_CODE; + // assign temp ptr to parameter return ptr + *configData = tempData; + // close file access + // fct: fclose + fclose(fileAccessPtr); + // return no error code + return true; +} + +/* +Name: getCpuSchedCode +Process: converts cpu schedule string to code (all scheduling possibilities) +Function Input/Parameters: lower case code string (const char *) +Function Output/Parameters: none +Function Output/Returned: cpu schedule code (ConfigDataCodes) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigDataCodes getCpuSchedCode(const char *lowerCaseCodeStr) +{ + // iniitalize function and variables + // set default return to FCFS-N + ConfigDataCodes returnVal = CPU_SCHED_FCFS_N_CODE; + // check for SJF-N + // fct: compareString + if(compareString(lowerCaseCodeStr, "sjf-n") == 0) + { + // set SJF-N code + returnVal = CPU_SCHED_SJF_N_CODE; + } + // check for SRTF-P + // fct: compareString + if(compareString(lowerCaseCodeStr, "srtf-p") == 0) + { + // set SRTF-P code + returnVal = CPU_SCHED_SRTF_P_CODE; + } + // check for FCFS-P + // fct: compareString + if(compareString(lowerCaseCodeStr, "fcfs-p") == 0) + { + // set FCFS-P code + returnVal = CPU_SCHED_FCFS_P_CODE; + } + // check for RR-P + // fct: compareString + if(compareString(lowerCaseCodeStr, "rr-p") == 0) + { + // set RR-P code + returnVal = CPU_SCHED_RR_P_CODE; + } + return returnVal; +} + +/* +Name: getDataLineCode +Process: converts leader line string to configuration code value + (processes all config file leader lines) +Function Input/Parameters: config leader line string (const char *) +Function Output/Parameters: none +Function Output/Returned: configuration code value (ConfigCodeMessages) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigCodeMessages getDataLineCode(const char *dataBuffer) +{ + // iniitalize function and variables + // return appropriate code depending on prompt string provided + // fct: compareString + if(compareString(dataBuffer, "Version/Phase") == 0) + { + return CFG_VERSION_CODE; + } + if(compareString(dataBuffer, "File Path") == 0) + { + return CFG_MD_FILE_NAME_CODE; + } + if(compareString(dataBuffer, "CPU Scheduling Code") == 0) + { + return CFG_CPU_SCHED_CODE; + } + if(compareString(dataBuffer, "Quantum Time (cycles)") == 0) + { + return CFG_QUANT_CYCLES_CODE; + } + if(compareString(dataBuffer, "Memory Display (On/Off)") == 0) + { + return CFG_MEM_DISPLAY_CODE; + } + if(compareString(dataBuffer, "Memory Available (KB)") == 0) + { + return CFG_MEM_AVAILABLE_CODE; + } + if(compareString(dataBuffer, "Processor Cycle Time (msec)") == 0) + { + return CFG_PROC_CYCLES_CODE; + } + if(compareString(dataBuffer, "I/O Cycle Time (msec)") == 0) + { + return CFG_IO_CYCLES_CODE; + } + if(compareString(dataBuffer, "Log To") == 0) + { + return CFG_LOG_TO_CODE; + } + if(compareString(dataBuffer, "Log File Path") == 0) + { + return CFG_LOG_FILE_NAME_CODE; + } + // return corrupt leader line error code + return CFG_CORRUPT_PROMPT_ERR; +} + +/* +Name: getLogToCode +Process: converts "log to" text to + configuration data code (three log to strings) +Function Input/Parameters: lower case log to string (const char *) +Function Output/Parameters: none +Function Output/Returned: configuration data code value +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigDataCodes getLogToCode(const char *lowerCaseLogToStr) +{ + // initialize function and variables + // set default to log to monitor + ConfigDataCodes returnVal = LOGTO_MONITOR_CODE; + // check for BOTH + // fct: compareString + if(compareString(lowerCaseLogToStr, "both") == 0) + { + // set return value to both code + returnVal = LOGTO_BOTH_CODE; + } + // check for FILE + // fct: compareString + if(compareString(lowerCaseLogToStr, "file") == 0) + { + // set return value to file code + returnVal = LOGTO_FILE_CODE; + } + // return selected code + return returnVal; +} + +/* +Name: stripTrailingSpaces +Process: removes trailing spaces from input config leader lines +Function Input/Parameters: config leader line string (char *) +Function Output/Parameters: updates config leader line string (char *) +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: getStringLength +*/ +void stripTrailingSpaces(char *str) +{ + // initialize index to length of string - 1 to get highest array index + int index = getStringLength(str) - 1; + // loop while space is found at the end of string + while(str[index] == SPACE) + { + // set element to NULL_CHAR + str[index] = NULL_CHAR; + // decrement index + index = index - 1; + } + // end loop from end of string + // void function, no return. +} + +/* +Name: valueInRange +Process: checks for config data values in range, including str values +Function Input/Parameters: line code number for specific config value (int), + integer value, as needed (int), + double value, as needed (double), + string value, as needed (const char *) +Function Output/Parameters: none +Function Output/Returned: Boolean result of the range test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool valueInRange(int lineCode, int intVal, double doubleVal, + const char *lowerCaseStringVal) +{ + // initialize function and variables + // set result to true, all tests are to find false + bool result = true; + // use line code to identify prompt line + switch(lineCode) + { + // for version code + case CFG_VERSION_CODE: + // check if limits of version code are exceeded + if(doubleVal < 0.00 || doubleVal > 10.00) + { + // set bool to false + result = false; + } + // break + break; + // for cpu scheduling code + case CFG_CPU_SCHED_CODE: + // check for not finding one of the scheduling strings + // fct: compareString + if(compareString(lowerCaseStringVal, "fcfs-n") != 0 && + compareString(lowerCaseStringVal, "sjf-n") != 0 && + compareString(lowerCaseStringVal, "srtf-p") != 0 && + compareString(lowerCaseStringVal, "fcfs-p") != 0 && + compareString(lowerCaseStringVal, "rr-p") != 0) + { + // set bool to false + result = false; + } + // break + break; + // for quantum cycles + case CFG_QUANT_CYCLES_CODE: + // check for quantum cycles limits exceeded + if(intVal < 0 || intVal > 100) + { + // set bool to false + result = false; + } + // break + break; + // for memory display + case CFG_MEM_DISPLAY_CODE: + // check for not finding either on or off + // fct: compareString + if(compareString(lowerCaseStringVal, "on") != 0 && + compareString(lowerCaseStringVal, "off") != 0) + { + // set bool to false + result = false; + } + // break + break; + // for memory available + case CFG_MEM_AVAILABLE_CODE: + // check for memory limits exceeded + if(intVal < 1024 || intVal > 102400) + { + // set bool to false + result = false; + } + // break + break; + // check for process cycles + case CFG_PROC_CYCLES_CODE: + // check for process cycles limits exceeded + if(intVal < 1 || intVal > 100) + { + // set bool to false + result = false; + } + // break + break; + // check for process cycles + case CFG_IO_CYCLES_CODE: + // check for process cycles limits exceeded + if(intVal < 1 || intVal > 1000) + { + // set bool to false + result = false; + } + // break + break; + // check for log to operation + case CFG_LOG_TO_CODE: + // check for not finding one of the log to strings + // fct: compareString + if(compareString(lowerCaseStringVal, "both") != 0 && + compareString(lowerCaseStringVal, "monitor") != 0 && + compareString(lowerCaseStringVal, "file") != 0) + { + // set bool to false + result = false; + } + // break + break; + } + // return result of limits analysis + return result; +} \ No newline at end of file diff --git a/Sim04/configops.h b/Sim04/configops.h new file mode 100644 index 0000000..c8d0ee9 --- /dev/null +++ b/Sim04/configops.h @@ -0,0 +1,168 @@ +#ifndef CONFIGOPS +#define CONFIGOPS + +#include "StandardConstants.h" +#include "StringUtils.h" + +typedef enum {CFG_FILE_ACCESS_ERR, + CFG_CORRUPT_DESCRIPTOR_ERR, + CFG_DATA_OUT_OF_RANGE_ERR, + CFG_CORRUPT_PROMPT_ERR, + CFG_VERSION_CODE, + CFG_MD_FILE_NAME_CODE, + CFG_CPU_SCHED_CODE, + CFG_QUANT_CYCLES_CODE, + CFG_MEM_DISPLAY_CODE, + CFG_MEM_AVAILABLE_CODE, + CFG_PROC_CYCLES_CODE, + CFG_IO_CYCLES_CODE, + CFG_LOG_TO_CODE, + CFG_LOG_FILE_NAME_CODE + } ConfigCodeMessages; + +typedef enum {CPU_SCHED_SJF_N_CODE, + CPU_SCHED_SRTF_P_CODE, + CPU_SCHED_FCFS_P_CODE, + CPU_SCHED_RR_P_CODE, + CPU_SCHED_FCFS_N_CODE, + LOGTO_MONITOR_CODE, + LOGTO_FILE_CODE, + LOGTO_BOTH_CODE, + NON_PREEMPTIVE_CODE, + PREEMPTIVE_CODE + } ConfigDataCodes; + +typedef struct ConfigDataTypeStruct +{ + double version; + char metaDataFileName[MAX_STR_LEN]; + int cpuSchedCode; + int quantumCycles; + bool memDisplay; + int memAvailable; + int procCycleRate; + int ioCycleRate; + int logToCode; + char logToFileName[MAX_STR_LEN]; +} ConfigDataType; + +/* +Name: clearConfigData +Process: frees dynamically allocated config data structure + if it has not already been freed +Function Input/Parameters: pointer to config data structure (ConfigDataType *) +Function Output/Parameters: none +Function Output/Returned: NULL (ConfigDataType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +ConfigDataType *clearConfigData(ConfigDataType *configData); + +/* +Name: configCodeToString +Process: utility fct converts configuration code numbers to string they represent +Function Input/Parameters: configuration code (int) +Function Output/Parameters: resulting output string (char *) +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: copyString +*/ +void configCodeToString(int code, char *outString); + +/* +Name: displayConfigData +Process: screen dump/display of all config data +Function Input/Parameters: pointer to config data structure (ConfigDataType *) +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Monitor: displayed as spec'd +Dependencies: ??? +*/ +void displayConfigData(ConfigDataType *configData); + +/* +Name: getConfigData +Process: driver function for capturing config data from config file +Function Input/Parameters: file name (const char *) +Function Output/Parameters: pointer to config data pointer (ConfigDataType **) + end/result state message pointer (char *) +Function Output/Returned: Boolean result of data access operation (bool) +Device Input/File: config data uploaded +Device Output/Device: none +Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, + malloc, free, stripTrailingSpaces, getDataLineCode, fscanf, + setStrToLowerCase, valueInRange, getCpuSchedCode, getLogToCode +*/ +bool getConfigData(const char *fileName, + ConfigDataType **configData, char *endStateMsg); + +/* +Name: getCpuSchedCode +Process: converts cpu schedule string to code (all scheduling possibilities) +Function Input/Parameters: lower case code string (const char *) +Function Output/Parameters: none +Function Output/Returned: cpu schedule code (ConfigDataCodes) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigDataCodes getCpuSchedCode(const char *lowerCaseCodeStr); + +/* +Name: getDataLineCode +Process: converts leader line string to configuration code value + (processes all config file leader lines) +Function Input/Parameters: config leader line string (const char *) +Function Output/Parameters: none +Function Output/Returned: configuration code value (ConfigCodeMessages) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigCodeMessages getDataLineCode(const char *dataBuffer); + +/* +Name: getLogToCode +Process: converts "log to" text to + configuration data code (three log to strings) +Function Input/Parameters: lower case log to string (const char *) +Function Output/Parameters: none +Function Output/Returned: configuration data code value +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +ConfigDataCodes getLogToCode(const char *lowerCaseLogToStr); + +/* +Name: stripTrailingSpaces +Process: removes trailing spaces from input config leader lines +Function Input/Parameters: config leader line string (char *) +Function Output/Parameters: updates config leader line string (char *) +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: getStringLength +*/ +void stripTrailingSpaces(char *str); + +/* +Name: valueInRange +Process: checks for config data values in range, including str values +Function Input/Parameters: line code number for specific config value (int), + integer value, as needed (int), + double value, as needed (double), + string value, as needed (const char *) +Function Output/Parameters: none +Function Output/Returned: Boolean result of the range test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool valueInRange(int lineCode, int intVal, double doubleVal, + const char *lowerCaseStringVal); + +#endif // CONFIGOPS \ No newline at end of file diff --git a/Sim04/logfile_1.lgf b/Sim04/logfile_1.lgf new file mode 100644 index 0000000..e69de29 diff --git a/Sim04/metadata5.mdf b/Sim04/metadata5.mdf new file mode 100644 index 0000000..3225e59 --- /dev/null +++ b/Sim04/metadata5.mdf @@ -0,0 +1,75 @@ +Start Program Meta-Data Code: +sys start +app start, 0 +dev in, serial, 28 +dev out, video signal, 42 +dev in, sound signal, 40 +dev out, hard drive, 15 +mem allocate, 4000, 2000 +dev in, keyboard, 80 +dev in, serial, 28 +cpu process, 10 +cpu process, 8 +cpu process, 6 +dev out, video signal, 49 +app end +app start, 0 +dev in, serial, 20 +cpu process, 6 +cpu process, 8 +dev out, monitor, 70 +cpu process, 6 +cpu process, 9 +mem allocate, 1000, 3000 +dev out, sound signal, 45 +dev out, hard drive, 15 +dev in, video signal, 49 +dev out, serial, 20 +mem access, 2000, 1000 +app end +app start, 0 +dev in, hard drive, 18 +dev out, video signal, 49 +dev out, usb, 14 +dev out, monitor, 70 +cpu process, 7 +mem allocate, 1500, 2000 +cpu process, 9 +dev in, keyboard, 70 +dev in, video signal, 42 +mem access, 2800, 1000 +cpu process, 5 +cpu process, 6 +app end +app start, 0 +dev in, hard drive, 21 +dev out, sound signal, 30 +cpu process, 7 +mem allocate, 2500, 3000 +dev in, keyboard, 80 +dev in, hard drive, 30 +dev out, video signal, 63 +mem access, 2600, 1500 +dev in, serial, 28 +dev out, sound signal, 25 +cpu process, 9 +mem allocate, 2500, 1000 +dev out, sound signal, 45 +app end +app start, 0 +dev in, serial, 24 +dev out, video signal, 42 +mem allocate, 3000, 3000 +cpu process, 5 +dev in, usb, 10 +cpu process, 8 +cpu process, 9 +mem access, 3500, 2000 +cpu process, 6 +dev out, hard drive, 18 +dev out, hard drive, 24 +dev out, hard drive, 21 +app end +sys end +End Program Meta-Data Code. + diff --git a/Sim04/metadataops.c b/Sim04/metadataops.c new file mode 100644 index 0000000..f2b2256 --- /dev/null +++ b/Sim04/metadataops.c @@ -0,0 +1,729 @@ +#include "metadataops.h" +#include "StandardConstants.h" +#include "StringUtils.h" + +/* +Name: addNode +Process: adds metadata node to linked list recursively, handles empty list +Function Input/Parameters: ptr to head or next linked node (OpCodeType *), + ptr to new node (OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: pointer to previous node, or head node (OpCodeType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, copyString +*/ +OpCodeType *addNode(OpCodeType *localPtr, OpCodeType *newNode) +{ + // initialize function and variables + // check for local pointer assigned to null + if(localPtr == NULL) + { + // access memory for new link/node + // fct: malloc + localPtr = (OpCodeType *) malloc(sizeof(OpCodeType)); + // assign all three values to newly created node + // assign next pointer to null + // fct: copyString + localPtr->pid = newNode->pid; + copyString(localPtr->command, newNode->command); + copyString(localPtr->inOutArg, newNode->inOutArg); + copyString(localPtr->strArg1, newNode->strArg1); + localPtr->intArg2 = newNode->intArg2; + localPtr->intArg3 = newNode->intArg3; + localPtr->opEndTime = newNode->opEndTime; + localPtr->nextNode = NULL; + // return current local pointer + return localPtr; + } + // assume end of list not found + // assign recursive fct to current node's next link + // fct: addNode + localPtr->nextNode = addNode(localPtr->nextNode, newNode); + // return current local ptr + return localPtr; +} + +/* +Name: clearMetaDataList +Process: recursively traverses list, frees dynamically allocated nodes +Function Input/Parameters: node opcode (const OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: NULL (OpCodeType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +OpCodeType *clearMetaDataList(OpCodeType *localPtr) +{ + // initialize function and variables + // check for local pointer not set to null (list not empty) + if(localPtr != NULL) + { + // call recursive function with next pointer + // fct: clearMetaDataList + clearMetaDataList(localPtr->nextNode); + // after recursive call, release mem to OS + // fct: free + free(localPtr); + // set given pointer to NULL + localPtr = NULL; + } + // return NULL to calling fct + return NULL; +} + +/* +Name: displayMetaData +Process: data dump/display of all opcode items +Function Input/Parameters: pointer to + head of opcode/metadata list (const OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: calculated time (int) +Device Input/Device: none +Device Output/Device: none +Dependencies: printf, compareString +*/ +void displayMetaData(const OpCodeType *localPtr) +{ + // initialize function and variables + // display title, with underline + // fct: printf + printf("Metadata File Display\n"); + printf("---------------------\n\n"); + // loop to end of linked list + while(localPtr != NULL) + { + // print leader + // fct: printf + printf("Opcode: "); + // print opcode pid + // fct: printf + printf("/pid: %d", localPtr->pid); + // print opcode command + // fct: printf + printf("/cmd: %s", localPtr->command); + // check for dev op + if(compareString(localPtr->command, "dev") == 0) + { + // print in/out parameter + // fct: printf + printf("/io: %s", localPtr->inOutArg); + } + // otherwise, assume other than dev + else + { + // print NA + // fct: printf + printf("/io: NA"); + } + // print first string argument + // fct: printf + printf("\n\t/arg 1: %s", localPtr->strArg1); + // print first int argument + // fct: printf + printf("/arg 2: %d", localPtr->intArg2); + // print second int argument + // fct: printf + printf("/arg 3: %d", localPtr->intArg3); + // print op end time + printf("/op end time: %8.6f", localPtr->opEndTime); + // endline print + // fct: printf + printf("\n\n"); + // assign local pointer to next node + localPtr = localPtr->nextNode; + } + // void function, no return. +} + +/* +Name: getCommand +Process: parses thre letter command part of opcode str +Function Input/Parameters: input opcode str (const char *), + starting index (int) +Function Output/Parameters: parsed command (char *) +Function Output/Returned: updated starting index for use by calling fct (int) +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +int getCommand(char *cmd, const char *inputStr, int index) +{ + // initialize function and variables + int lengthOfCommand = 3; + // loop across command length + while(index < lengthOfCommand) + { + // assign character from input string to buffer string + cmd[index] = inputStr[index]; + // increment index + index = index + 1; + // set next character to null character + cmd[index] = NULL_CHAR; + } + // return current index + return index; +} + +/* +Name: getMetaData +Process: main driver function to upload, parse, and store list + of op code commands in a linked list +Function Input/Parameters: file name (const char *) +Function Output/Parameters: ptr to opcode linked list head ptr (OpCodeType **), + result msg of fct state after completion (char *) +Function Output/Returned: Boolean result of operation (bool) +Device Input/File: op code list uploaded +Device Output/Device: none +Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, + malloc, getOpCommand, updateStartCount, updateEndCount, + clearMetaDataList, free, addNode +*/ +bool getMetaData(const char *fileName, + OpCodeType **opCodeDataHead, char *endStateMsg) +{ + // initialize function and variables + // iniitialize read only constant + const char READ_ONLY_FLAG[] = "r"; + // initialize variables + int accessResult, startCount = 0, endCount = 0; + char dataBuffer[MAX_STR_LEN]; + bool returnState = true; + OpCodeType *newNodePtr; + OpCodeType *localHeadPtr = NULL; + FILE *fileAccessPtr; + // initialize opcode data pointer in case of return error + *opCodeDataHead = NULL; + // initialize end state message + // fct: copyString + copyString(endStateMsg, "Metadata file upload successful"); + // open file for reading + // fct: fopen + fileAccessPtr = fopen(fileName, READ_ONLY_FLAG); + // check for file open failure + if(fileAccessPtr == NULL) + { + // set end state message + // fct: copyString + copyString(endStateMsg, "Metadata file access error"); + // return file access error + return false; + } + // check first line for correct leader + // fct: getStringToDelimiter, compareString + if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer) || + compareString(dataBuffer, "Start Program Meta-Data Code") != 0) + { + // close file + // fct: fclose + fclose(fileAccessPtr); + // set end state message + // fct: copyString + copyString(endStateMsg, "Corrupt metadata leader line error"); + // return corrupt descriptor error + return false; + } + // allocate memory for the temporary data structure + // fct: malloc + newNodePtr = (OpCodeType *) malloc(sizeof(OpCodeType)); + // get the first op command + // fct: getOpCommand + accessResult = getOpCommand(fileAccessPtr, newNodePtr); + // get start and end counts for later comparison + // fct: updateStartCount, updateEndCount + startCount = updateStartCount(startCount, newNodePtr->strArg1); + endCount = updateEndCount(endCount, newNodePtr->strArg1); + // check for failure of first complete op command + if(accessResult != COMPLETE_OPCMD_FOUND_MSG) + { + // close file + // fct: fclose + fclose(fileAccessPtr); + // clear data from the structure list + // fct: clearMetaDataList + *opCodeDataHead = clearMetaDataList(localHeadPtr); + // free temporary structure memory + // fct: free + free(newNodePtr); + // set end state message + // fct: copyString + copyString(endStateMsg, "Metadata incomplete first op command found"); + // return result of operation + return false; + } + // loop across all remaining op commands + // (while complete op commands are found) + while(accessResult == COMPLETE_OPCMD_FOUND_MSG) + { + // add the new op command to the linked list + // fct: addNode + localHeadPtr = addNode(localHeadPtr, newNodePtr); + // get a new op command + // fct: getOpCommand + accessResult = getOpCommand(fileAccessPtr, newNodePtr); + // update start and end counts for later comparison + // fct: updateStartCount, updateEndCount + startCount = updateStartCount(startCount, newNodePtr->strArg1); + endCount = updateEndCount(endCount, newNodePtr->strArg1); + } + // end loop across all remaining op commands + // check for last op command found + if(accessResult == LAST_OPCMD_FOUND_MSG) + { + // check for start and end opcode counts equal + if(startCount == endCount) + { + // add the last node to the linked list + // fct: addNode + localHeadPtr = addNode(localHeadPtr, newNodePtr); + // set access result to no error for later operation + accessResult = NO_ACCESS_ERR; + // check last line for incorrect end descriptor + // fct: getStringToDelimiter, compareString + if(!getStringToDelimiter(fileAccessPtr, PERIOD, dataBuffer) || + compareString(dataBuffer, "End Program Meta-Data Code") != 0) + { + // set access result to corrupted descriptor error + accessResult = MD_CORRUPT_DESCRIPTOR_ERR; + // set end state message + // fct: copyString + copyString(endStateMsg, "Metadata corrupted descriptor error"); + } + } + // otherwise, assume start/end counts not equal + else + { + // close file + // fct: fclose + fclose(fileAccessPtr); + // clear data from the structure list + // fct: clearMetaDataList + *opCodeDataHead = clearMetaDataList(localHeadPtr); + // free temporary structure memory + // fct: free + free(newNodePtr); + // set access result to error + accessResult = UNBALANCED_START_END_ERR; + // set end state message + // fct: copyString + copyString(endStateMsg, + "Unbalanced start and end arguments in metadata"); + // return result of operation + return false; + } + } + // otherwise, assume didn't find end + else + { + // set end state message + // fct: copyString + copyString(endStateMsg, "Corrupted metadata opcode"); + // unset return state + returnState = false; + } + // check for any errors found (not no error) + if(accessResult != NO_ACCESS_ERR) + { + // clear the op command list + // fct: clearMetaDataList + localHeadPtr = clearMetaDataList(localHeadPtr); + } + // close access file + // fct: fclose + fclose(fileAccessPtr); + // release temporary structure memory + // fct: free + free(newNodePtr); + // assign temporary local head ptr to parameter return ptr + *opCodeDataHead = localHeadPtr; + // return access result + return returnState; +} + +/* +Name: getOpCommand +Process: acquires one op command line from a previously opened file, + parses it, and sets various struct members according to the + three letter command +Function Input/Parameters: ptr to open file handle (FILE *) +Function Output/Parameters: ptr to one opcode struct (OpCodeType *) +Function Output/Returned: coded result of operation (OpCodeMessages) +Device Input/File: opcode line uploaded +Device Output/Device: none +Dependencies: getStringToDelimiter, getCommand, copyString, verifyValidCommand, + compareString, getStringArg, verifyFirstStringArg, getNumberArg +*/ +OpCodeMessages getOpCommand(FILE *filePtr, OpCodeType *inData) +{ + // initialize function and variables + // initialize local constants + const int MAX_CMD_LENGTH = 5; + const int MAX_ARG_STR_LENGTH = 15; + // initialize other variables + int numBuffer = 0; + char strBuffer[STD_STR_LEN]; + char cmdBuffer[MAX_CMD_LENGTH]; + char argStrBuffer[MAX_ARG_STR_LENGTH]; + int runningStringIndex = 0; + bool arg2FailureFlag = false; + bool arg3FailureFlag = false; + // get whole op command as string, check for successful access + // fct: getStringToDelimiter + if(getStringToDelimiter(filePtr, SEMICOLON, strBuffer)) + { + // get three-letter command + // fct: getCommand + runningStringIndex = getCommand(cmdBuffer, + strBuffer, runningStringIndex); + // assign op command to node + // fct: copyString + copyString(inData->command, cmdBuffer); + } + // otherwise, assume unsuccessful access + else + { + // set ptr to data structure to null + inData = NULL; + // return op command access failure + return OPCMD_ACCESS_ERR; + } + // verify op command + if(!verifyValidCommand(cmdBuffer)) + { + // return op command error + return CORRUPT_OPCMD_ERR; + } + // set all struct values that may not be initialized to defaults + inData->pid = 0; + inData->inOutArg[0] = NULL_CHAR; + inData->intArg2 = 0; + inData->intArg3 = 0; + inData->opEndTime = 0.0; + inData->nextNode = NULL; + // check for device command + if(compareString(cmdBuffer, "dev") == 0) + { + // get in/out arg + runningStringIndex = getStringArg(argStrBuffer, + strBuffer, runningStringIndex); + // set device in/out arg + copyString(inData->inOutArg, argStrBuffer); + // check correct argument + if(compareString(argStrBuffer, "in") != 0 && + compareString(argStrBuffer, "out") != 0) + { + // return argument error + return CORRUPT_OPCMD_ARG_ERR; + } + } + // get first string arg + runningStringIndex = getStringArg(argStrBuffer, + strBuffer, runningStringIndex); + // set device in/out arg + copyString(inData->strArg1, argStrBuffer); + // check for legit first string arg + if(!verifyFirstStringArg(argStrBuffer)) + { + // return arg error + return CORRUPT_OPCMD_ARG_ERR; + } + // check for last op command found + if(compareString(inData->command, "sys") == 0 && + compareString(inData->strArg1, "end") == 0) + { + // return last op command found message + return LAST_OPCMD_FOUND_MSG; + } + // check for app start seconds argument + if(compareString(inData->command, "app") == 0 && + compareString(inData->strArg1, "start") == 0) + { + // get number argument + // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { + // set failure flag + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } + // check for cpu cycle time + else if(compareString(inData->command, "cpu") == 0) + { + // get number argument + // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { + // set failure flag + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } + // check for device cycle time + else if(compareString(inData->command, "dev") == 0) + { + // get number argument + // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { + // set failure flag + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } + // check for memory base and offset + else if(compareString(inData->command, "mem") == 0) + { + // get number argument + // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { + // set failure flag + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + // get number argument for offset + // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + if(numBuffer <= BAD_ARG_VAL) + { + // set failure flag + arg3FailureFlag = true; + } + // set second int argument to number + inData->intArg3 = numBuffer; + } + // check int args for upload failure + if(arg2FailureFlag || arg3FailureFlag) + { + // return corrupt op command found message + return CORRUPT_OPCMD_ARG_ERR; + } + // return complete op command found message + return COMPLETE_OPCMD_FOUND_MSG; +} + +/* +Name: getNumberArg +Process: starts at given index, captures + and assembles int arg, returns as parameter +Function Input/Parameters: input str (const char *), starting index (int) +Function Output/Parameters: pointer to captured integer value +Function Output/Returned: updated index for next function start +Device Input/Device: none +Device Output/Device: none +Dependencies: isDigit +*/ +int getNumberArg(int *number, const char *inputStr, int index) +{ + // initialize function and variables + bool foundDigit = false; + *number = 0; + int multiplier = 1; + // loop to skip whitespace + while(inputStr[index] <= SPACE || inputStr[index] == COMMA) + { + // increment the index + index = index + 1; + } + // loop across string length + while(isDigit(inputStr[index]) && + inputStr[index] != NULL_CHAR) + { + // set digit found flag + foundDigit = true; + // assign digit to output + (*number) = (*number) * multiplier + (inputStr[index] - '0'); + // increment index and multiplier + index = index + 1; + multiplier = 10; + } + // check for digit not found + if(!foundDigit) + { + // set number to BAD_ARG_VAL, use dereference for ptr + *number = BAD_ARG_VAL; + } + // return current index + return index; +} + +/* +Name: getStringArg +Process: starts at given index, captures + and assembles str arg, returns as parameter +Function Input/Parameters: input str (const char *), starting index (int) +Function Output/Parameters: ptr to captured string argument (char *) +Function Output/Returned: updated index for next fct start +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +int getStringArg(char *strArg, const char *inputStr, int index) +{ + // initialize function and variables + int localIndex = 0; + // loop to skip whitespace + while(inputStr[index] <= SPACE || inputStr[index] == COMMA) + { + // increment the index + index = index + 1; + } + // loop across string length + while(inputStr[index] != COMMA && inputStr[index] != NULL_CHAR) + { + // assign character from input string to buffer string + strArg[localIndex] = inputStr[index]; + // increment index + index = index + 1; + localIndex = localIndex + 1; + // set next character to null character + strArg[localIndex] = NULL_CHAR; + } + // return current index + return index; +} + +/* +Name: isDigit +Process: tests character parameter for digit, + returns true if is digit, false otherwise +Function Input/Parameters: test character (char) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +bool isDigit(char testChar) +{ + // check for test character between characters '0' - '9' + // return true + // otherwise, assume character if not digit, return false + return testChar >= '0' && testChar <= '9'; +} + +/* +Name: updateEndCount +Process: manages count of "end" arguments + to be compared at end of process input +Function Input/Parameters: initial count (int), + test string for "end" (const char *) +Function Output/Parameters: none +Function Output/Returned: updated count, if "end" string found, + otherwise no change +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +int updateEndCount(int count, const char *opString) +{ + // check for "end" in op string + // fct: compareString + if(compareString(opString, "end") == 0) + { + // return incremented end count + return count + 1; + } + // return unchanged end count + return count; +} + +/* +Name: updateStartCount +Process: manages count of "start" arguments + to be compared at start of process input +Function Input/Parameters: initial count (int), + test string for "start" (const char *) +Function Output/Parameters: none +Function Output/Returned: updated count, if "start" string found, + otherwise no change +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +int updateStartCount(int count, const char *opString) +{ + // check for "start" in op string + // fct: compareString + if (compareString(opString, "start") == 0) + { + // return incremented start count + return count + 1; + } + // return unchanged start count + return count; +} + +/* +Name: verifyFirstStringArg +Process: checks for all possibilities of first argument string of op command +Function Input/Parameters: test string (const char *) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool verifyFirstStringArg(const char *strArg) +{ + // check for string holding correct first argument + // fct: compareString + // return true + // otherwise, assume test fail, return false + return compareString(strArg, "access") == 0 || + compareString(strArg, "allocate") == 0 || + compareString(strArg, "end") == 0 || + compareString(strArg, "ethernet") == 0 || + compareString(strArg, "hard drive") == 0 || + compareString(strArg, "keyboard") == 0 || + compareString(strArg, "monitor") == 0 || + compareString(strArg, "printer") == 0 || + compareString(strArg, "process") == 0 || + compareString(strArg, "serial") == 0 || + compareString(strArg, "sound signal") == 0 || + compareString(strArg, "start") == 0 || + compareString(strArg, "usb") == 0 || + compareString(strArg, "video signal") == 0; +} + +/* +Name: verifyValidCommand +Process: checks for all possibilities of three-letter opcode command +Function Input/Parameters: test string for command (const char *) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool verifyValidCommand(char *testCmd) +{ + // check for string holding three-letter opcode command + // fct: compareString + // return true + // otherwise, assume test failure, return false + return compareString(testCmd, "sys") == 0 || + compareString(testCmd, "app") == 0 || + compareString(testCmd, "cpu") == 0 || + compareString(testCmd, "mem") == 0 || + compareString(testCmd, "dev") == 0; +} \ No newline at end of file diff --git a/Sim04/metadataops.h b/Sim04/metadataops.h new file mode 100644 index 0000000..162c36a --- /dev/null +++ b/Sim04/metadataops.h @@ -0,0 +1,207 @@ +#ifndef METADATAOPS +#define METADATAOPS + +#include "StandardConstants.h" +#include "StringUtils.h" + +typedef enum {BAD_ARG_VAL = -1, + NO_ACCESS_ERR, + MD_FILE_ACCESS_ERR, + MD_CORRUPT_DESCRIPTOR_ERR, + OPCMD_ACCESS_ERR, + CORRUPT_OPCMD_ERR, + CORRUPT_OPCMD_ARG_ERR, + UNBALANCED_START_END_ERR, + COMPLETE_OPCMD_FOUND_MSG, + LAST_OPCMD_FOUND_MSG + } OpCodeMessages; + +typedef struct OpCodeTypeStruct +{ + int pid; + char command[MAX_STR_LEN]; + char inOutArg[MAX_STR_LEN]; + char strArg1[MAX_STR_LEN]; + int intArg2; + int intArg3; + double opEndTime; + struct OpCodeTypeStruct *nextNode; +} OpCodeType; + +/* +Name: addNode +Process: adds metadata node to linked list recursively, handles empty list +Function Input/Parameters: ptr to head or next linked node (OpCodeType *), + ptr to new node (OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: pointer to previous node, or head node (OpCodeType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: malloc, copyString +*/ +OpCodeType *addNode(OpCodeType *localPtr, OpCodeType *newNode); + +/* +Name: clearMetaDataList +Process: recursively traverses list, frees dynamically allocated nodes +Function Input/Parameters: node opcode (const OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: NULL (OpCodeType *) +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +OpCodeType *clearMetaDataList(OpCodeType *localPtr); + +/* +Name: displayMetaData +Process: data dump/display of all opcode items +Function Input/Parameters: pointer to + head of opcode/metadata list (const OpCodeType *) +Function Output/Parameters: none +Function Output/Returned: calculated time (int) +Device Input/Device: none +Device Output/Device: none +Dependencies: printf, compareString +*/ +void displayMetaData(const OpCodeType *localPtr); + +/* +Name: getCommand +Process: parses thre letter command part of opcode str +Function Input/Parameters: input opcode str (const char *), + starting index (int) +Function Output/Parameters: parsed command (char *) +Function Output/Returned: updated starting index for use by calling fct (int) +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +int getCommand(char *cmd, const char *inputStr, int index); + +/* +Name: getMetaData +Process: main driver function to upload, parse, and store list + of op code commands in a linked list +Function Input/Parameters: file name (const char *) +Function Output/Parameters: ptr to opcode linked list head ptr (OpCodeType **), + result msg of fct state after completion (char *) +Function Output/Returned: Boolean result of operation (bool) +Device Input/File: op code list uploaded +Device Output/Device: none +Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, + malloc, getOpCommand, updateStartCount, updateEndCount, + clearMetaDataList, free, addNode +*/ +bool getMetaData(const char *fileName, + OpCodeType **opCodeDataHead, char *endStateMsg); + +/* +Name: getOpCommand +Process: acquires one op command line from a previously opened file, + parses it, and sets various struct members according to the + three letter command +Function Input/Parameters: ptr to open file handle (FILE *) +Function Output/Parameters: ptr to one opcode struct (OpCodeType *) +Function Output/Returned: coded result of operation (OpCodeMessages) +Device Input/File: opcode line uploaded +Device Output/Device: none +Dependencies: getStringToDelimiter, getCommand, copyString, verifyValidCommand, + compareString, getStringArg, verifyFirstStringArg, getNumberArg +*/ +OpCodeMessages getOpCommand(FILE *filePtr, OpCodeType *inData); + +/* +Name: getNumberArg +Process: starts at given index, captures + and assembles int arg, returns as parameter +Function Input/Parameters: input str (const char *), starting index (int) +Function Output/Parameters: pointer to captured integer value +Function Output/Returned: updated index for next function start +Device Input/Device: none +Device Output/Device: none +Dependencies: isDigit +*/ +int getNumberArg(int *number, const char *inputStr, int index); + +/* +Name: getStringArg +Process: starts at given index, captures + and assembles str arg, returns as parameter +Function Input/Parameters: input str (const char *), starting index (int) +Function Output/Parameters: ptr to captured string argument (char *) +Function Output/Returned: updated index for next fct start +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +int getStringArg(char *strArg, const char *inputStr, int index); + +/* +Name: isDigit +Process: tests character parameter for digit, + returns true if is digit, false otherwise +Function Input/Parameters: test character (char) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +bool isDigit(char testChar); + +/* +Name: updateEndCount +Process: manages count of "end" arguments + to be compared at end of process input +Function Input/Parameters: initial count (int), + test string for "end" (const char *) +Function Output/Parameters: none +Function Output/Returned: updated count, if "end" string found, + otherwise no change +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +int updateEndCount(int count, const char *opString); + +/* +Name: updateStartCount +Process: manages count of "start" arguments + to be compared at start of process input +Function Input/Parameters: initial count (int), + test string for "start" (const char *) +Function Output/Parameters: none +Function Output/Returned: updated count, if "start" string found, + otherwise no change +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +int updateStartCount(int count, const char *opString); + +/* +Name: verifyFirstStringArg +Process: checks for all possibilities of first argument string of op command +Function Input/Parameters: test string (const char *) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool verifyFirstStringArg(const char *strArg); + +/* +Name: verifyValidCommand +Process: checks for all possibilities of three-letter opcode command +Function Input/Parameters: test string for command (const char *) +Function Output/Parameters: none +Function Output/Returned: bool result of test (bool) +Device Input/Device: none +Device Output/Device: none +Dependencies: compareString +*/ +bool verifyValidCommand(char *testCmd); + +#endif // METADATAOPS \ No newline at end of file diff --git a/Sim04/sim03 b/Sim04/sim03 new file mode 100755 index 0000000000000000000000000000000000000000..8d57268ffd620d83d43bbb2b19f7340172bd0c87 GIT binary patch literal 68832 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 0 ) + { + timeStr[ index ] = (char) ( uSecTime % 10 + '0' ); + uSecTime /= 10; + + index++; + + } + + while( index < 6 ) + { + timeStr[ index ] = '0'; + + index++; + } + + timeStr[ index ] = RADIX_POINT; + + index++; + + if( secTime < 10 ) // single digit in display + { + timeStr[ index ] = (char) ( secTime % 10 + '0' ); + + index++; + + timeStr[ index ] = SPACE; + + index++; + + secTime = 0; + } +/* + if( secTime == 0 ) + { + timeStr[ index ] = '0'; + + index++; + } +*/ + while( secTime > 0 ) + { + timeStr[ index ] = (char) ( secTime % 10 + '0' ); + + secTime /= 10; + + index++; + } + + timeStr[ index ] = NULL_CHAR; + + low = 0; high = index - 1; + + while( low < high ) + { + temp = timeStr[ low ]; + timeStr[ low ] = timeStr[ high ]; + timeStr[ high ] = temp; + + low++; high--; + } + } + +#endif // ifndef SIMTIMER_C + + + + + diff --git a/Sim04/simtimer.h b/Sim04/simtimer.h new file mode 100644 index 0000000..f57ae94 --- /dev/null +++ b/Sim04/simtimer.h @@ -0,0 +1,49 @@ +// Program Information //////////////////////////////////////////////////////// +/** + * @file SimpleTimer.h + * + * @brief Header file for micro-second precision timer + * + * @author Michael Leverington + * + * @details Specifies all member methods of the SimpleTimer + * + * @version 2.00 (13 January 2017) + * 1.00 (11 September 2015) + * + * @Note None + */ + +// Precompiler directives ///////////////////////////////////////////////////// + +#ifndef SIMTIMER_H +#define SIMTIMER_H + +// Header files /////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "OS_SimDriver.h" + +// Global Constants ////////////////////////////////////////////////////////// + +enum TIMER_CTRL_CODES { ZERO_TIMER, LAP_TIMER, STOP_TIMER }; + +extern const char RADIX_POINT; +extern const char SPACED; + +// Function Prototyp ///////////////////////////////////////////////////////// + +void *runTimer(void *mSecVoidPtr); +// will run a timer for the amount of ms specified +double accessTimer( int controlCode, char *timeStr ); +// returns the actual time as a double AND as a time string + +// no more access needed beyond this point (supporting functions) +double processTime( double startSec, double endSec, + double startUSec, double endUSec, char *timeStr ); +void timeToString( int secTime, int uSecTime, char *timeStr ); + +#endif // ifndef SIMTIMER_H + diff --git a/Sim04/simulator.c b/Sim04/simulator.c new file mode 100644 index 0000000..db2ba8f --- /dev/null +++ b/Sim04/simulator.c @@ -0,0 +1,1021 @@ +#include "simulator.h" + +/* +Name: accessMemory +Process: checks that the memory is between the offset and the size. + checks that the memory is ??? +Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int) +Function Output/Parameters: none +Function Output/Returned: boolean to indicate success or failure of accessed memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool accessMemory(ProcessControlBlock *singlePCB, int offset, int size) +{ + // return true (temp) + return true; +} + +/* +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: boolean to indicate success or failure of allocated memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int arraySize) +{ + int allocateIterator = 0; + // while until a '-1' is hit, then store the value. + while(singlePCB->allocatedMemSizes[allocateIterator] != -1 && allocateIterator < arraySize) + { + // + singlePCB->allocatedMemOffsets[allocateIterator] = offset; + singlePCB->allocatedMemSizes[allocateIterator] = size; + allocateIterator = allocateIterator + 1; + printf("Alloc Iter: %d\n", allocateIterator); + } + // return true (temp) + return true; +} + +/* +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 every offset and size within it's PCB +Function Input/Parameters: source PCB (ProcessControlBlock *) +Function Output/Parameters: none +Function Output/Returned: boolean to indicate success or failure of allocated memory +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool deallocMemory(ProcessControlBlock *singlePCB, int arraySize) +{ + int deallocateIterator; + // while until a '-1' is hit, then store the value. + for (deallocateIterator = 0; deallocateIterator < arraySize; deallocateIterator++) + { + // + singlePCB->allocatedMemOffsets[deallocateIterator] = -1; + singlePCB->allocatedMemSizes[deallocateIterator] = -1; + } + // return true (temp) + return true; +} + +/* +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: boolean for success or failure of memory management +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) +{ + bool memDisplay = configPtr->memDisplay; + ProcessControlBlock *wkgPtr; + int availableMem = configPtr->memAvailable; + int usedMem = 0; + int currentOffset = 0; + int currentSize = 0; + int memIterator; + int *memorySizeArray; + int totalArraySize = 0; + bool subFunctionSuccess = true; + wkgPtr = pcbList->headPtr; + + // grab how much memory is being used total, then count how big the total memory array should be + while(wkgPtr != NULL) + { + // count up the total used memory within each process control block. + for(memIterator = 0; memIterator < wkgPtr->memArraySize; memIterator++) + { + if(wkgPtr->allocatedMemSizes[memIterator] != -1) + { + // grab how much memory is used by that process + usedMem = usedMem + wkgPtr->allocatedMemSizes[memIterator]; + } + totalArraySize = totalArraySize + 1; + } + // move to the next pointer + wkgPtr = wkgPtr->nextPtr; + } + + // reset the working pointer + wkgPtr = pcbList->headPtr; + + // declare the array for the memory + memorySizeArray = malloc(sizeof(int) * totalArraySize); + + // grab the entire memory structure, so that the memory can be contiguous + while (wkgPtr != NULL) + { + // count up the total used memory within each process control block. + for (memIterator = 0; memIterator < totalArraySize; memIterator++) + { + // grab how much memory is used by that process + memorySizeArray[memIterator] = wkgPtr->allocatedMemSizes[memIterator]; + } + // move to the next pointer + wkgPtr = wkgPtr->nextPtr; + } + + // grab the size of the + // while() + // { + // // + // } + + // switch case for each memory code + switch (memCode) + { + case MEMORY_INITIALIZE: + for(memIterator = 0; memIterator < singlePCB->memArraySize; memIterator++) + { + // initialize the arrays with all '-1' to 'nullify' the memory, make it easier to iterate through later + singlePCB->allocatedMemOffsets[memIterator] = -1; + singlePCB->allocatedMemSizes[memIterator] = -1; + } + 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: + // check if the memory allocation can happen before storing it. + if(size <= availableMem - usedMem + 1) + { + // grab the offset and size, store it, using the allocate memory function. + subFunctionSuccess = allocMemory(singlePCB, offset, size, singlePCB->memArraySize); + usedMem = usedMem + size; + } + else + { + // set the subfunction success to false. + subFunctionSuccess = false; + } + // if the function returns true, then it successfully did the operation, display as such. + if (memDisplay) + { + if(subFunctionSuccess) + { + // + printf("--------------------------------------------------\n"); + printf("After memory allocation\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // + printf("--------------------------------------------------\n"); + printf("After memory allocation failure\n"); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + } + break; + + case MEMORY_ACCESS: + // printf("Used memory at current: %d\n", usedMem); + subFunctionSuccess = accessMemory(singlePCB, offset, size); + if (memDisplay) + { + if (subFunctionSuccess) + { + // + printf("--------------------------------------------------\n"); + printf("After access success\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // + printf("--------------------------------------------------\n"); + printf("After access failure\n"); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + } + break; + + case MEMORY_DEALLOCATE: + subFunctionSuccess = deallocMemory(singlePCB, singlePCB->memArraySize); + if (memDisplay) + { + if (subFunctionSuccess) + { + // THIS SHOULD ALWAYS HAPPEN. + printf("--------------------------------------------------\n"); + printf("After clear process %d success\n", singlePCB->uniquePid); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem - usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + else + { + // THIS SHOULD NEVER HAPPEN. + printf("--------------------------------------------------\n"); + printf("After clear process %d failure\n", singlePCB->uniquePid); + printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem - usedMem, currentOffset, currentSize, availableMem - 1); + printf("--------------------------------------------------\n"); + } + } + break; + + case MEMORY_CLEAR: + if (memDisplay) + { + // this will happen regardless. Will always be cleaning up memory with dealloc. + printf("--------------------------------------------------\n"); + printf("After memory clear\n"); + printf("No memory configured\n"); + printf("--------------------------------------------------\n"); + } + break; + + default: + break; + } + // clear out the dynamic array + free(memorySizeArray); + // return if the subfunction succeeded, if applicable + return subFunctionSuccess; +} + +/* +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; + int *cpuTimePtr = &cpuTime; + 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, runTimer, (void *)cpuTimePtr); + 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; + int *ioTimePtr = &ioTime; + 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, runTimer, (void *)ioTimePtr); + 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]; + char processOutput[HUGE_STR_LEN]; + // grab the next operation code for the + OpCodeType *workingMeta = singlePCB->nextOpCode; + char *command; + char *argument; + int intArg; + int intArgTwo; + bool memManagerSuccess = true; + // char *inOutArg; + command = workingMeta->command; + argument = workingMeta->strArg1; + intArg = workingMeta->intArg2; + intArgTwo = workingMeta->intArg3; + // inOutArg = workingMeta->inOutArg; + while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV) && memManagerSuccess) + { + // 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); + } + if(compareString(command, "mem") == EQUIV) + { + // run memory operations with the memory manager + if(compareString(argument, "allocate") == EQUIV) + { + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + // run the memory manager in allocate mode + memManagerSuccess = memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); + if(!memManagerSuccess) + { + // + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + } + } + else if(compareString(argument, "access") == EQUIV) + { + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + // run the memory manager in access mode + memManagerSuccess = memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); + if (!memManagerSuccess) + { + // + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + logOutput(configPtr, processOutput, false); + } + } + } + workingMeta = workingMeta->nextNode; + command = workingMeta->command; + argument = workingMeta->strArg1; + intArg = workingMeta->intArg2; + intArgTwo = workingMeta->intArg3; + } + // display the process exited, if not segfaulted. + if(memManagerSuccess) + { + // + sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + logOutput(configPtr, processOutput, false); + } + else + { + // + sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + logOutput(configPtr, processOutput, false); + } + // deallocate the memory for the process + memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB); +} + +/* +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; + int *totalPCBTimePtr = &totalPCBTime; + + + pthread_t cpuThread; + pthread_create(&cpuThread, NULL, runTimer, (void *)totalPCBTimePtr); + + // + int processTimeLeft = pcbPtr->timeLeft; + int *processTimeLeftPtr = &processTimeLeft; + + // 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, pcbList->headPtr); + + // 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, runTimer, (void *)processTimeLeftPtr); + 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; + processTimeLeftPtr = &processTimeLeft; + pcbPtr = pcbPtr->nextPtr; + } + currentPid = scheduleProcess(pcbList, configPtr); + pcbPtr = pcbList->headPtr; + } + pthread_join(cpuThread, NULL); + // deallocate all the memory for each process. + memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr); + 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; + + int shortestJob = 0; + int shortestJobProcNum = 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. + + 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); +// } \ No newline at end of file diff --git a/Sim04/simulator.h b/Sim04/simulator.h new file mode 100644 index 0000000..9e9e59f --- /dev/null +++ b/Sim04/simulator.h @@ -0,0 +1,234 @@ +#ifndef SIMULATORX +#define SIMULATORX + +#include "StandardConstants.h" +#include "configops.h" +#include "metadataops.h" +#include "simtimer.h" +#include + +// data structures + +typedef enum{ + PROCESS_STATE_NEW = 0, + PROCESS_STATE_READY, + PROCESS_STATE_RUNNING, + PROCESS_STATE_BLOCKED, + PROCESS_STATE_TERMINATED + } PROCESS_STATES; + +typedef enum{ + MEMORY_INITIALIZE = 0, + MEMORY_ACCESS, + MEMORY_ALLOCATE, + MEMORY_CLEAR, + MEMORY_DEALLOCATE + } MEMORY_SIGNALS; + +typedef struct ProcessControlBlockStruct +{ + int uniquePid; + PROCESS_STATES process_state; + // need a process start ptr for where the process starts. + // this will be a mini loop within the master loop that goes until it + // hits the app end command. + // it may hold the next opcode, since you don't need to traverse backward + OpCodeType *nextOpCode; + // have an IO cycle count here + int ioCycles; + // have a CPU cycle count here + int cpuCycles; + // maybe have a total cycle count here + int totalCycles; + // time left could be calculated from these. + // potentially could change the cycles or have a 'left' variable to + // see how many are left. + // also need a time left state here? + double timeLeft; + // allocated memory array (stores the offsets) + int *allocatedMemOffsets; + // allocated memory array sizes (stores the sizes for each offset) + int *allocatedMemSizes; + // size of memory array + int memArraySize; + // connect to the next process control block here + struct ProcessControlBlockStruct *nextPtr; +} ProcessControlBlock; + +typedef struct ProcessControlBlockLLStruct +{ + // holds the head ptr for PCBs + ProcessControlBlock *headPtr; +} ProcessControlBlockLL; + +/* +Name: ??? +Process: ??? +Function Input/Parameters: ??? +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ + +/* +Name: ??? +Process: ??? +Function Input/Parameters: ??? +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ + +/* +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); + +/* +Name: createProcessList +Process: initializes head pointer to the 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(); + +/* +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); + +/* +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); + +/* +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); + +/* +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); + +/* +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: sprintf, ??? +*/ +void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd); + +/* +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: ??? +*/ +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); + +/* +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: ??? +*/ +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +/* +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: ??? +*/ +void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr); + +/* +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 *) +Function Output/Parameters: none +Function Output/Returned: none +Device Input/Device: none +Device Output/Device: none +Dependencies: ??? +*/ +int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr); + +/* +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: ??? +*/ +// void *simThread(int milSec); + +#endif // SIMULATORX \ No newline at end of file diff --git a/Sim04/testfile-dnw.mdf b/Sim04/testfile-dnw.mdf new file mode 100644 index 0000000..6fdd099 --- /dev/null +++ b/Sim04/testfile-dnw.mdf @@ -0,0 +1,86 @@ +Start Program Meta-Data Code: + +# starting the master loop +sys start + +# process 0 start +app start, 0 +# process 0 I/O (run HDD for 18 cycles) +dev in, hard drive, 18 +# process 0 CPU (run CPU for 9 cycles 3 times) +cpu process, 9 +cpu process, 9 +cpu process, 9 +# process 0 I/O (run monitor for 60 cycles) +dev out, monitor, 60 +# process 0 end +app end + +# P0 total cycles ran: 105 + +# process 1 start +app start, 0 +# process 1 I/O (run sound for 40 cycles, HDD for 30 cycles, sound for 25 cycles) +dev in, sound signal, 40 +dev in, hard drive, 30 +dev in, sound signal, 25 +# process 1 CPU (run CPU for 6 cycles) +cpu process, 6 +# process 1 I/O (run USB for 10 cycles) +dev out, usb, 10 +# process 1 end +app end + +# P1 total cycles ran: 111 + +# process 2 start +app start, 0 +# process 2 I/O (run video for 70 cycles) +dev in, video signal, 70 +# process 2 CPU (run CPU for 10 cycles) +cpu process, 10 +# process 2 I/O (run monitor for 70 cycles, HDD for 18 cycles) +dev out, monitor, 70 +dev in, hard drive, 18 +# process 2 CPU (run CPU for 9 cycles) +cpu process, 9 +# process 2 end +app end + +# P2 total cycles ran: 177 + +# process 3 start +app start, 0 +# process 3 I/O (run sound for 35 cycles, monitor for 100 cycles, keyboard for 50 cycles) +dev in, sound signal, 35 +dev out, monitor, 100 +dev in, keyboard, 50 +# process 3 CPU (run CPU for 9 cycles) +cpu process, 9 +# process 3 I/O (run video for 49 cycles) +dev out, video signal, 49 +# process 3 end +app end + +# P3 total cycles ran: 243 + +# process 4 start +app start, 0 +# process 4 I/O (run keyboard for 90 cycles, sound for 40 cycles, serial for 32 cycles) +dev in, keyboard, 90 +dev out, sound signal, 40 +dev out, serial, 32 +# process 4 CPU (run CPU for 10 cycles) +cpu process, 10 +# process 4 I/O (run HDD for 15 cycles) +dev in, hard drive, 15 +# process 4 end +app end + +# P4 total cycles ran: 187 + +# master loop ends +sys end + +End Program Meta-Data Code. + diff --git a/Sim04/testfile.cnf b/Sim04/testfile.cnf new file mode 100644 index 0000000..77c71ed --- /dev/null +++ b/Sim04/testfile.cnf @@ -0,0 +1,12 @@ +Start Simulator Configuration File: +Version/Phase : 1.00 +File Path : testfile.mdf +CPU Scheduling Code : FCFS-N +Quantum Time (cycles) : 55 +Memory Available (KB) : 12000 +Memory Display (On/Off) : On +Processor Cycle Time (msec) : 10 +I/O Cycle Time (msec) : 20 +Log To : Monitor +Log File Path : logfile_1.lgf +End Simulator Configuration File. \ No newline at end of file diff --git a/Sim04/testfile.mdf b/Sim04/testfile.mdf new file mode 100644 index 0000000..b8da714 --- /dev/null +++ b/Sim04/testfile.mdf @@ -0,0 +1,40 @@ +Start Program Meta-Data Code: +sys start +app start, 0 +dev in, hard drive, 18 +cpu process, 9 +cpu process, 9 +cpu process, 9 +dev out, monitor, 60 +app end +app start, 0 +dev in, sound signal, 40 +dev in, hard drive, 30 +dev in, sound signal, 25 +cpu process, 6 +dev out, usb, 10 +app end +app start, 0 +dev in, video signal, 70 +cpu process, 10 +dev out, monitor, 70 +dev in, hard drive, 18 +cpu process, 9 +app end +app start, 0 +dev in, sound signal, 35 +dev out, monitor, 100 +dev in, keyboard, 50 +cpu process, 9 +dev out, video signal, 49 +app end +app start, 0 +dev in, keyboard, 90 +dev out, sound signal, 40 +dev out, serial, 32 +cpu process, 10 +dev in, hard drive, 15 +app end +sys end +End Program Meta-Data Code. + From fda21f3cb6d41e948e6824d2c3edc798bde67823 Mon Sep 17 00:00:00 2001 From: cdez Date: Mon, 15 Apr 2024 21:00:29 -0700 Subject: [PATCH 10/11] Attempting working on Sim04 without the LL stuff trying to fix in 03. --- Sim03/logfile_1.lgf | 2 +- Sim03/sim03 | Bin 73896 -> 73880 bytes Sim04/logfile_1.lgf | 7 ++ Sim04/sim03 | Bin 68832 -> 0 bytes Sim04/sim04 | Bin 0 -> 68984 bytes Sim04/{sim03_mf => sim04_mf} | 4 +- Sim04/simulator.c | 123 +++++++++++++++++++++++------------ Sim04/simulator.h | 12 ---- 8 files changed, 91 insertions(+), 57 deletions(-) delete mode 100755 Sim04/sim03 create mode 100755 Sim04/sim04 rename Sim04/{sim03_mf => sim04_mf} (90%) diff --git a/Sim03/logfile_1.lgf b/Sim03/logfile_1.lgf index fea283a..c3d5bca 100644 --- a/Sim03/logfile_1.lgf +++ b/Sim03/logfile_1.lgf @@ -1 +1 @@ -0.000001, OS: Simulator start +0.000988, OS: Simulator start diff --git a/Sim03/sim03 b/Sim03/sim03 index 9e0361fd5bba974d25da940b6bc90bd959a3dbc8..5bbd9049a29bc5e4854e9ad888443375342d6469 100755 GIT binary patch delta 6726 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 diff --git a/Sim04/logfile_1.lgf b/Sim04/logfile_1.lgf index e69de29..52b0e91 100644 --- a/Sim04/logfile_1.lgf +++ b/Sim04/logfile_1.lgf @@ -0,0 +1,7 @@ +0.000000, OS: Simulator start + READY state from NEW state +ate + +ate + + diff --git a/Sim04/sim03 b/Sim04/sim03 deleted file mode 100755 index 8d57268ffd620d83d43bbb2b19f7340172bd0c87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68832 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 GI{ypvq7hC2 literal 0 HcmV?d00001 diff --git a/Sim04/sim03_mf b/Sim04/sim04_mf similarity index 90% rename from Sim04/sim03_mf rename to Sim04/sim04_mf index d6d51fb..ce4d173 100644 --- a/Sim04/sim03_mf +++ b/Sim04/sim04_mf @@ -5,7 +5,7 @@ OBJECTS = OS_SimDriver.o simulator.o metadataops.o configops.o StringUtils.o sim all: Simulator Simulator: $(OBJECTS) - $(CC) $(OBJECTS) -o sim03 + $(CC) $(OBJECTS) -lpthread -o sim04 StringUtils.o: StringUtils.c $(CC) -c StringUtils.c -o StringUtils.o @@ -26,7 +26,7 @@ simtimer.o: simtimer.c $(CC) -c simtimer.c -o simtimer.o clean: - rm -f $(OBJECTS) sim03 sim03.out + rm -f $(OBJECTS) sim04 sim04.out clean_objects: rm -f $(OBJECTS) diff --git a/Sim04/simulator.c b/Sim04/simulator.c index db2ba8f..ba5a2d8 100644 --- a/Sim04/simulator.c +++ b/Sim04/simulator.c @@ -71,7 +71,7 @@ bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int array singlePCB->allocatedMemOffsets[allocateIterator] = offset; singlePCB->allocatedMemSizes[allocateIterator] = size; allocateIterator = allocateIterator + 1; - printf("Alloc Iter: %d\n", allocateIterator); + // printf("Alloc Iter: %d\n", allocateIterator); } // return true (temp) return true; @@ -331,6 +331,21 @@ int findMin(int one, int another) return minimumVal; } +/* +Name: interruptManager +Process: does the managing of interrupts for the program +Function Input/Parameters: ??? +Function Output/Parameters: none +Function Output/Returned: ??? +Device Input/Device: none +Device Output/Device: none +Dependencies: none +*/ +void interruptManager() +{ + // +} + /* Name: logOutput Process: Takes in a string, and then outputs it to monitor AND/OR file @@ -400,7 +415,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, ProcessControlBlock *singlePCB) +bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offset, int size, ConfigDataType *configPtr, + ProcessControlBlock *singlePCB) { bool memDisplay = configPtr->memDisplay; ProcessControlBlock *wkgPtr; @@ -497,7 +513,8 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // printf("--------------------------------------------------\n"); printf("After memory allocation\n"); - printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, + offset + size - 1, size - 1); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } @@ -522,7 +539,8 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // printf("--------------------------------------------------\n"); printf("After access success\n"); - printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, + offset + size - 1, size - 1); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } @@ -531,7 +549,8 @@ bool memManager(ProcessControlBlockLL *pcbList, MEMORY_SIGNALS memCode, int offs // printf("--------------------------------------------------\n"); printf("After access failure\n"); - printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, offset + size - 1, size - 1); + printf("%d [ Used, P#: %d, %d-%d ] %d\n", offset - offset, singlePCB->uniquePid, offset, + offset + size - 1, size - 1); printf("%d [ Open, P#: x, %d-%d ] %d\n", usedMem, currentOffset, currentSize, availableMem - 1); printf("--------------------------------------------------\n"); } @@ -593,6 +612,7 @@ Dependencies: pthreads, sprintf, logOutput, ??? */ void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) { + double timeDigits; char timeStringy[MAX_STR_LEN]; // char *command = workingMeta->command; // char *argument = workingMeta->strArg1; @@ -601,13 +621,15 @@ void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr int cpuTime = 0; int *cpuTimePtr = &cpuTime; cpuTime = intArg * configPtr->procCycleRate; - sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); logOutput(configPtr, cpuOutput, false); // run timer for intArg * procCycleRate pthread_t cpuThread; pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); pthread_join(cpuThread, NULL); - sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); logOutput(configPtr, cpuOutput, false); // pthread_exit(NULL); } @@ -624,17 +646,20 @@ Dependencies: pthreads, sprintf, logOutput, ??? */ void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) { + double timeDigits; char timeStringy[MAX_STR_LEN]; char ioOutput[MAX_STR_LEN]; int ioTime = 0; int *ioTimePtr = &ioTime; ioTime = intArg * configPtr->ioCycleRate; - sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); logOutput(configPtr, ioOutput, false); pthread_t ioThread; pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); pthread_join(ioThread, NULL); - sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); logOutput(configPtr, ioOutput, false); } @@ -650,6 +675,7 @@ Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList) { + double timeDigits; // 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]; @@ -667,7 +693,9 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce intArg = workingMeta->intArg2; intArgTwo = workingMeta->intArg3; // inOutArg = workingMeta->inOutArg; - while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV) && memManagerSuccess) + while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && + !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV) && + memManagerSuccess) { // check to see what operation will be performed if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV) @@ -685,27 +713,35 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce // run memory operations with the memory manager if(compareString(argument, "allocate") == EQUIV) { - sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", timeDigits, + singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); // run the memory manager in allocate mode memManagerSuccess = memManager(pcbList, MEMORY_ALLOCATE, intArg, intArgTwo, configPtr, singlePCB); if(!memManagerSuccess) { // - sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", timeDigits, + singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); } } else if(compareString(argument, "access") == EQUIV) { - sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "%f, Process: %d, %s %s request (%d, %d)\n", timeDigits, + singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); // run the memory manager in access mode memManagerSuccess = memManager(pcbList, MEMORY_ACCESS, intArg, intArgTwo, configPtr, singlePCB); if (!memManagerSuccess) { // - sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid, command, argument, intArg, intArgTwo); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "%f, Process: %d, failed %s %s request (%d, %d)\n", timeDigits, + singlePCB->uniquePid, command, argument, intArg, intArgTwo); logOutput(configPtr, processOutput, false); } } @@ -720,13 +756,15 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce if(memManagerSuccess) { // - sprintf(processOutput, "\n%f, OS: Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "\n%f, OS: Process %d ended\n", timeDigits, singlePCB->uniquePid); logOutput(configPtr, processOutput, false); } else { // - sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", timeDigits, singlePCB->uniquePid); logOutput(configPtr, processOutput, false); } // deallocate the memory for the process @@ -757,6 +795,7 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // char *nextCode; // string variable for the timer stuff char simulatorOutput[MAX_STR_LEN]; + double timeDigits; char timeStringy[MAX_STR_LEN]; int processCount = 0; int processIterator; @@ -765,7 +804,8 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) accessTimer(ZERO_TIMER, timeStringy); // Operating System start timer goes here, log it. - sprintf(simulatorOutput, "%f, OS: Simulator start\n", accessTimer(LAP_TIMER, timeStringy)); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Simulator start\n", timeDigits); logOutput(configPtr, simulatorOutput, false); // int variable for process to run int currentPid; @@ -812,13 +852,17 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) { // 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Process %d set to RUNNING state from READY state\n\n", timeDigits, + pcbPtr->uniquePid); logOutput(configPtr, simulatorOutput, false); pthread_t runThread; pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr); 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", timeDigits, + pcbPtr->uniquePid); logOutput(configPtr, simulatorOutput, false); pcbPtr->process_state = PROCESS_STATE_TERMINATED; pthread_join(runThread, NULL); @@ -833,9 +877,11 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) pthread_join(cpuThread, NULL); // deallocate all the memory for each process. memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr); - sprintf(simulatorOutput, "%f, OS: System Stop\n", accessTimer(LAP_TIMER, timeStringy)); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: System Stop\n", timeDigits); logOutput(configPtr, simulatorOutput, false); - sprintf(simulatorOutput, "%f, OS: Simulation End\n", accessTimer(LAP_TIMER, timeStringy)); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Simulation End\n", timeDigits); logOutput(configPtr, simulatorOutput, true); // deallocate the process list with destroyProcessList destroyProcessList(pcbList); @@ -858,6 +904,7 @@ Dependencies: sprintf, logOutput, ??? */ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr) { + double timeDigits; ProcessControlBlock *wkgPtr; int returnPid = -1; wkgPtr = headPointer->headPtr; @@ -897,7 +944,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt // 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + wkgPtr->uniquePid); logOutput(configPtr, loggingStr, false); } // move to the next pointer @@ -912,7 +961,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + wkgPtr->uniquePid, wkgPtr->timeLeft); logOutput(configPtr, loggingStr, false); returnPid = wkgPtr->uniquePid; } @@ -940,7 +991,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt // 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + wkgPtr->uniquePid); logOutput(configPtr, loggingStr, false); } // move to the next pointer @@ -991,7 +1044,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + shortestJobProcNum, (double)shortestJob); logOutput(configPtr, loggingStr, false); } returnPid = shortestJobProcNum; @@ -1002,20 +1057,4 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt } // 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); -// } \ No newline at end of file +} \ No newline at end of file diff --git a/Sim04/simulator.h b/Sim04/simulator.h index 9e9e59f..f55b9de 100644 --- a/Sim04/simulator.h +++ b/Sim04/simulator.h @@ -219,16 +219,4 @@ Dependencies: ??? */ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr); -/* -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: ??? -*/ -// void *simThread(int milSec); - #endif // SIMULATORX \ No newline at end of file From 722df73955c1c821c7946a471f0f13453a384fdf Mon Sep 17 00:00:00 2001 From: cdez Date: Thu, 18 Apr 2024 22:05:38 -0700 Subject: [PATCH 11/11] Finally gotten to the point with NO MORE WARNINGS!!! YAY --- Sim04/logfile_1.lgf | 7 - Sim04/sim04 | Bin 68984 -> 73944 bytes Sim04/simulator.c | 307 ++++++++++++++++++++++++++++++++++++++------ Sim04/simulator.h | 16 ++- 4 files changed, 283 insertions(+), 47 deletions(-) diff --git a/Sim04/logfile_1.lgf b/Sim04/logfile_1.lgf index 52b0e91..e69de29 100644 --- a/Sim04/logfile_1.lgf +++ b/Sim04/logfile_1.lgf @@ -1,7 +0,0 @@ -0.000000, OS: Simulator start - READY state from NEW state -ate - -ate - - diff --git a/Sim04/sim04 b/Sim04/sim04 index 0b1c3b8a2ddbdd807cd63b47a05023f108f4fba5..52d566410c0ce6b0efe5cc02c0b61ae27c4f8967 100755 GIT binary patch delta 24835 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 NxUN%cH=ES>{{!b2`BeY_ delta 23143 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 YiweBQdmF%@*SVU_*E8>hc$W6R0J5S!^#A|> diff --git a/Sim04/simulator.c b/Sim04/simulator.c index ba5a2d8..4867aca 100644 --- a/Sim04/simulator.c +++ b/Sim04/simulator.c @@ -341,9 +341,35 @@ Device Input/Device: none Device Output/Device: none Dependencies: none */ -void interruptManager() +bool interruptManager(ConfigDataType *configPtr, ProcessControlBlock *singlePCB, INTERRUPT_ROUTINE interruptRequest) { + // need to check which interrupt service routine that is selected from the list + switch (interruptRequest) + { + case IO_RETURN: + // unset the PCB's state from blocked to ready. + singlePCB->process_state = PROCESS_STATE_READY; + return true; + break; + case QUANTUM_TIMEOUT: + // set something? + // this may need to stop the current process from running, and force a new one... not sure. + return true; + break; + case CPU_SWITCH: + // needs to switch to the next process, schedule to the next process? + return true; + break; + // case FOUR: + // /* code */ + // break; + case CLEAR_INTERRUPT: + // COMMENT HERE + return false; + break; + } // + return false; } /* @@ -610,28 +636,52 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod) { double timeDigits; char timeStringy[MAX_STR_LEN]; // char *command = workingMeta->command; // char *argument = workingMeta->strArg1; // int intArg = workingMeta->intArg2; - char cpuOutput[MAX_STR_LEN]; + char cpuOutput[MAX_STR_LEN * 4]; int cpuTime = 0; int *cpuTimePtr = &cpuTime; - cpuTime = intArg * configPtr->procCycleRate; - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); - logOutput(configPtr, cpuOutput, false); - // run timer for intArg * procCycleRate pthread_t cpuThread; - pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); - pthread_join(cpuThread, NULL); - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); - logOutput(configPtr, cpuOutput, false); - // pthread_exit(NULL); + + switch (schedMethod) + { + case NON_PREEMPTIVE_CODE: + cpuTime = intArg * configPtr->procCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // run timer for intArg * procCycleRate + pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); + pthread_join(cpuThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // pthread_exit(NULL); + break; + + case PREEMPTIVE_CODE: + cpuTime = intArg * configPtr->procCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // run timer for intArg * procCycleRate + pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); + pthread_join(cpuThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + break; + + default: + // this should never happen... if it does, you'll know. + break; + } } /* @@ -644,23 +694,51 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod) { double timeDigits; char timeStringy[MAX_STR_LEN]; - char ioOutput[MAX_STR_LEN]; + char ioOutput[MAX_STR_LEN * 4]; int ioTime = 0; int *ioTimePtr = &ioTime; - ioTime = intArg * configPtr->ioCycleRate; - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); - logOutput(configPtr, ioOutput, false); pthread_t ioThread; - pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); - pthread_join(ioThread, NULL); - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); - logOutput(configPtr, ioOutput, false); + + switch (schedMethod) + { + case NON_PREEMPTIVE_CODE: + ioTime = intArg * configPtr->ioCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); + pthread_join(ioThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + break; + + case PREEMPTIVE_CODE: + // need to set this to 'blocked' state here. + singlePCB->process_state = PROCESS_STATE_BLOCKED; + ioTime = intArg * configPtr->ioCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + // pthread_join(ioThread, NULL); // not sure if this will be needed... + // pthread_exit(NULL); // this may be needed if pthread_join doesn't produce expected results. + // call the interruptManager here, with the IO Return code. + interruptManager(configPtr, singlePCB, IO_RETURN); + break; + + default: + // this shouldn't happen, but if it does, you'll know... + break; + } } /* @@ -673,13 +751,14 @@ Device Input/Device: none Device Output/Device: none Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ -void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList) +void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList, + ConfigDataCodes schedMethod) { double timeDigits; // 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]; - char processOutput[HUGE_STR_LEN]; + char processOutput[HUGE_STR_LEN * 4]; // grab the next operation code for the OpCodeType *workingMeta = singlePCB->nextOpCode; char *command; @@ -701,12 +780,14 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce 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); + runCPU(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, + singlePCB, schedMethod); } if(compareString(command, "dev") == EQUIV) { // run IO operations for the required amount of time. - runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); + runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, + singlePCB, schedMethod); } if(compareString(command, "mem") == EQUIV) { @@ -751,6 +832,17 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce argument = workingMeta->strArg1; intArg = workingMeta->intArg2; intArgTwo = workingMeta->intArg3; + + switch (schedMethod) + { + case PREEMPTIVE_CODE: + interruptManager(configPtr, singlePCB, CLEAR_INTERRUPT); + break; + default: + // this will only happen when NON_PREEMPTIVE is in progress, but + // warnings will result without having this here, so... + break; + } } // display the process exited, if not segfaulted. if(memManagerSuccess) @@ -794,7 +886,8 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // string variable for nextCode, temp unused // char *nextCode; // string variable for the timer stuff - char simulatorOutput[MAX_STR_LEN]; + int schedulingMethod = configPtr->cpuSchedCode; + char simulatorOutput[MAX_STR_LEN * 4]; double timeDigits; char timeStringy[MAX_STR_LEN]; int processCount = 0; @@ -802,6 +895,19 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) int memoryOffset = 0; int memorySize = 1; + if (schedulingMethod == CPU_SCHED_FCFS_P_CODE || + schedulingMethod == CPU_SCHED_RR_P_CODE || + schedulingMethod == CPU_SCHED_SRTF_P_CODE) + { + // if in a preemptive scheduling method, set to PREEMPTIVE MODE + schedulingMethod = PREEMPTIVE_CODE; + } + else + { + // if in a non-preemptive scheduling method, set to NON_PREEMPTIVE MODE + schedulingMethod = NON_PREEMPTIVE_CODE; + } + accessTimer(ZERO_TIMER, timeStringy); // Operating System start timer goes here, log it. timeDigits = accessTimer(LAP_TIMER, timeStringy); @@ -858,13 +964,23 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) logOutput(configPtr, simulatorOutput, false); pthread_t runThread; pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr); - runProcess(pcbPtr, configPtr, pcbList); - // when finished, set to terminated - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", timeDigits, - pcbPtr->uniquePid); - logOutput(configPtr, simulatorOutput, false); - pcbPtr->process_state = PROCESS_STATE_TERMINATED; + runProcess(pcbPtr, configPtr, pcbList, schedulingMethod); + switch (schedulingMethod) + { + case NON_PREEMPTIVE_CODE: + // when finished, set to terminated + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", timeDigits, + pcbPtr->uniquePid); + logOutput(configPtr, simulatorOutput, false); + // this assumes that the processes finish executing all the way though. + pcbPtr->process_state = PROCESS_STATE_TERMINATED; + break; + case PREEMPTIVE_CODE: + // will need to instead, set the next process up? + interruptManager(configPtr, pcbPtr, CPU_SWITCH); + break; + } pthread_join(runThread, NULL); } processTimeLeft = pcbPtr->timeLeft; @@ -973,9 +1089,55 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt break; case CPU_SCHED_FCFS_P_CODE: // TODO: First Come, First Served, Preemptive Scheduling + // try copying the previous code, making sure that if it is in a + // blocked state, it cannot be scheduled, + // if it is in a waiting state, then it can be scheduled. + // can also be scheduled or not based on the previous section of + // code as well. + 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + 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 running, terminated OR blocked. + if (wkgPtr->process_state != PROCESS_STATE_RUNNING && + wkgPtr->process_state != PROCESS_STATE_TERMINATED && + wkgPtr->process_state != PROCESS_STATE_BLOCKED) + { + // printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + wkgPtr->uniquePid, wkgPtr->timeLeft); + logOutput(configPtr, loggingStr, false); + returnPid = wkgPtr->uniquePid; + } + // move to next pointer + wkgPtr = wkgPtr->nextPtr; + } break; case CPU_SCHED_RR_P_CODE: // TODO: Round Robin Scheduling + // need to FCFS first. however, just rotate through each process. + // maybe keep track via an array or previously used process? not sure how exactly I want this. + // maybe an extern??? not sure how to essentially keep track even when scope is lost here. + // actually, I think a static variable may be the key to solving this. + // alternatively, I could use a circularly linked list, given that proper scheduling is done. break; case CPU_SCHED_SJF_N_CODE: // Shortest Job First Scheduling @@ -1053,6 +1215,77 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt break; case CPU_SCHED_SRTF_P_CODE: // TODO: Shortest Run-time First Scheduling + // may be able to copy the same code that I've used above, just + // with more restrictive rules similarly to the FCFS described above. + 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + 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 and NOT blocked. (can only be waiting) + // now, ALSO needs to check which process takes the least time. + if (wkgPtr->process_state != PROCESS_STATE_RUNNING && + wkgPtr->process_state != PROCESS_STATE_TERMINATED && + wkgPtr->process_state != PROCESS_STATE_BLOCKED) + { + // 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); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + shortestJobProcNum, (double)shortestJob); + logOutput(configPtr, loggingStr, false); + } + returnPid = shortestJobProcNum; break; } // return returnPid diff --git a/Sim04/simulator.h b/Sim04/simulator.h index f55b9de..b31aa41 100644 --- a/Sim04/simulator.h +++ b/Sim04/simulator.h @@ -25,6 +25,13 @@ typedef enum{ MEMORY_DEALLOCATE } MEMORY_SIGNALS; +typedef enum{ + IO_RETURN = 0, + QUANTUM_TIMEOUT, + CPU_SWITCH, + CLEAR_INTERRUPT + } INTERRUPT_ROUTINE; + typedef struct ProcessControlBlockStruct { int uniquePid; @@ -143,7 +150,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *metadataPtr, ProcessControlBlockLL *headPointer); +ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *metadataPtr, + ProcessControlBlockLL *headPointer); /* Name: findMin @@ -181,7 +189,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod); /* Name: runIO @@ -193,7 +202,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod); /* Name: runSim Process: primary simulation driver