From fda57566d88c65538f58f5e40fbe43625fe87e82 Mon Sep 17 00:00:00 2001 From: cdez Date: Sun, 14 Apr 2024 18:41:58 -0700 Subject: [PATCH] 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. +