Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file primus_exploring_main.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115openCore_kernelopenBap.StdopenMonads.StdopenBap_primus.StdincludeSelf()typet={explored:intTid.Map.t;pending:Primus.Machine.idFqueue.t}letstate=Primus.Machine.State.declare~uuid:"5a863fc2-96cf-4a00-b046-b9b38f95aa11"~name:"exploring-scheduler"(fun_->{pending=Fqueue.empty;explored=Tid.Map.empty;})moduleScheduler(Machine:Primus.Machine.S)=structopenMachine.SyntaxmoduleEval=Primus.Interpreter.Make(Machine)(** [enqueue level state pid] adds [pid] to the list of ids that
will be explored, if the [next|pid] points to an unvisited term, or
to a term that was visited the number of times equal to
[level].
As a side effect will add an unvisited term pointed by [next] (if
any) to the [explored] mapping, with the number of explorations
equal to zero. Also, will leave the machine the state with the
given [pid].
*)letenqueueleveltid=letadd?(level=0)tid={pending=Fqueue.enqueuet.pendingid;explored=Map.sett.explored~key:tid~data:level}inMachine.switchid>>=fun()->Eval.pos>>|Primus.Pos.tid>>|funtid->matchMap.findt.exploredtidwith|None->addtid|Some0->t|Somenwhenn=level->add~leveltid|Some_->tletremove_planned_explorationst={twithexplored=Map.filterit.explored~f:(fun~key~data->data<>0)}letrecreschedulelevelt=Machine.current()>>=funid->Machine.forks()>>=Machine.Seq.fold~init:t~f:(enqueuelevel)>>=funt->Machine.switchid>>=fun()->ifFqueue.is_emptyt.pendingthenreschedule(level+1)telseMachine.return@@remove_planned_explorationstletrecschedulet=matchFqueue.dequeuet.pendingwith|None->reschedule0t>>=schedule|Some(id,pending)->Machine.switchid>>|fun()->{twithpending}letvisitt=Machine.Global.updatestate~f:(funs->{swithexplored=Map.updates.explored(Term.tidt)~f:(function|None->1|Somen->n+1)})letstep_blk=Machine.Global.getstate>>=schedule>>=Machine.Global.putstateletinit()=Machine.List.sequence[Primus.Interpreter.leave_blk>>>step;Primus.Interpreter.leave_blk>>>visit;Primus.Interpreter.leave_sub>>>visit;]endletdesc="The exploring scheduler will prioritize clones that will wonder \
into not yet explored or less explored areas. More specifically, \
from a set of machine clones, it will choose those, that will \
proceed to a basic block that was visited the least amount of \
times. The round-robin scheduler will switch the context after \
each basic block. It will count the number of time the block was \
evaluated"letregisterenabled=ifenabledthenPrimus.Machine.add_component(moduleScheduler)[@warning"-D"];Primus.Components.register_generic"exploring-scheduler"(moduleScheduler)~package:"bap"~desc:("Enables the exploring scheduler (experimental). "^desc)openConfig;;manpage[`S"DESCRIPTION";`Pdesc;];;letenabled=flag"scheduler"~doc:"Enable the scheduler."let()=when_ready(fun{get=(!!)}->register!!enabled)