#include "configops.h" #include "metadataops.h" #include "StandardConstants.h" #include "simulator.h" /* Name: addProcess Process: adds a process to the 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, fillProcessList */ // ProcessControlBlock *addProcess() // { // // return NULL (temp) // return NULL; // } /* 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: 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) { // 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. (Linking is left to the calling function, returns a pointer to the filled struct) Function Input/Parameters: metadata (OpCodeType *) Function Output/Parameters: none Function Output/Returned: pointer to filled PCB (ProcessControlBlock *) Device Input/Device: none Device Output/Device: none Dependencies: ??? */ ProcessControlBlockLL *fillProcessList(OpCodeType *metadataPtr, ProcessControlBlockLL *headPointer) { // initialize function/variables // need a working pointer for the metadata OpCodeType *wkgMetaPtr; OpCodeType *wkgInternalPtr; ProcessControlBlock currentPCB; ProcessControlBlock *wkgPCBPtr; // 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 int timeLeftCount = 0; // need a variable that fills PIDs, starting at 0 int processId = 0; // process variables? char *command; char *commandInt; char *argument; char *argumentInt; char *inOutArg; int integerArgumentOne; // unused as of current //int integerArgumentTwo; // set the working pointer to the first part of the metadata pointer wkgMetaPtr = 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; // loop through the process list, until you hit a sys end. while(wkgMetaPtr->nextNode != NULL || (compareString(argument, "end") && compareString(command, "sys"))) { // 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; // set the nextOpCode as a pointer to the first place metadataPtr started currentPCB.nextOpCode = wkgMetaPtr; // set the internal pointer to the location that wkgPtr is at wkgInternalPtr = wkgMetaPtr; // set the internal command and argument commandInt = wkgInternalPtr->command; argumentInt = wkgInternalPtr->strArg1; inOutArg = wkgInternalPtr->inOutArg; integerArgumentOne = wkgInternalPtr->intArg2; // integer argument two is unused atm //integerArgumentTwo = wkgInternalPtr->intArg3; // loop while no longer have io or cpu instructions? (aka not at app end?) while(wkgInternalPtr->nextNode != NULL || (compareString(argumentInt, "end") && compareString(commandInt, "app"))) { // count number of io cycles if((compareString(commandInt, "dev") == 0 && compareString(inOutArg, "in") == 0)) { ioCycleCount = ioCycleCount + integerArgumentOne; } if((compareString(commandInt, "dev") == 0 && compareString(inOutArg, "out") == 0)) { ioCycleCount = ioCycleCount + integerArgumentOne; } // count number of cpu cycles if((compareString(argumentInt, "process") == 0 && compareString(commandInt, "cpu") == 0)) { cpuCycleCount = cpuCycleCount + integerArgumentOne; } // move to next node, set relevant args wkgInternalPtr = wkgInternalPtr->nextNode; commandInt = wkgInternalPtr->command; argumentInt = wkgInternalPtr->strArg1; inOutArg = wkgInternalPtr->inOutArg; } // 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 the time left from (ioCycles * ioCycleRate) + (cpuCycles * procCyclesRate) // this gets the number of ms in the process. currentPCB.timeLeft = timeLeftCount; // increment the PID counter processId = processId + 1; } // move to the next bit of data wkgMetaPtr = wkgMetaPtr->nextNode; command = wkgMetaPtr->command; argument = wkgMetaPtr->strArg1; // needs to add nodes to the end and all data once parsed // do both the metadata and PCBs wkgPCBPtr = ¤tPCB; wkgPCBPtr->nextPtr = NULL; } // return null (temp) (should return the headpointer) return headPointer; } /* 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) { // initialize function/variables // need a FILE * for file operations FILE *fileWritePtr; // 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; // string variable for nextCode char *nextCode; // create the process list with createProcessList, store the pointed to address pcbList = createProcessList(); // fill the process list given the metadata pcbList = fillProcessList(metaDataMstrPtr, pcbList); // create temp strings char *command; char *argument; // get the first data out of the metadata command = metaDataMstrPtr->command; argument = metaDataMstrPtr->strArg1; // set the master working pointer to the first metadata block wkgPtrMaster = metaDataMstrPtr; // function holds master loop, loops until sys end opcode found OR wkgPtrMaster nextNode != NULL while( wkgPtrMaster->nextNode != NULL || (compareString(argument, "end") && compareString(command, "sys"))) { // will have a loop that goes from app start to app end for a PCB // (checks to see if the next instruction is NOT app end), using getNextProcess? // this will getNextOpCode // this will checkForIO and run the IO operations, outputting to FILE * and/or monitor // checkForIO will need the FILE * passed, will need timer access, and ??? // this will checkForCPU and run the CPU operations, outputting to FILE * and/or monitor // checkForCPU will need the FILE * passed, will need timer access, and ??? // move the wkgPtrMaster to the next metadata block wkgPtrMaster = wkgPtrMaster->nextNode; // set the command and argument to the current cmd and arg command = wkgPtrMaster->command; argument = wkgPtrMaster->strArg1; } // // deallocate the process list with destroyProcessList destroyProcessList(pcbList); //printf("runSim called here"); // void function, no return. } // getNextProcess/scheduler/dispatcher run here, loads/"runs" the process // getNextOpCode, not needed for Sim02 apparently, keep in mind. // checkForIO, I think this gets passed the current process and runs the IO ops // checkForCPU, I think this gets passed the current process and runs the CPU ops // checkForMemory, I think this gets passed the current process // and runs mem ops (not needed for Sim02) // cpuIdler (not needed for Sim02)