diff --git a/js/dos/afvm_manager.js b/js/dos/afvm_manager.js new file mode 100644 index 0000000..573b81b --- /dev/null +++ b/js/dos/afvm_manager.js @@ -0,0 +1,222 @@ +/** + * Created by sbosse on 3/6/15. + */ +var Types = require('./afvm_types'); +var Net = require('./network'); +var Que = require('./afvm_queue'); +var Sch = require('./scheduler'); +var Io = require('./io'); +var util = require('util'); +var div = require('./compat').div; + +// delayed binding due to cross referencing +var Vm=undefined; + +var assert = function(condition, message) { + if (!condition) + throw Error("[afvm_manager]" + (typeof message !== "undefined" ? ": " + message : "")); +}; + +var Manager = function(max_proc,max_vm,cf_max) { + var con,i,j; + con=Sch.Context(0,this); + + this.MAX_PROC=max_proc; + // Process table + this.PT=[]; + // Code Frame list table (one for each VM) + this.CQ=[]; + // Token list?? + this.PQ=[]; + + // All attached VMs + this.vms=[]; + // Processing queue + this.tq=new Que.TokenQueue('AM.T'); + // Suspend queue + this.sq=new Que.TokenQueue('AM.S'); + // Wakeup queue + this.wq=new Que.TokenQueue('AM.S'); + this.netout=undefined; + this.context=con; + this.token=undefined; + for(i=0;i=this.MAX_PROC) return undefined; + return this.PT[pi]; +}; + +Manager.prototype.Add = function (obj) +{ + if (obj instanceof Vm.VM) this.vms.push(obj); + else assert (false,'Unknown object '+util.inspect(obj)) +}; + +Manager.prototype.Kill = function (pro) { + console.log('[MANA] Killing agent process '+util.inspect(pro)) +}; + +/* +** State Machine + */ + + +Manager.prototype.init = function (self) { + console.log('[MANA] Init.'); +}; + +Manager.prototype.await = function (self) { + self.token=self.tq.Inq(); + console.log('[MANA] Await. [blocked '+self.context.blocked+' token='+util.inspect(self.token)+']'); +}; + +Manager.prototype.execute = function (self) { + var pro,vm,processor,breakit,id,tw; + console.log('[MANA] Execu.'); + switch (self.token.tk_colour) { + case Types.Token_colour.TK_PRO: + pro = self.PT[self.token.tk_pi]; + processor = self.vms[pro.pro_vm].processor; + if (pro.pro_flag == Types.Process_state.PROC_START) { + pro.pro_flag = Types.Process_state.PROC_RUN; + vm = self.vms[pro.pro_vm]; + vm.tq.Outq(self.token); + } else if (pro.pro_flag == Types.Process_state.PROC_STOP) { + self.Kill(pro); + processor.proc_free(self,pro) + } else if (pro.pro_flag == Types.Process_state.PROC_EXCEPTION) { + self.Kill(pro) + processor.proc_free(self,pro); + } else if (pro.pro_flag == Types.Process_state.PROC_MOVE) { + // pass to network_out manager -- + self.netout.Outq(self.token); + } else if (pro.pro_flag == Types.Process_state.PROC_SUSP) { + self.sq.Outq(self.token); + } else if (pro.pro_flag == Types.Process_state.PROC_AWAIT) { + self.sq.Outq(self.token); + } + break; + + case Types.Token_colour.TK_TS_EVENT: + /* + ** filter out all suspended processes + ** waiting for the event (t.tk_pi) + */ + id = -1; + breakit = self.sq.Emptyq(); + while (!breakit) { + tw = self.sq.Inq(); + if (id == -1) id = tw.tk_pi; + else if (id == tw.tk_pi) { + self.sq.Outq(tw); + breakit = true; + } + if (!breakit) { + pro = self.PT[tw.tk_pi]; + if (pro.pro_await == Types.Process_await.AWAIT_TS && + pro.pro_await_arg == self.token.tk_pi) { + // resume process, restart from scratch -- + if (id == tw.tk_pi) id = -1; + pro.pro_flag = Types.Process_state.PROC_RUN; + pro.pro_await = Types.Process_await.AWAIT_NONE; + pro.pro_await_arg = 0; + pro.pro_ip = 0; + pro.pro_cfcur = pro.pro_cfroot; + vm = self.vms[pro.pro_vm]; + // mon_event(pro,"WAKEUP EVENT PRO="+ToString(pro.pro_id)+" IP="+ToString(pro.pro_ip)+" CF="+ToString(pro.pro_cfcur)); + vm.tq.outq(tw); + } + else self.sq.Outq(tw); + } + breakit = breakit || self.sq.Emptyq(); + } + break; + case Types.Token_colour.TK_WAKEUP: + /* + ** Wakeup request for a process which CAN be suspended and waiting for signal events -- + */ + id = -1; + breakit = self.sq.Emptyq(); + while (!breakit) { + tw = inq(sq); + if (id == -1) id = tw.tk_pi; + else if (id == tw.tk_pi) { + self.sq.Outq(tw); + breakit = true; + } + if (!breakit) { + pro = self.PT[tw.tk_pi]; + if (pro.pro_await == Types.Process_await.AWAIT_SIG) { + // resume process -- + if (id == tw.tk_pi) id = -1; + pro.pro_flag = Types.Process_state.PROC_RUN; + pro.pro_await = Types.Process_await.AWAIT_NONE; + pro.pro_await_arg = 0; + vm = vms[pro.pro_vm]; + // mon_event(pro,"WAKEUP SIG PRO="+ToString(pro.pro_id)+" IP="+ToString(pro.pro_ip)+" CF="+ToString(pro.pro_cfcur)); + vm.tq.Outq(tw); + } else self.sq.Outq(tw); + } + breakit = breakit || self.sq.Emptyq(); + } + break; + } +}; + +Manager.prototype.sleep = function (self) { + console.log('[MANA] Sleep.'); +}; + +Manager.prototype.transitions = function () { + var trans; + trans = + [ + [undefined,this.init,function (self) {return true}], + [this.init,this.await,function (self) {return true}], + [this.await,this.execute,function (self) {return self.context.blocked==false}], + [this.await,this.await,function (self) {return true}], + [this.execute,this.await,function (self) {return true}] + ]; + return trans; +}; + +module.exports = { + Random: function(a,b) { + return div(Math.random()*b+a) + }, + Manager: Manager +}; \ No newline at end of file