Merge branch 'main' of https://git.cdezselfhosted.pw/cdez/CS480-Projects
This commit is contained in:
commit
37aa8c3b81
28 changed files with 5614 additions and 147 deletions
BIN
Sim03/Sim03_GradingForm_413499.xlsx
Normal file
BIN
Sim03/Sim03_GradingForm_413499.xlsx
Normal file
Binary file not shown.
|
|
@ -1,7 +1 @@
|
||||||
0.000000, OS: Simulator start
|
0.000988, OS: Simulator start
|
||||||
READY state from NEW state
|
|
||||||
ate
|
|
||||||
|
|
||||||
ate
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ OBJECTS = OS_SimDriver.o simulator.o metadataops.o configops.o StringUtils.o sim
|
||||||
all: Simulator
|
all: Simulator
|
||||||
|
|
||||||
Simulator: $(OBJECTS)
|
Simulator: $(OBJECTS)
|
||||||
$(CC) $(OBJECTS) -o sim03
|
$(CC) $(OBJECTS) -lpthread -o sim03
|
||||||
|
|
||||||
StringUtils.o: StringUtils.c
|
StringUtils.o: StringUtils.c
|
||||||
$(CC) -c StringUtils.c -o StringUtils.o
|
$(CC) -c StringUtils.c -o StringUtils.o
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,13 @@
|
||||||
const char RADIX_POINT = '.';
|
const char RADIX_POINT = '.';
|
||||||
const char SPACED = ' ';
|
const char SPACED = ' ';
|
||||||
|
|
||||||
void runTimer( int milliSeconds )
|
void *runTimer( void *mSecVoidPtr )
|
||||||
{
|
{
|
||||||
struct timeval startTime, endTime;
|
struct timeval startTime, endTime;
|
||||||
int startSec, startUSec, endSec, endUSec;
|
int startSec, startUSec, endSec, endUSec;
|
||||||
int uSecDiff, mSecDiff, secDiff, timeDiff;
|
int uSecDiff, mSecDiff, secDiff, timeDiff;
|
||||||
|
int *mSecPtr = (int *)mSecVoidPtr;
|
||||||
|
int milliSeconds = *mSecPtr;
|
||||||
|
|
||||||
gettimeofday( &startTime, NULL );
|
gettimeofday( &startTime, NULL );
|
||||||
|
|
||||||
|
|
@ -62,9 +64,44 @@ void runTimer( int milliSeconds )
|
||||||
secDiff = ( endSec - startSec ) * 1000;
|
secDiff = ( endSec - startSec ) * 1000;
|
||||||
timeDiff = secDiff + mSecDiff;
|
timeDiff = secDiff + mSecDiff;
|
||||||
}
|
}
|
||||||
// return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void runTimer(int milliSeconds)
|
||||||
|
// {
|
||||||
|
// struct timeval startTime, endTime;
|
||||||
|
// int startSec, startUSec, endSec, endUSec;
|
||||||
|
// int uSecDiff, mSecDiff, secDiff, timeDiff;
|
||||||
|
|
||||||
|
// gettimeofday(&startTime, NULL);
|
||||||
|
|
||||||
|
// startSec = startTime.tv_sec;
|
||||||
|
// startUSec = startTime.tv_usec;
|
||||||
|
|
||||||
|
// timeDiff = 0;
|
||||||
|
|
||||||
|
// while (timeDiff < milliSeconds)
|
||||||
|
// {
|
||||||
|
// gettimeofday(&endTime, NULL);
|
||||||
|
|
||||||
|
// endSec = endTime.tv_sec;
|
||||||
|
// endUSec = endTime.tv_usec;
|
||||||
|
// uSecDiff = endUSec - startUSec;
|
||||||
|
|
||||||
|
// if (uSecDiff < 0)
|
||||||
|
// {
|
||||||
|
// uSecDiff = uSecDiff + 1000000;
|
||||||
|
|
||||||
|
// endSec = endSec - 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mSecDiff = uSecDiff / 1000;
|
||||||
|
// secDiff = (endSec - startSec) * 1000;
|
||||||
|
// timeDiff = secDiff + mSecDiff;
|
||||||
|
// }
|
||||||
|
// // return NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
double accessTimer( int controlCode, char *timeStr )
|
double accessTimer( int controlCode, char *timeStr )
|
||||||
{
|
{
|
||||||
static bool running = false;
|
static bool running = false;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ extern const char SPACED;
|
||||||
|
|
||||||
// Function Prototyp /////////////////////////////////////////////////////////
|
// Function Prototyp /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void runTimer( int milliSeconds );
|
void *runTimer(void *mSecVoidPtr);
|
||||||
// will run a timer for the amount of ms specified
|
// will run a timer for the amount of ms specified
|
||||||
double accessTimer( int controlCode, char *timeStr );
|
double accessTimer( int controlCode, char *timeStr );
|
||||||
// returns the actual time as a double AND as a time string
|
// returns the actual time as a double AND as a time string
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,45 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name: accessMemory
|
Name: accessMemory
|
||||||
Process: checks offset from the PCB
|
Process: checks that the memory is between the offset and the size.
|
||||||
|
checks that the memory is ???
|
||||||
Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int)
|
Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int)
|
||||||
Function Output/Parameters: none
|
Function Output/Parameters: none
|
||||||
Function Output/Returned: none?
|
Function Output/Returned: boolean to indicate success or failure of accessed memory
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: ???
|
Dependencies: ???
|
||||||
*/
|
*/
|
||||||
void accessMemory(ProcessControlBlock *singlePCB, int offset, int size)
|
bool accessMemory(ProcessControlBlock *singlePCB, int offset, int size)
|
||||||
{
|
{
|
||||||
// no return, void (temp)
|
// return true (temp)
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -40,6 +68,9 @@ ProcessControlBlock *addProcess(const ProcessControlBlock source)
|
||||||
workingNode->process_state = source.process_state;
|
workingNode->process_state = source.process_state;
|
||||||
workingNode->timeLeft = source.timeLeft;
|
workingNode->timeLeft = source.timeLeft;
|
||||||
workingNode->totalCycles = source.totalCycles;
|
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!
|
// make sure to set the next pointer to NULL!
|
||||||
workingNode->nextPtr = NULL;
|
workingNode->nextPtr = NULL;
|
||||||
// return workingNode
|
// return workingNode
|
||||||
|
|
@ -51,14 +82,46 @@ Name: allocMemory
|
||||||
Process: 'allocates' memory within the PCB, stores offset and size within it's PCB
|
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 Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int)
|
||||||
Function Output/Parameters: none
|
Function Output/Parameters: none
|
||||||
Function Output/Returned: none?
|
Function Output/Returned: boolean to indicate success or failure of allocated memory
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: ???
|
Dependencies: ???
|
||||||
*/
|
*/
|
||||||
void allocMemory(ProcessControlBlock *singlePCB, int offset, int size)
|
bool allocMemory(ProcessControlBlock *singlePCB, int offset, int size, int arraySize)
|
||||||
{
|
{
|
||||||
// no return, void (temp)
|
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: 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -84,17 +147,46 @@ ProcessControlBlockLL *createProcessList()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name: deallocMemory
|
Name: deallocMemory
|
||||||
Process: 'deallocates' memory within the PCB, removes offset and size within it's PCB
|
Process: 'deallocates' memory within the PCB, removes every offset and size within it's PCB
|
||||||
Function Input/Parameters: source PCB (ProcessControlBlock *), offset (int), size (int)
|
Function Input/Parameters: source PCB (ProcessControlBlock *)
|
||||||
Function Output/Parameters: none
|
Function Output/Parameters: none
|
||||||
Function Output/Returned: none?
|
Function Output/Returned: boolean to indicate success or failure of allocated memory
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: ???
|
Dependencies: ???
|
||||||
*/
|
*/
|
||||||
void deallocMemory(ProcessControlBlock *singlePCB, int offset, int size)
|
bool deallocMemory(ProcessControlBlock *singlePCB, int arraySize)
|
||||||
{
|
{
|
||||||
// no return, void (temp)
|
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: 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -117,6 +209,30 @@ ProcessControlBlockLL *destroyProcessList(ProcessControlBlockLL *linkedListPtr)
|
||||||
return NULL;
|
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
|
Name: destroyProcessListHelper
|
||||||
Process: recursively clears the PCB linked list struct, freeing the struct
|
Process: recursively clears the PCB linked list struct, freeing the struct
|
||||||
|
|
@ -132,6 +248,8 @@ ProcessControlBlock *destroyProcessListHelper(ProcessControlBlock *nodePtr)
|
||||||
// check to see if the pointer is NOT null
|
// check to see if the pointer is NOT null
|
||||||
if(nodePtr != NULL)
|
if(nodePtr != NULL)
|
||||||
{
|
{
|
||||||
|
free(nodePtr->allocatedMemOffsets);
|
||||||
|
free(nodePtr->allocatedMemSizes);
|
||||||
// if not null, move to the next pointer (recurse)
|
// if not null, move to the next pointer (recurse)
|
||||||
nodePtr->nextPtr = destroyProcessListHelper(nodePtr->nextPtr);
|
nodePtr->nextPtr = destroyProcessListHelper(nodePtr->nextPtr);
|
||||||
}
|
}
|
||||||
|
|
@ -168,6 +286,8 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me
|
||||||
double timeLeftCount = 0.0;
|
double timeLeftCount = 0.0;
|
||||||
// need a variable that fills PIDs, starting at 0
|
// need a variable that fills PIDs, starting at 0
|
||||||
int processId = 0;
|
int processId = 0;
|
||||||
|
// need a variable that checks how many allocate statements there are.
|
||||||
|
int memAllocation = 0;
|
||||||
// process variables?
|
// process variables?
|
||||||
char *command;
|
char *command;
|
||||||
char *argument;
|
char *argument;
|
||||||
|
|
@ -226,6 +346,12 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me
|
||||||
cpuCycleCount = cpuCycleCount + integerArgumentOne;
|
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))
|
if ((compareString(argument, "end") == EQUIV && compareString(command, "app") == EQUIV))
|
||||||
{
|
{
|
||||||
// set the ioCycles from variable
|
// set the ioCycles from variable
|
||||||
|
|
@ -234,6 +360,9 @@ ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *me
|
||||||
currentPCB.cpuCycles = cpuCycleCount;
|
currentPCB.cpuCycles = cpuCycleCount;
|
||||||
// set totalCycles from adding both IO/CPU
|
// set totalCycles from adding both IO/CPU
|
||||||
currentPCB.totalCycles = ioCycleCount + cpuCycleCount;
|
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
|
// currentPCB must have the starting instruction from wkgInsPtr
|
||||||
wkgInsPtr = wkgMetaPtr;
|
wkgInsPtr = wkgMetaPtr;
|
||||||
|
|
@ -305,48 +434,350 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: fprintf, ???
|
Dependencies: fprintf, ???
|
||||||
*/
|
*/
|
||||||
void logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd)
|
logFileLL *logOutput(ConfigDataType *configPtr, char *logStr, bool isEnd, logFileLL *logPtr)
|
||||||
{
|
{
|
||||||
|
logFile toLog;
|
||||||
|
// toLog.stringData = malloc(sizeof(*logStr));
|
||||||
|
logFile *wkgLogPtr;
|
||||||
|
wkgLogPtr = logPtr->headPtr;
|
||||||
if (configPtr->logToCode == LOGTO_BOTH_CODE)
|
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.
|
// close the file, if at the end.
|
||||||
if (isEnd)
|
if (isEnd)
|
||||||
{
|
{
|
||||||
|
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);
|
fclose(fileWritePtr);
|
||||||
}
|
}
|
||||||
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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.
|
// close the file, if at the end.
|
||||||
if (isEnd)
|
// if (isEnd)
|
||||||
{
|
// {
|
||||||
fclose(fileWritePtr);
|
// 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);
|
// 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
|
else
|
||||||
{
|
{
|
||||||
fprintf(stdout, "%s", logStr);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -399,7 +830,7 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: pthreads, sprintf, logOutput, ???
|
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 timeStringy[MAX_STR_LEN];
|
||||||
// char *command = workingMeta->command;
|
// char *command = workingMeta->command;
|
||||||
|
|
@ -407,15 +838,16 @@ void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr
|
||||||
// int intArg = workingMeta->intArg2;
|
// int intArg = workingMeta->intArg2;
|
||||||
char cpuOutput[MAX_STR_LEN];
|
char cpuOutput[MAX_STR_LEN];
|
||||||
int cpuTime = 0;
|
int cpuTime = 0;
|
||||||
|
int *cpuTimePtr = &cpuTime;
|
||||||
cpuTime = intArg * configPtr->procCycleRate;
|
cpuTime = intArg * configPtr->procCycleRate;
|
||||||
sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument);
|
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
|
// run timer for intArg * procCycleRate
|
||||||
pthread_t cpuThread;
|
pthread_t cpuThread;
|
||||||
pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)cpuTime);
|
pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr);
|
||||||
pthread_join(cpuThread, NULL);
|
pthread_join(cpuThread, NULL);
|
||||||
sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument);
|
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);
|
// pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,19 +861,20 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: pthreads, sprintf, logOutput, ???
|
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 timeStringy[MAX_STR_LEN];
|
||||||
char ioOutput[MAX_STR_LEN];
|
char ioOutput[MAX_STR_LEN];
|
||||||
int ioTime = 0;
|
int ioTime = 0;
|
||||||
|
int *ioTimePtr = &ioTime;
|
||||||
ioTime = intArg * configPtr->ioCycleRate;
|
ioTime = intArg * configPtr->ioCycleRate;
|
||||||
sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument);
|
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_t ioThread;
|
||||||
pthread_create(&ioThread, NULL, (void *)&simThread, (void *)ioTime);
|
pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr);
|
||||||
pthread_join(ioThread, NULL);
|
pthread_join(ioThread, NULL);
|
||||||
sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", accessTimer(LAP_TIMER, timeStringy), processId, command, argument);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -454,39 +887,89 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: accessTimer, compareString, runCPU, runIO, ???
|
Dependencies: accessTimer, compareString, runCPU, runIO, ???
|
||||||
*/
|
*/
|
||||||
void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr)
|
void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList, logFileLL *logList)
|
||||||
{
|
{
|
||||||
// run over the entire process, running the CPU when a CPU cycle comes up
|
// run over the entire process, running the CPU when a CPU cycle comes up
|
||||||
// or a run IO when an IO cycle comes up
|
// or a run IO when an IO cycle comes up
|
||||||
char timeStringy[MAX_STR_LEN];
|
char timeStringy[MAX_STR_LEN];
|
||||||
|
char processOutput[HUGE_STR_LEN];
|
||||||
// grab the next operation code for the
|
// grab the next operation code for the
|
||||||
OpCodeType *workingMeta = singlePCB->nextOpCode;
|
OpCodeType *workingMeta = singlePCB->nextOpCode;
|
||||||
char *command;
|
char *command;
|
||||||
char *argument;
|
char *argument;
|
||||||
int intArg;
|
int intArg;
|
||||||
char *inOutArg;
|
int intArgTwo;
|
||||||
|
bool memManagerSuccess = true;
|
||||||
|
// char *inOutArg;
|
||||||
command = workingMeta->command;
|
command = workingMeta->command;
|
||||||
argument = workingMeta->strArg1;
|
argument = workingMeta->strArg1;
|
||||||
intArg = workingMeta->intArg2;
|
intArg = workingMeta->intArg2;
|
||||||
inOutArg = workingMeta->inOutArg;
|
intArgTwo = workingMeta->intArg3;
|
||||||
while (!(compareString(command, "app") == EQUIV && compareString(argument, "end") == EQUIV) && !(compareString(command, "sys") == EQUIV && compareString(argument, "end") == EQUIV))
|
// 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
|
// check to see what operation will be performed
|
||||||
if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV)
|
if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV)
|
||||||
{
|
{
|
||||||
// run the CPU for the required amount of time.
|
// 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)
|
if(compareString(command, "dev") == EQUIV)
|
||||||
{
|
{
|
||||||
// run IO operations for the required amount of time.
|
// 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)
|
||||||
|
{
|
||||||
|
// 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, logList);
|
||||||
|
// run the memory manager in allocate mode
|
||||||
|
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, 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, logList);
|
||||||
|
// run the memory manager in access mode
|
||||||
|
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, logList);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
workingMeta = workingMeta->nextNode;
|
workingMeta = workingMeta->nextNode;
|
||||||
command = workingMeta->command;
|
command = workingMeta->command;
|
||||||
argument = workingMeta->strArg1;
|
argument = workingMeta->strArg1;
|
||||||
intArg = workingMeta->intArg2;
|
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, logList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
sprintf(processOutput, "\n%f, OS: Segmentation Fault, Process %d ended\n", accessTimer(LAP_TIMER, timeStringy), singlePCB->uniquePid);
|
||||||
|
logOutput(configPtr, processOutput, false, logList);
|
||||||
|
}
|
||||||
|
// deallocate the memory for the process
|
||||||
|
memManager(pcbList, MEMORY_DEALLOCATE, intArg, intArgTwo, configPtr, singlePCB, logList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -504,11 +987,12 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr)
|
||||||
{
|
{
|
||||||
// initialize function/variables
|
// initialize function/variables
|
||||||
// need two working pointers, one for master loop, one for internal loop
|
// need two working pointers, one for master loop, one for internal loop
|
||||||
OpCodeType *wkgPtrMaster;
|
// OpCodeType *wkgPtrMaster;
|
||||||
// currentTime variable that stores the time. [now unsure if needed]
|
// currentTime variable that stores the time. [now unsure if needed]
|
||||||
// need a variable for headPointer to point
|
// need a variable for headPointer to point
|
||||||
ProcessControlBlockLL *pcbList;
|
ProcessControlBlockLL *pcbList;
|
||||||
ProcessControlBlock *pcbPtr;
|
ProcessControlBlock *pcbPtr;
|
||||||
|
logFileLL *loggingList;
|
||||||
// string variable for nextCode, temp unused
|
// string variable for nextCode, temp unused
|
||||||
// char *nextCode;
|
// char *nextCode;
|
||||||
// string variable for the timer stuff
|
// string variable for the timer stuff
|
||||||
|
|
@ -516,12 +1000,16 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr)
|
||||||
char timeStringy[MAX_STR_LEN];
|
char timeStringy[MAX_STR_LEN];
|
||||||
int processCount = 0;
|
int processCount = 0;
|
||||||
int processIterator;
|
int processIterator;
|
||||||
|
int memoryOffset = 0;
|
||||||
|
int memorySize = 1;
|
||||||
|
|
||||||
|
// create the file list with createFileLogList, store the pointed to address
|
||||||
|
loggingList = createFileLogList();
|
||||||
|
|
||||||
accessTimer(ZERO_TIMER, timeStringy);
|
accessTimer(ZERO_TIMER, timeStringy);
|
||||||
// Operating System start timer goes here, log it.
|
// Operating System start timer goes here, log it.
|
||||||
sprintf(simulatorOutput, "%f, OS: Simulator start\n", accessTimer(LAP_TIMER, timeStringy));
|
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 variable for process to run
|
||||||
int currentPid;
|
int currentPid;
|
||||||
// create the process list with createProcessList, store the pointed to address
|
// create the process list with createProcessList, store the pointed to address
|
||||||
|
|
@ -539,43 +1027,23 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr)
|
||||||
processCount = processCount + 1;
|
processCount = processCount + 1;
|
||||||
}
|
}
|
||||||
pcbPtr = pcbList->headPtr;
|
pcbPtr = pcbList->headPtr;
|
||||||
|
int *totalPCBTimePtr = &totalPCBTime;
|
||||||
|
|
||||||
|
|
||||||
pthread_t cpuThread;
|
pthread_t cpuThread;
|
||||||
pthread_create(&cpuThread, NULL, (void *)&simThread, (void *)totalPCBTime);
|
pthread_create(&cpuThread, NULL, runTimer, (void *)totalPCBTimePtr);
|
||||||
|
|
||||||
//
|
//
|
||||||
int processTimeLeft = pcbPtr->timeLeft;
|
int processTimeLeft = pcbPtr->timeLeft;
|
||||||
|
int *processTimeLeftPtr = &processTimeLeft;
|
||||||
|
|
||||||
// set the current process id to the first scheduled process
|
// 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, loggingList);
|
||||||
|
|
||||||
// loop until current process is hit
|
// loop until current process is hit
|
||||||
// while(pcbPtr->process_state != PROCESS_STATE_TERMINATED && pcbPtr != NULL && processCount != 0)
|
|
||||||
// {
|
|
||||||
// if(pcbPtr->uniquePid == currentPid)
|
|
||||||
// {
|
|
||||||
// // needs to set from READY to RUNNING
|
|
||||||
// pcbPtr->process_state = PROCESS_STATE_RUNNING;
|
|
||||||
// sprintf(simulatorOutput, "%f, OS: Process %d set to RUNNING state from READY state\n\n", accessTimer(LAP_TIMER, timeStringy), pcbPtr->uniquePid);
|
|
||||||
// logOutput(configPtr, simulatorOutput, false);
|
|
||||||
// pthread_t runThread;
|
|
||||||
// pthread_create(&runThread, NULL, (void *)&simThread, (void *)processTimeLeft);
|
|
||||||
// runProcess(pcbPtr, configPtr);
|
|
||||||
// // when finished, set to terminated
|
|
||||||
// sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", accessTimer(LAP_TIMER, timeStringy), pcbPtr->uniquePid);
|
|
||||||
// logOutput(configPtr, simulatorOutput, false);
|
|
||||||
// pcbPtr->process_state = PROCESS_STATE_TERMINATED;
|
|
||||||
// processCount = processCount - 1;
|
|
||||||
// pthread_join(runThread, NULL);
|
|
||||||
// }
|
|
||||||
// processTimeLeft = pcbPtr->timeLeft;
|
|
||||||
// pcbPtr = pcbPtr->nextPtr;
|
|
||||||
// currentPid = scheduleProcess(pcbList, configPtr);
|
|
||||||
// if(configPtr->cpuSchedCode == CPU_SCHED_SJF_N_CODE && pcbPtr == NULL)
|
|
||||||
// {
|
|
||||||
// //
|
|
||||||
// pcbPtr = pcbList->headPtr;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
for(processIterator = 0; processIterator < processCount; processIterator++)
|
for(processIterator = 0; processIterator < processCount; processIterator++)
|
||||||
{
|
{
|
||||||
while (pcbPtr != NULL)
|
while (pcbPtr != NULL)
|
||||||
|
|
@ -588,31 +1056,36 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr)
|
||||||
// needs to set from READY to RUNNING
|
// needs to set from READY to RUNNING
|
||||||
pcbPtr->process_state = PROCESS_STATE_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);
|
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_t runThread;
|
||||||
pthread_create(&runThread, NULL, (void *)&simThread, (void *)processTimeLeft);
|
pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr);
|
||||||
runProcess(pcbPtr, configPtr);
|
runProcess(pcbPtr, configPtr, pcbList, loggingList);
|
||||||
// when finished, set to terminated
|
// 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);
|
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;
|
pcbPtr->process_state = PROCESS_STATE_TERMINATED;
|
||||||
pthread_join(runThread, NULL);
|
pthread_join(runThread, NULL);
|
||||||
}
|
}
|
||||||
processTimeLeft = pcbPtr->timeLeft;
|
processTimeLeft = pcbPtr->timeLeft;
|
||||||
|
processTimeLeftPtr = &processTimeLeft;
|
||||||
pcbPtr = pcbPtr->nextPtr;
|
pcbPtr = pcbPtr->nextPtr;
|
||||||
}
|
}
|
||||||
currentPid = scheduleProcess(pcbList, configPtr);
|
currentPid = scheduleProcess(pcbList, configPtr, loggingList);
|
||||||
pcbPtr = pcbList->headPtr;
|
pcbPtr = pcbList->headPtr;
|
||||||
}
|
}
|
||||||
pthread_join(cpuThread, NULL);
|
pthread_join(cpuThread, NULL);
|
||||||
|
// deallocate all the memory for each process.
|
||||||
|
memManager(pcbList, MEMORY_CLEAR, memoryOffset, memorySize, configPtr, pcbList->headPtr, loggingList);
|
||||||
sprintf(simulatorOutput, "%f, OS: System Stop\n", accessTimer(LAP_TIMER, timeStringy));
|
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));
|
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
|
// deallocate the process list with destroyProcessList
|
||||||
destroyProcessList(pcbList);
|
destroyProcessList(pcbList);
|
||||||
// once complete, log the output to FILE if required
|
// 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
|
// pthread_exit(NULL); // this line seems to make the program execution stop short... no warning either
|
||||||
// void function, no return.
|
// void function, no return.
|
||||||
}
|
}
|
||||||
|
|
@ -628,7 +1101,7 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: sprintf, logOutput, ???
|
Dependencies: sprintf, logOutput, ???
|
||||||
*/
|
*/
|
||||||
int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr)
|
int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr, logFileLL *logList)
|
||||||
{
|
{
|
||||||
ProcessControlBlock *wkgPtr;
|
ProcessControlBlock *wkgPtr;
|
||||||
int returnPid = -1;
|
int returnPid = -1;
|
||||||
|
|
@ -637,6 +1110,9 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
char timeStringy[MAX_STR_LEN];
|
char timeStringy[MAX_STR_LEN];
|
||||||
int processCount = 0;
|
int processCount = 0;
|
||||||
|
|
||||||
|
int shortestJob = 0;
|
||||||
|
int shortestJobProcNum = 0;
|
||||||
|
|
||||||
while (wkgPtr != NULL)
|
while (wkgPtr != NULL)
|
||||||
{
|
{
|
||||||
if(wkgPtr->process_state != PROCESS_STATE_TERMINATED)
|
if(wkgPtr->process_state != PROCESS_STATE_TERMINATED)
|
||||||
|
|
@ -667,7 +1143,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
wkgPtr->process_state = PROCESS_STATE_READY;
|
wkgPtr->process_state = PROCESS_STATE_READY;
|
||||||
// printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid);
|
// 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);
|
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
|
// move to the next pointer
|
||||||
wkgPtr = wkgPtr->nextPtr;
|
wkgPtr = wkgPtr->nextPtr;
|
||||||
|
|
@ -682,7 +1158,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
{
|
{
|
||||||
//printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft);
|
//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);
|
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;
|
returnPid = wkgPtr->uniquePid;
|
||||||
}
|
}
|
||||||
// move to next pointer
|
// move to next pointer
|
||||||
|
|
@ -700,8 +1176,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
// need to find shortest job, maybe using a find min function?
|
// need to find shortest job, maybe using a find min function?
|
||||||
// reuse the previous code to set each process to READY from NEW
|
// 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.
|
// will select the process that is in the READY state, with the shortest time.
|
||||||
int shortestJob = 0;
|
|
||||||
int shortestJobProcNum = 0;
|
|
||||||
while (wkgPtr != NULL)
|
while (wkgPtr != NULL)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|
@ -711,7 +1186,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
wkgPtr->process_state = PROCESS_STATE_READY;
|
wkgPtr->process_state = PROCESS_STATE_READY;
|
||||||
// printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid);
|
// 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);
|
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
|
// move to the next pointer
|
||||||
wkgPtr = wkgPtr->nextPtr;
|
wkgPtr = wkgPtr->nextPtr;
|
||||||
|
|
@ -762,7 +1237,7 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt
|
||||||
{
|
{
|
||||||
// printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft);
|
// 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);
|
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;
|
returnPid = shortestJobProcNum;
|
||||||
break;
|
break;
|
||||||
|
|
@ -784,8 +1259,8 @@ Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: pthreads, runTimer
|
Dependencies: pthreads, runTimer
|
||||||
*/
|
*/
|
||||||
void *simThread(int milSec)
|
// void *simThread(int milSec)
|
||||||
{
|
// {
|
||||||
runTimer(milSec);
|
// runTimer(milSec);
|
||||||
pthread_exit(NULL);
|
// pthread_exit(NULL);
|
||||||
}
|
// }
|
||||||
|
|
@ -21,9 +21,23 @@ typedef enum{
|
||||||
MEMORY_INITIALIZE = 0,
|
MEMORY_INITIALIZE = 0,
|
||||||
MEMORY_ACCESS,
|
MEMORY_ACCESS,
|
||||||
MEMORY_ALLOCATE,
|
MEMORY_ALLOCATE,
|
||||||
|
MEMORY_CLEAR,
|
||||||
MEMORY_DEALLOCATE
|
MEMORY_DEALLOCATE
|
||||||
} MEMORY_SIGNALS;
|
} 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
|
typedef struct ProcessControlBlockStruct
|
||||||
{
|
{
|
||||||
int uniquePid;
|
int uniquePid;
|
||||||
|
|
@ -48,6 +62,8 @@ typedef struct ProcessControlBlockStruct
|
||||||
int *allocatedMemOffsets;
|
int *allocatedMemOffsets;
|
||||||
// allocated memory array sizes (stores the sizes for each offset)
|
// allocated memory array sizes (stores the sizes for each offset)
|
||||||
int *allocatedMemSizes;
|
int *allocatedMemSizes;
|
||||||
|
// size of memory array
|
||||||
|
int memArraySize;
|
||||||
// connect to the next process control block here
|
// connect to the next process control block here
|
||||||
struct ProcessControlBlockStruct *nextPtr;
|
struct ProcessControlBlockStruct *nextPtr;
|
||||||
} ProcessControlBlock;
|
} ProcessControlBlock;
|
||||||
|
|
@ -80,6 +96,31 @@ Device Output/Device: none
|
||||||
Dependencies: ???
|
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
|
Name: addProcess
|
||||||
Process: allocates the memory for the pcb, grabs the data from the created PCB,
|
Process: allocates the memory for the pcb, grabs the data from the created PCB,
|
||||||
|
|
@ -93,9 +134,33 @@ Dependencies: malloc, sizeof, ???
|
||||||
*/
|
*/
|
||||||
ProcessControlBlock *addProcess(const ProcessControlBlock source);
|
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
|
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 Input/Parameters: none
|
||||||
Function Output/Parameters: none
|
Function Output/Parameters: none
|
||||||
Function Output/Returned: head pointer to the PCBs
|
Function Output/Returned: head pointer to the PCBs
|
||||||
|
|
@ -105,6 +170,30 @@ Dependencies: malloc, sizeof, ???
|
||||||
*/
|
*/
|
||||||
ProcessControlBlockLL *createProcessList();
|
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
|
Name: destroyProcessList
|
||||||
Process: deallocates memory used for the linked list struct
|
Process: deallocates memory used for the linked list struct
|
||||||
|
|
@ -117,6 +206,18 @@ Dependencies: free, destroyProcessListHelper, ???
|
||||||
*/
|
*/
|
||||||
ProcessControlBlockLL *destroyProcessList(ProcessControlBlockLL *linkedListPtr);
|
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
|
Name: destroyProcessListHelper
|
||||||
Process: recursively clears the PCB linked list struct, freeing the struct
|
Process: recursively clears the PCB linked list struct, freeing the struct
|
||||||
|
|
@ -164,9 +265,24 @@ Function Output/Parameters: none
|
||||||
Function Output/Returned: none
|
Function Output/Returned: none
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/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
|
Name: runCPU
|
||||||
|
|
@ -176,9 +292,9 @@ Function Output/Parameters: none
|
||||||
Function Output/Returned: none
|
Function Output/Returned: none
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/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
|
Name: runIO
|
||||||
|
|
@ -188,9 +304,22 @@ Function Output/Parameters: none
|
||||||
Function Output/Returned: none
|
Function Output/Returned: none
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/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: 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, logFileLL *logList);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name: runSim
|
Name: runSim
|
||||||
Process: primary simulation driver
|
Process: primary simulation driver
|
||||||
|
|
@ -200,32 +329,21 @@ Function Output/Parameters: none
|
||||||
Function Output/Returned: none
|
Function Output/Returned: none
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: ???
|
Dependencies: pthreads, accessTimer, sprintf, logOutput, runProcess, destroyProcessList, ???
|
||||||
*/
|
*/
|
||||||
void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr);
|
void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name: scheduleProcess
|
Name: scheduleProcess
|
||||||
Process: takes in the scheduling data, and then returns which process is to be ran
|
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/Parameters: none
|
||||||
Function Output/Returned: none
|
Function Output/Returned: none
|
||||||
Device Input/Device: none
|
Device Input/Device: none
|
||||||
Device Output/Device: none
|
Device Output/Device: none
|
||||||
Dependencies: ???
|
Dependencies: sprintf, logOutput, ???
|
||||||
*/
|
*/
|
||||||
int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr);
|
int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPtr, logFileLL *logList);
|
||||||
|
|
||||||
/*
|
|
||||||
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
|
#endif // SIMULATORX
|
||||||
246
Sim04/OS_SimDriver.c
Normal file
246
Sim04/OS_SimDriver.c
Normal file
|
|
@ -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] <configfile.cnf>\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.
|
||||||
|
}
|
||||||
74
Sim04/OS_SimDriver.h
Normal file
74
Sim04/OS_SimDriver.h
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef OS_DRIVER
|
||||||
|
#define OS_DRIVER
|
||||||
|
|
||||||
|
// header files
|
||||||
|
#include <stdio.h>
|
||||||
|
#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
|
||||||
79
Sim04/StandardConstants.h
Normal file
79
Sim04/StandardConstants.h
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
// Preprocessor directives
|
||||||
|
#ifndef STANDARD_CONSTANTS_H
|
||||||
|
#define STANDARD_CONSTANTS_H
|
||||||
|
|
||||||
|
// Include Boolean
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// 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
|
||||||
454
Sim04/StringUtils.c
Normal file
454
Sim04/StringUtils.c
Normal file
|
|
@ -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
|
||||||
|
*/
|
||||||
176
Sim04/StringUtils.h
Normal file
176
Sim04/StringUtils.h
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
#ifndef STRINGUTILS
|
||||||
|
#define STRINGUTILS
|
||||||
|
|
||||||
|
// header files
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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
|
||||||
13
Sim04/config0.cnf
Normal file
13
Sim04/config0.cnf
Normal file
|
|
@ -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.
|
||||||
|
|
||||||
608
Sim04/configops.c
Normal file
608
Sim04/configops.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
168
Sim04/configops.h
Normal file
168
Sim04/configops.h
Normal file
|
|
@ -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
|
||||||
0
Sim04/logfile_1.lgf
Normal file
0
Sim04/logfile_1.lgf
Normal file
75
Sim04/metadata5.mdf
Normal file
75
Sim04/metadata5.mdf
Normal file
|
|
@ -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.
|
||||||
|
|
||||||
729
Sim04/metadataops.c
Normal file
729
Sim04/metadataops.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
207
Sim04/metadataops.h
Normal file
207
Sim04/metadataops.h
Normal file
|
|
@ -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
|
||||||
BIN
Sim04/sim04
Executable file
BIN
Sim04/sim04
Executable file
Binary file not shown.
32
Sim04/sim04_mf
Normal file
32
Sim04/sim04_mf
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
CC = gcc -Wall -std=c99 -pedantic -g
|
||||||
|
SOURCES = StringUtils.c simulator.c metadataops.c configops.c OS_SimDriver.c simtimer.c
|
||||||
|
OBJECTS = OS_SimDriver.o simulator.o metadataops.o configops.o StringUtils.o simtimer.o
|
||||||
|
|
||||||
|
all: Simulator
|
||||||
|
|
||||||
|
Simulator: $(OBJECTS)
|
||||||
|
$(CC) $(OBJECTS) -lpthread -o sim04
|
||||||
|
|
||||||
|
StringUtils.o: StringUtils.c
|
||||||
|
$(CC) -c StringUtils.c -o StringUtils.o
|
||||||
|
|
||||||
|
simulator.o: simulator.c
|
||||||
|
$(CC) -c simulator.c -o simulator.o
|
||||||
|
|
||||||
|
metadataops.o: metadataops.c
|
||||||
|
$(CC) -c metadataops.c -o metadataops.o
|
||||||
|
|
||||||
|
configops.o: configops.c
|
||||||
|
$(CC) -c configops.c -o configops.o
|
||||||
|
|
||||||
|
OS_SimDriver.o: OS_SimDriver.c
|
||||||
|
$(CC) -c OS_SimDriver.c -o OS_SimDriver.o
|
||||||
|
|
||||||
|
simtimer.o: simtimer.c
|
||||||
|
$(CC) -c simtimer.c -o simtimer.o
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJECTS) sim04 sim04.out
|
||||||
|
|
||||||
|
clean_objects:
|
||||||
|
rm -f $(OBJECTS)
|
||||||
270
Sim04/simtimer.c
Normal file
270
Sim04/simtimer.c
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
// Program Information ////////////////////////////////////////////////////////
|
||||||
|
/**
|
||||||
|
* @file SimpleTimer.c
|
||||||
|
*
|
||||||
|
* @brief Implementation file for using a timer with micro-second precision
|
||||||
|
*
|
||||||
|
* @author Michael Leverington
|
||||||
|
*
|
||||||
|
* @details Implements member methods for timing
|
||||||
|
*
|
||||||
|
* @version 3.00 (02 February 2017) Update to simulator timer
|
||||||
|
2.00 (13 January 2017) Update to C language
|
||||||
|
* 1.00 (11 September 2015)
|
||||||
|
*
|
||||||
|
* @Note Requires SimpleTimer.h.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Precompiler directives /////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SIMTIMER_C
|
||||||
|
#define SIMTIMER_C
|
||||||
|
|
||||||
|
// Header files ///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "simtimer.h"
|
||||||
|
|
||||||
|
// Constants /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const char RADIX_POINT = '.';
|
||||||
|
const char SPACED = ' ';
|
||||||
|
|
||||||
|
void *runTimer( void *mSecVoidPtr )
|
||||||
|
{
|
||||||
|
struct timeval startTime, endTime;
|
||||||
|
int startSec, startUSec, endSec, endUSec;
|
||||||
|
int uSecDiff, mSecDiff, secDiff, timeDiff;
|
||||||
|
int *mSecPtr = (int *)mSecVoidPtr;
|
||||||
|
int milliSeconds = *mSecPtr;
|
||||||
|
|
||||||
|
gettimeofday( &startTime, NULL );
|
||||||
|
|
||||||
|
startSec = startTime.tv_sec;
|
||||||
|
startUSec = startTime.tv_usec;
|
||||||
|
|
||||||
|
timeDiff = 0;
|
||||||
|
|
||||||
|
while( timeDiff < milliSeconds )
|
||||||
|
{
|
||||||
|
gettimeofday( &endTime, NULL );
|
||||||
|
|
||||||
|
endSec = endTime.tv_sec;
|
||||||
|
endUSec = endTime.tv_usec;
|
||||||
|
uSecDiff = endUSec - startUSec;
|
||||||
|
|
||||||
|
if( uSecDiff < 0 )
|
||||||
|
{
|
||||||
|
uSecDiff = uSecDiff + 1000000;
|
||||||
|
|
||||||
|
endSec = endSec - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSecDiff = uSecDiff / 1000;
|
||||||
|
secDiff = ( endSec - startSec ) * 1000;
|
||||||
|
timeDiff = secDiff + mSecDiff;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void runTimer(int milliSeconds)
|
||||||
|
// {
|
||||||
|
// struct timeval startTime, endTime;
|
||||||
|
// int startSec, startUSec, endSec, endUSec;
|
||||||
|
// int uSecDiff, mSecDiff, secDiff, timeDiff;
|
||||||
|
|
||||||
|
// gettimeofday(&startTime, NULL);
|
||||||
|
|
||||||
|
// startSec = startTime.tv_sec;
|
||||||
|
// startUSec = startTime.tv_usec;
|
||||||
|
|
||||||
|
// timeDiff = 0;
|
||||||
|
|
||||||
|
// while (timeDiff < milliSeconds)
|
||||||
|
// {
|
||||||
|
// gettimeofday(&endTime, NULL);
|
||||||
|
|
||||||
|
// endSec = endTime.tv_sec;
|
||||||
|
// endUSec = endTime.tv_usec;
|
||||||
|
// uSecDiff = endUSec - startUSec;
|
||||||
|
|
||||||
|
// if (uSecDiff < 0)
|
||||||
|
// {
|
||||||
|
// uSecDiff = uSecDiff + 1000000;
|
||||||
|
|
||||||
|
// endSec = endSec - 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mSecDiff = uSecDiff / 1000;
|
||||||
|
// secDiff = (endSec - startSec) * 1000;
|
||||||
|
// timeDiff = secDiff + mSecDiff;
|
||||||
|
// }
|
||||||
|
// // return NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
double accessTimer( int controlCode, char *timeStr )
|
||||||
|
{
|
||||||
|
static bool running = false;
|
||||||
|
static int startSec = 0, endSec = 0, startUSec = 0, endUSec = 0;
|
||||||
|
static int lapSec = 0, lapUSec = 0;
|
||||||
|
struct timeval startData, lapData, endData;
|
||||||
|
double fpTime = 0.0;
|
||||||
|
|
||||||
|
switch( controlCode )
|
||||||
|
{
|
||||||
|
case ZERO_TIMER:
|
||||||
|
gettimeofday( &startData, NULL );
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
startSec = startData.tv_sec;
|
||||||
|
startUSec = startData.tv_usec;
|
||||||
|
|
||||||
|
fpTime = 0.000000000;
|
||||||
|
lapSec = 0.000000000;
|
||||||
|
lapUSec = 0.000000000;
|
||||||
|
|
||||||
|
timeToString( lapSec, lapUSec, timeStr );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LAP_TIMER:
|
||||||
|
if( running == true )
|
||||||
|
{
|
||||||
|
gettimeofday( &lapData, NULL );
|
||||||
|
|
||||||
|
lapSec = lapData.tv_sec;
|
||||||
|
lapUSec = lapData.tv_usec;
|
||||||
|
|
||||||
|
fpTime = processTime( startSec, lapSec,
|
||||||
|
startUSec, lapUSec, timeStr );
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpTime = 0.000000000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOP_TIMER:
|
||||||
|
if( running == true )
|
||||||
|
{
|
||||||
|
gettimeofday( &endData, NULL );
|
||||||
|
running = false;
|
||||||
|
|
||||||
|
endSec = endData.tv_sec;
|
||||||
|
endUSec = endData.tv_usec;
|
||||||
|
|
||||||
|
fpTime = processTime( startSec, endSec,
|
||||||
|
startUSec, endUSec, timeStr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume timer not running
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpTime = 0.000000000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fpTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
double processTime( double startSec, double endSec,
|
||||||
|
double startUSec, double endUSec, char *timeStr )
|
||||||
|
{
|
||||||
|
double secDiff = endSec - startSec;
|
||||||
|
double uSecDiff = endUSec - startUSec;
|
||||||
|
double fpTime;
|
||||||
|
|
||||||
|
fpTime = (double) secDiff + (double) uSecDiff / 1000000;
|
||||||
|
|
||||||
|
if( uSecDiff < 0 )
|
||||||
|
{
|
||||||
|
uSecDiff = uSecDiff + 1000000;
|
||||||
|
secDiff = secDiff - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeToString( secDiff, uSecDiff, timeStr );
|
||||||
|
|
||||||
|
return fpTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is a bit of a drawn-out function, but it is written
|
||||||
|
to force the time result to always be in the form x.xxxxxxx
|
||||||
|
when printed as a string; this will not always be the case
|
||||||
|
if the time is presented as a floating point number
|
||||||
|
*/
|
||||||
|
void timeToString( int secTime, int uSecTime, char *timeStr )
|
||||||
|
{
|
||||||
|
int low, high, index = 0;
|
||||||
|
char temp;
|
||||||
|
|
||||||
|
while( uSecTime > 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
49
Sim04/simtimer.h
Normal file
49
Sim04/simtimer.h
Normal file
|
|
@ -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 <sys/time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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
|
||||||
|
|
||||||
1293
Sim04/simulator.c
Normal file
1293
Sim04/simulator.c
Normal file
File diff suppressed because it is too large
Load diff
232
Sim04/simulator.h
Normal file
232
Sim04/simulator.h
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
#ifndef SIMULATORX
|
||||||
|
#define SIMULATORX
|
||||||
|
|
||||||
|
#include "StandardConstants.h"
|
||||||
|
#include "configops.h"
|
||||||
|
#include "metadataops.h"
|
||||||
|
#include "simtimer.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// 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 enum{
|
||||||
|
IO_RETURN = 0,
|
||||||
|
QUANTUM_TIMEOUT,
|
||||||
|
CPU_SWITCH,
|
||||||
|
CLEAR_INTERRUPT
|
||||||
|
} INTERRUPT_ROUTINE;
|
||||||
|
|
||||||
|
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, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod);
|
||||||
|
|
||||||
|
/*
|
||||||
|
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, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod);
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif // SIMULATORX
|
||||||
86
Sim04/testfile-dnw.mdf
Normal file
86
Sim04/testfile-dnw.mdf
Normal file
|
|
@ -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.
|
||||||
|
|
||||||
12
Sim04/testfile.cnf
Normal file
12
Sim04/testfile.cnf
Normal file
|
|
@ -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.
|
||||||
40
Sim04/testfile.mdf
Normal file
40
Sim04/testfile.mdf
Normal file
|
|
@ -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.
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue