#include <fstream> #include <iostream> #include <string> #include <cstdlib> #include "Assembler.h" #include "VirtualMachine.h" #include "OS.h" using namespace std; OS::OS() { //Assembler as; //VirtualMachine vm; string line; fstream assembly, objectCode; fstream in, out, stack; int base=0, limit = 0; system("ls *.s > progs"); fstream program; program.open("progs", ios::in); if (!program.is_open()) { cout << "Couldn't open progs" << endl; exit(1); } getline(program, line); while (!program.eof()) { objectCode.close(); in.close(); out.close(); stack.close(); limit = 0; string assemblyFile = line; int pos = assemblyFile.find("."); if (pos > assemblyFile.length() || assemblyFile.substr(pos) != ".s") { cout << "No .s suffix.\n"; exit(2); } string name = assemblyFile.substr(0, pos); string objectFile = name + ".o"; assembly.open(assemblyFile.c_str(), ios::in); objectCode.open(objectFile.c_str(), ios::out); if (!assembly.is_open() or !objectCode.is_open()) { cout << "Couldn't open " << assemblyFile << " and/or " << objectFile << endl; exit(3); } PCB * p = new PCB(name, base, limit); if (as.assemble(assembly, objectCode)) { cout << "Assembler Error\n"; assembly.close(); objectCode.close(); exit(4); } assembly.close(); objectCode.close(); objectCode.open(objectFile.c_str(), ios::in); if (!objectCode.is_open()) { cout << "Couldn't open " << objectFile << endl; exit(5); } string inFile = name + ".in"; string outFile = name + ".out"; string stFile = name + ".st"; system(string("touch " + stFile).c_str()); p->in.open(inFile.c_str(), ios::in); p->out.open(outFile.c_str(), ios::out); p->stack.open(stFile.c_str(), ios::in | ios::out); if (!p->in.is_open() or !p->out.is_open()) { cout << "Couldn't open " << inFile << " and/or " << outFile << endl; exit(6); } for (p->limit; objectCode >> vm.mem[p->limit + p->base]; p->limit++); base += p->limit + 1; jobs.push_back(p); getline(program, line); } list<PCB *>::iterator it = jobs.begin(); while (it != jobs.end()) { readyQ.push(*it); it++; } } OS::~OS() { cout << "Clock = " << sys_time << endl; PCB *temp; while(!jobs.empty()) { temp = jobs.front(); delete temp; jobs.pop_front(); } delete running; } void OS::run(/*int argc, char *argv[]*/) { while (true) { if(readyQ.empty() && waitQ.empty()) break; contextSwitch(); if(running) { loadState(); vm.run(running->in, running->out, TIME_SLICE); saveState(); } } } // run void OS::loadState() { vm.pc = running->pc; for (int i = 0; i < 4; i++) vm.r[i] = running->r[i]; vm.ir = running->ir; vm.sr = running->sr; vm.base = running->base; vm.limit = running->limit; vm.sp = running->sp; running->stack.seekg(0, ios::beg); for (int i = vm.sp; i < vm.msize and not running->stack.fail(); i++) running->stack >> vm.mem[i]; } void OS::saveState() { running->pc = vm.pc; for (int i = 0; i < 4; i++) running->r[i] = vm.r[i]; running->ir = vm.ir; running->sr = vm.sr; running->base = vm.base; running->limit = vm.limit; running->sp = vm.sp; running->stack.seekp(0, ios::beg); for (int i = vm.sp; i < vm.msize; i++) running->stack << vm.mem[i] << endl; } void OS::contextSwitch() { if(running) { sys_time += vm.get_clock(); running->cpu_time += vm.get_clock(); } while(true) { if(!waitQ.empty()) { if(waitQ.front()->io_completion <= sys_time) { readyQ.push(waitQ.front()); waitQ.pop(); } } break; } int VMReturnStatus = (vm.sr&0xe0)>>5; if (VMReturnStatus == 0) { /* Time Slice */ readyQ.push(running); } if (VMReturnStatus == 1) { /* Halt Instruction */ } if (VMReturnStatus == 2) { /* Out-of-bound Reference */ } if (VMReturnStatus == 3) { /* Stack Overflow */ } if (VMReturnStatus == 4) { /* Stack Underflow */ } if (VMReturnStatus == 5) { /* Invalid Opcode */ } if (VMReturnStatus == 6) { /* Read Operation */ running->io_completion = running->cpu_time + 27; waitQ.push(running); } if (VMReturnStatus == 7) { /* Write Operation */ running->io_completion = running->cpu_time + 27; waitQ.push(running); } running = NULL; vm.sr = 0; if (!readyQ.empty()) { running = readyQ.front(); readyQ.pop(); } sys_time += 5; // time for context switch }