123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293openCore_kernelopenBap.StdopenMonads.StdopenBap_primus.StdopenFormatincludeSelf()moduleMid=Monad.State.Multi.Idtypet={pending:Mid.tFqueue.t;finished:Mid.Set.t}letstate=Primus.Machine.State.declare~uuid:"d1b33e16-bf5d-48d5-a174-3901dff3d123"~name:"round-robin-scheduler"(fun_->{pending=Fqueue.empty;finished=Mid.Set.empty;})moduleRR(Machine:Primus.Machine.S)=structopenMachine.Syntaxletrecschedulet=matchFqueue.dequeuet.pendingwith|None->Machine.forks()>>|Seq.filter~f:(funid->not(Set.memt.finishedid))>>=funfs->ifSeq.is_emptyfsthenMachine.return()elseschedule{twithpending=Seq.foldfs~init:Fqueue.empty~f:Fqueue.enqueue}|Some(next,pending)->Machine.statusnext>>=function|`Dead->eprintf"Machine %a is dead, skipping over@\n%!"Machine.Id.ppnext;schedule{pending;finished=Set.addt.finishednext}|_->eprintf"Switching to machine %a@\n"Machine.Id.ppnext;Machine.Global.putstate{twithpending}>>=fun()->Machine.switchnext>>=fun()->Machine.Global.getstate>>=scheduleletstep_=Machine.Global.getstate>>=scheduleletfinish()=Machine.current()>>=funid->Machine.Global.updatestate~f:(funt->{twithfinished=Set.addt.finishedid})>>=fun()->eprintf"machine %a is done@\n%!"Machine.Id.ppid;step()letinit()=Machine.sequence[Primus.Interpreter.leave_blk>>>step;Primus.System.fini>>>finish;]endletregisterenabled=ifenabledthenPrimus.Machine.add_component(moduleRR)[@warning"-D"];Primus.Components.register_generic"round-robin-scheduler"(moduleRR)~package:"bap"~desc:"Enables the round-robin scheduler (experimental)."openConfig;;manpage[`S"DESCRIPTION";`P"The round-robin scheduler will try to distribute machine time
equally between competing clones. The state tree will be traversed
in an order that is close to the bread-first search order";`P"The round-robin scheduler will switch the context after each basic block."];;letenabled=flag"scheduler"~doc:"Enable the scheduler."let()=when_ready(fun{get=(!!)}->register!!enabled)