/** * 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 };