I just need someone to compile this code and give me the screen shot
#define ENABLE_COMMANDER
#define ENABLE_REPORTER
#include <cctype> // for toupper()
#include <cstdlib> // for EXIT_SUCCESS and EXIT_FAILURE
#include <cstring> // for strerror()
#include <cerrno> // for errno
#include <deque> // for deque (used for ready and blocked queues)
#include <fstream> // for ifstream (used for reading simulated process programs)
#include <iostream> // for cout, endl, and cin
#include <sstream> // for stringstream (for parsing simulated process programs)
#include <sys/wait.h> // for wait()
#include <unistd.h> // for pipe(), read(), write(), close(), fork(), and _exit()
#include <vector> // for vector (used for PCB table)
using namespace std;
class Instruction {
public:
char operation;
int intArg;
string stringArg;
};
class Cpu {
public:
vector<Instruction> *pProgram;
int programCounter;
int value;
int timeSlice;
int timeSliceUsed;
};
enum State {
STATE_READY,
STATE_RUNNING,
STATE_BLOCKED,
STATE_END
};
class PcbEntry {
public:
int processId;
int parentProcessId;
vector<Instruction> program;
unsigned int programCounter;
int value;
unsigned int priority;
State state;
unsigned int startTime;
unsigned int timeUsed;
};
// The number of valid priorities.
#define NUM_PRIORITIES 4
// An array that maps priorities to their allotted time slices.
static const unsigned int PRIORITY_TIME_SLICES[NUM_PRIORITIES] = {
1,
2,
4,
8
};
unsigned int timestamp = 0;
Cpu cpu;
// For the states below, -1 indicates empty (since it is an invalid index).
int runningState = -1; // The index of the running process in the PCB table.
// readyStates is an array of queues. Each queue holds PCB indices for ready processes
// of a particular priority.
deque<int> readyStates[NUM_PRIORITIES];
deque<int> blockedState; // A queue fo PCB indices for blocked processes.
deque<int> deadState;
// In this implementation, we'll never explicitly clear PCB entries and the
// index in the table will always be the process ID. These choices waste memory,
// but since this program is just a simulation it the easiest approach.
// Additionally, debugging is simpler since table slots and process IDs are
// never re-used.
vector<PcbEntry *> pcbTable;
double cumulativeTimeDiff = 0;
int numTerminatedProcesses = 0;
// Sadly, C++ has no built-in way to trim strings:
string &trim(string &argument)
{
string whitespace(" \t\n\v\f\r");
size_t found = argument.find_last_not_of(whitespace);
if (found != string::npos) {
argument.erase(found + 1);
argument.erase(0, argument.find_first_not_of(whitespace));
} else {
argument.clear(); // all whitespace
}
return argument;
}
bool createProgram(const string &filename, vector<Instruction> &program)
{
ifstream file;
int lineNum = 0;
program.clear();
file.open(filename.c_str());
if (!file.is_open()) {
cout << "Error opening file " << filename << endl;
return false;
}
while (file.good()) {
string line;
getline(file, line);
trim(line);
if (line.size() > 0) {
Instruction instruction;
instruction.operation = toupper(line[0]);
instruction.stringArg = trim(line.erase(0, 1));
stringstream argStream(instruction.stringArg);
switch (instruction.operation) {
case 'S': // Integer argument.
case 'A': // Integer argument.
case 'D': // Integer argument.
case 'F': // Integer argument.
if (!(argStream >> instruction.intArg)) {
cout << filename << ":" << lineNum
<< " - Invalid integer argument "
<< instruction.stringArg << " for "
<< instruction.operation << " operation" << endl;
file.close();
return false;
}
break;
case 'B': // No argument.
case 'E': // No argument.
break;
case 'R': // String argument.
// Note that since the string is trimmed on both ends,
// filenames with leading or trailing whitespace (unlikely)
// will not work.
if (instruction.stringArg.size() == 0) {
cout << filename << ":" << lineNum
<< " - Missing string argument" << endl;
file.close();
return false;
}
break;
default:
cout << filename << ":" << lineNum
<< " - Invalid operation, " << instruction.operation
<< endl;
file.close();
return false;
}
program.push_back(instruction);
}
lineNum++;
}
file.close();
return true;
}
// Implements the S operation.
void set(int value)
{
cpu.value = value;
cout << "Set CPU value to " << value << endl;
}
// Implements the A operation.
void add(int value)
{
cpu.value += value;
cout << "Incremented CPU value by " << value << endl;
}
// Implements the D operation.
void decrement(int value)
{
cpu.value -= value;
cout << "Decremented CPU value by " << value << endl;
}
// Performs scheduling.
void schedule()
{
// TODO: Debug and test
//If runningState != -1 AND the cpu.timeSliceUsed equals or exceeds
// cpu.timeSlice:
cout <<" cpu timeslice Used " << cpu.timeSliceUsed<<endl;
cout <<" cpu timeslice " << cpu.timeSlice<<endl;
if ((runningState != -1) && (cpu.timeSliceUsed >= cpu.timeSlice)){
// 1. Get the PCB entry for runningState.
PcbEntry *myPCB = pcbTable[runningState];
// 2. Lower the process priority (remember since the highest priority is zero,
// you actually have to increment the priority to lower it). Also make sure to
// not increment the priority past its maximum value.
if (myPCB->priority >= 0 && myPCB->priority < (NUM_PRIORITIES - 1)) myPCB->priority++;
// 3. Push runningState on to the end of the correct readyStates queue (hint: use
// pcbEntry.priority to select the correct queue.
switch (myPCB->priority)
{
case 0 :
readyStates[0].push_back(runningState);
break;
case 1 :
readyStates[1].push_back(runningState);
break;
case 2 :
readyStates[2].push_back(runningState);
break;
case 3 :
readyStates[3].push_back(runningState);
break;
default:
cout << "Invalid running state" << endl;
break;
}
// 4. Update the pcbEntry:
// a. Set state to STATE_READY.
// b. Set the programCounter to cpu.programCounter.
// c. Set the value to cpu.value.
// d. Increment timeUsed by cpu.timeSliceUsed.
myPCB->state = STATE_READY;
myPCB->programCounter = cpu.programCounter;
myPCB->value = cpu.value;
myPCB->timeUsed = myPCB->timeUsed + cpu.timeSliceUsed;
cout << " time this process has used = " << myPCB->timeUsed << endl;
cout << " scheduler is ending process and decreasing priority to "<< myPCB->priority <<"\n" << endl;
// 5. Set runningState to -1.
runningState = -1;
}
if (runningState != -1) {//the correct priority program is running
cout << " correct process is running exiting scheduler" << endl;
return;
}
cout << " loading new process from ";
// TODO: Debug and test
// Get a new process to run, if possible, from the ready queue in
// priority order. Remember that the highest priority is zero! The code below
// needs to be updated/replaced since right now it only uses the highest priority
// queue.
if(!readyStates[0].empty()){
runningState = readyStates[0].front();
cout << "priority 0 " << endl;
readyStates[0].pop_front();
}
else if(!readyStates[1].empty()){
runningState = readyStates[1].front();
cout << "priority 1" << endl;
readyStates[1].pop_front();
}
else if(!readyStates[2].empty()){
runningState = readyStates[2].front();
cout << "priority 2 " << endl;
readyStates[2].pop_front();
}
else if(!readyStates[3].empty()){
runningState = readyStates[3].front();
cout << "priority 3 " << endl;
readyStates[3].pop_front();
}
else cout << "ERROR ready state has invalid state entries";
// Make sure there is a process to run.
if (runningState != -1) {
// Mark the process as running.
PcbEntry *pcbEntry = pcbTable[runningState];
pcbEntry->state = STATE_RUNNING;
// Update the CPU with new PCB entry details.
cpu.pProgram = &pcbEntry->program;
cpu.programCounter = pcbEntry->programCounter;
cpu.value = pcbEntry->value;
// TODO: Debug and test
// Set cpu.timeSlice to the correct value (hint: use the
// global PRIORITY_TIME_SLICES array and pcbEntry->priority)
switch (pcbEntry->priority)
{
case 0 :
cpu.timeSlice = PRIORITY_TIME_SLICES[0];
cout << " setting cpu.timeslice to 1"<<endl;
break;
case 1 :
cpu.timeSlice = PRIORITY_TIME_SLICES[1];
cout << " setting cpu.timeslice to 2"<<endl;
break;
case 2 :
cpu.timeSlice = PRIORITY_TIME_SLICES[2];
cout << " setting cpu.timeslice to 4"<<endl;
break;
case 3 :
cpu.timeSlice = PRIORITY_TIME_SLICES[3];
cout << " setting cpu.timeslice to 8"<<endl;
break;
default:
cout << "ERROR setting cpu timeslice Invalid priority" << endl;
break;
}
// TODO: Debug and test
// Set cpu->timeSliceUsed to zero.
cpu.timeSliceUsed = 0;
cout << "Process running, pid = " << pcbEntry->processId << endl;
}
}
// Implements the B operation.
void block()
{
PcbEntry *pcbEntry = pcbTable[runningState];
//TODO there is a problem with pcb time used counter will this fix it
pcbEntry->timeUsed += cpu.timeSliceUsed + 1;//add 1 for CPU time to block the process
// TODO: Debug and test
// Raise the process priority (remember since the highest priority is zero,
// you actually have to decrement the priority to raise it). Also make sure to
// not decrement the priority below zero.
if (pcbEntry->priority > 0) pcbEntry->priority--;
blockedState.push_back(runningState);
pcbEntry->state = STATE_BLOCKED;
pcbEntry->programCounter = cpu.programCounter;
pcbEntry->value = cpu.value;
runningState = -1;
cout << "Blocked process, pid = " << pcbEntry->processId << endl;
}
// Implements the E operation.
void end()
{
PcbEntry *pcbEntry = pcbTable[runningState];
//TODO there is a problem with pcb timused will this fix it?
pcbEntry->timeUsed = pcbEntry->timeUsed + cpu.timeSliceUsed + 1;//add 1 to account for e operation
// Add 1 to account for the time to execute the E operation.
cumulativeTimeDiff += (double)(timestamp + 1 - pcbEntry->startTime);
numTerminatedProcesses++;
cout << "Ended process, pid = " << pcbEntry->processId << endl;
pcbEntry->state = STATE_END;
deadState.push_back(runningState);
runningState = -1;
}
// Implements the F operation.
void fork(int value)
{
int pcbIndex = (int)pcbTable.size();
PcbEntry *runningPcbEntry = pcbTable[runningState];
PcbEntry *pcbEntry = new PcbEntry();
pcbEntry->processId = pcbIndex;
pcbEntry->parentProcessId = runningPcbEntry->processId;
pcbEntry->program = runningPcbEntry->program;
pcbEntry->programCounter = cpu.programCounter;
pcbEntry->value = cpu.value;
pcbEntry->priority = runningPcbEntry->priority;
pcbEntry->state = STATE_READY;
pcbEntry->startTime = timestamp + 1;
pcbEntry->timeUsed = 0;
pcbTable.push_back(pcbEntry);
// TODO: debug and test
//Update the line below to use the correct readyStates queue.
readyStates[pcbEntry->priority].push_back(pcbIndex);
cout << "Forked new process, pid = " << pcbEntry->processId << endl;
if ((value < 0) ||
(cpu.programCounter + value >= (int)cpu.pProgram->size())) {
cout << "Error executing F operation, ending parent process" << endl;
end();
}
cpu.programCounter += value;
}
// Implements the R operation.
void replace(string &argument)
{
if (!createProgram(argument, *cpu.pProgram)) {
cout << "Error executing R operation, ending process" << endl;
end();
return;
}
cpu.programCounter = 0;
cout << "Replaced process with " << argument << ", pid = "
<< pcbTable[runningState]->processId << endl;
}
// Implements the Q command.
void quantum()
{
Instruction instruction;
if (runningState == -1) {
cout << "No processes are running" << endl;
++timestamp;
return;
}
if (cpu.programCounter < (int)cpu.pProgram->size()) {
instruction = (*cpu.pProgram)[cpu.programCounter];
cpu.programCounter++;
} else {
cout << "End of program reached without E operation" << endl;
instruction.operation = 'E';
}
switch (instruction.operation) {
case 'S':
set(instruction.intArg);
break;
case 'A':
add(instruction.intArg);
break;
case 'D':
decrement(instruction.intArg);
break;
case 'B':
block();
break;
case 'E':
end();
break;
case 'F':
fork(instruction.intArg);
break;
case 'R':
replace(instruction.stringArg);
break;
}
timestamp++;
// TODO: degug and test
// Increment cpu.timeSliceUsed.
cpu.timeSliceUsed++;
schedule();
}
// Implements the U command.
void unblock()
{
if (!blockedState.empty()) {
int pcbIndex = blockedState.front();
PcbEntry *pcbEntry = pcbTable[pcbIndex];
blockedState.pop_front();
// TODO: debug and test. PHIL << "this process does not increment the timeStamp, because it comes from Commander?"
// Update the line below to use the correct readyStates queue.
readyStates[pcbEntry->priority].push_back(pcbIndex);
pcbEntry->state = STATE_READY;
cout << "Unblocked process, pid = " << pcbEntry->processId << endl;
}
schedule();
}
void printReadyQue(int *myArray){
for (unsigned int j = 0; j < NUM_PRIORITIES; j++){
if (!readyStates[j].empty()){
cout << "READY STATE PRIORITY " << j << " QUEUE:\n pid | ppid | priority | value | start time | cpu time used |" << endl;
for (unsigned int i = 0; i < readyStates[j].size(); i++) {
int pcbIndex = readyStates[j][i];
PcbEntry *pcbEntry = pcbTable[pcbIndex];
printf("% *d % *d % *d % *d % *d % *d \n" , 7 , pcbEntry->processId , 11, pcbEntry->parentProcessId, 10, pcbEntry->priority,
10, pcbEntry->value, 10, pcbEntry->startTime, 10, pcbEntry->timeUsed);
myArray[j] = myArray[j]+1;//increment prioriety
myArray[4] += pcbEntry->timeUsed;//sum
}
}
}
}
void printProcess(int *myArray){
int myTimeUsed = 0;
const int NUM_STATE = 4;
State myState[NUM_STATE] = {STATE_READY , STATE_RUNNING, STATE_BLOCKED, STATE_END};
for (int j =1; j < NUM_STATE; j++){
switch (j) {
case 1:
cout << "RUNNING PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl;
break;
case 2:
if (!blockedState.empty())
cout << "BLOCKED PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl;
break;
case 3:
if (!deadState.empty())
cout << "DEAD PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl;
break;
default:
cout << "ERROR!!!!!";
break;
}
for(unsigned int readyEntry = 0; readyEntry < pcbTable.size(); readyEntry++){
if (pcbTable[readyEntry]->state == myState[j] ){
if (pcbTable[readyEntry]->state == STATE_RUNNING)myTimeUsed = pcbTable[runningState]->timeUsed+cpu.timeSliceUsed;
else myTimeUsed = pcbTable[readyEntry]->timeUsed;
printf("% *d % *d % *d % *d % *d % *d \n" , 7 , pcbTable[readyEntry]->processId , 11, pcbTable[readyEntry]->parentProcessId, 10, pcbTable[readyEntry]->priority,
10, pcbTable[readyEntry]->value, 10, pcbTable[readyEntry]->startTime, 10, myTimeUsed);
myArray[pcbTable[readyEntry]->priority]++;//increment prioriety
myArray[4] += myTimeUsed;
}
}
}
}
void printPriorieties(int *prioritieList){
cout << endl;
for (int i =0; i<4; i++){
if ( prioritieList[i] != 0)
cout << "number of processes with priority "<< i << " is: " << prioritieList[i] << endl;
}
if ((int)timestamp == prioritieList[4]) cout << "\nCURRENT TIME: " << timestamp << " = " << "total CPU TIME USED: "<< prioritieList[4] << endl;
else cout << "PCB total time does not match this can only happen if no process was running" << endl;
}
// Implements the P command.
void print()
{
#ifdef ENABLE_REPORTER
pid_t pid;
pid = fork();
if (pid == -1) {
cout << "fork:" << strerror(errno) << endl;
return;
}
if (pid != 0) {
// Wait for the reporter process to exit.
wait(NULL);
return;
}
#endif
#ifdef ENABLE_REPORTER
// TODO: debug and test
//Implement all of the printing logic.
int prioritieList[NUM_PRIORITIES + 1] = {0,0,0,0,0};//+ one for sum[4] counter
cout << "\n----------------------------------------------------------------------" << endl;
//cout << "CURRENT TIME: " << timestamp<< endl;
printReadyQue(prioritieList);//prints the processes in ready state by que
printProcess(prioritieList);// prints the rest of the processes
printPriorieties(prioritieList);
cout << "----------------------------------------------------------------------\n"<<endl;
_exit(EXIT_SUCCESS);
#endif
}
// Function that implements the process manager.
int runProcessManager(int fileDescriptor)
{
PcbEntry *pcbEntry = new PcbEntry();
// Attempt to create the init process.
if (!createProgram("/home/philwilliammee/eclipseworkspace/CDT/ilab3/src/init" , pcbEntry->program)) {
delete pcbEntry;
return EXIT_FAILURE;
}
pcbEntry->processId = (int)pcbTable.size();
pcbEntry->parentProcessId = -1;
pcbEntry->programCounter = 0;
pcbEntry->value = 0;
pcbEntry->priority = 0;
pcbEntry->state = STATE_RUNNING;
pcbEntry->startTime = 0;
pcbEntry->timeUsed = 0;
pcbTable.push_back(pcbEntry);
runningState = pcbEntry->processId;
cout << "Running init process, pid = " << pcbEntry->processId << endl;
cpu.pProgram = &(pcbEntry->program);
cpu.programCounter = pcbEntry->programCounter;
cpu.value = pcbEntry->value;
timestamp = 0;
double avgTurnaroundTime = 0;
// Loop until a 'T' is read, then terminate.
char ch;
do {
// Read a command character from the pipe.
if (read(fileDescriptor, &ch, sizeof(ch)) != sizeof(ch)) {
// Assume the parent process exited, breaking the pipe.
break;
}
// Ignore whitespace characters.
if (isspace(ch)) {
continue;
}
// Convert commands to a common case so both lower and uppercase
// commands can be used.
ch = toupper(ch);
switch (ch) {
case 'Q':
quantum();
break;
case 'U':
unblock();
break;
case 'P':
print();
break;
case 'T':
if (numTerminatedProcesses != 0) {
avgTurnaroundTime = cumulativeTimeDiff
/ (double)numTerminatedProcesses;
}
cout << "The average turnaround time is " << avgTurnaroundTime
<< "." << endl;
break;
default:
cout << "Unknown command, " << ch << endl;
break;
}
} while (ch != 'T');
// Cleanup any remaining PCB entries.
for (vector<PcbEntry *>::iterator it = pcbTable.begin();
it != pcbTable.end(); it++) {
delete *it;
}
pcbTable.clear();
return EXIT_SUCCESS;
}
// Main function that implements the commander.
int main(int argc, char *argv[])
{
#ifdef ENABLE_COMMANDER
int pipeDescriptors[2];
pid_t processMgrPid;
char ch;
int result;
// Create a pipe.
if (pipe(pipeDescriptors) == -1) {
// Print an error message to help debugging.
cout << "pipe: " << strerror(errno) << endl;
return EXIT_FAILURE;
}
// Create the process manager process.
processMgrPid = fork();
if (processMgrPid == -1) {
// Print an error message to help debugging.
cout << "fork: " << strerror(errno) << endl;
return EXIT_FAILURE;
}
if (processMgrPid == 0) {
// The process manager process is running.
// Close the unused write end of the pipe for the process manager
// process.
close(pipeDescriptors[1]);
// Run the process manager.
result = runProcessManager(pipeDescriptors[0]);
// Close the read end of the pipe for the process manager process (for
// cleanup purposes).
close(pipeDescriptors[0]);
_exit(result);
} else {
// The commander process is running.
// Close the unused read end of the pipe for the commander process.
close(pipeDescriptors[0]);
// Loop until a 'T' is written or until the pipe is broken.
do {
sleep(1);
cout << "Input a command: ";
// Read a command character from the standard input.
cin >> ch;
cout << endl;
// Pass commands to the process manager process via the pipe.
if (write(pipeDescriptors[1], &ch, sizeof(ch)) != sizeof(ch)) {
// Assume the child process exited, breaking the pipe.
break;
}
} while (ch != 'T');
// Wait for the process manager to exit.
wait(&result);
// Close the write end of the pipe for the commander process (for
// cleanup purposes).
close(pipeDescriptors[1]);
}
return result;
#else
// Run the Process Manager directly.
return runProcessManager(fileno(stdin));
#endif
}