12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788openCore_kernel[@@warning"-D"]openBap.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->schedule{pending;finished=Set.addt.finishednext}|_->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()->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)