From Mill Computing Wiki
Jump to: navigation, search

Outcalls are a mechanism by which the Mill program being simulated can cause events in and communicate with the host that is running the simulation. In the conAsm they are indicated by a normal function entry block: 'F("name")' whose body is the outcall pseudo-op with the argument count and result width: 'outcall(3, w)' instead of the conAsm of the function body. The rest of the code can call the outcall normally; the call site is identical to a non-outcall function call.

When that call is executed, the simulator finds a host function of the same name that was linked into the sim when it was built. That is, the function is part of the simulator, and not part of the simulation. The function must have a special signature: it must return a value whose size is the width given in the outcall pseudo in the conAsm; its first argument must be of the simulator type "focus", and the next N arguments must be of the simulator type "outcallArg", where N is the count given in the outcall pseudo in the conAsm. You will find samples in outcalls/include/syscallOutcalls.hh.

The sim calls the function it finds. The "focus" argument describes the state of the simulation at point of call - which process, thread and frame made the outcall, so that the same outcall can be called by different places in the simulation and have different meanings depending on who calls. The outcallArg arguments each refer to the internal simulator data structure that it uses to represent an operand on the belt. There is no support for outcalls with multiple results, nor for those that pass arguments in memory.

Once the simulator calls the outcall function, that function can do whatever it wants. It is running in the simulator (host) environment, so any state that it needs to keep from call to call it must keep in static global state. Using the focus argument it can alter the internal execution of the simulator itself, for example to turn on or off debug tracing of the ongoing simulation. In addition it can execute backcalls back into the (target) simulation. Eventually it will complete, returning its result to the simulator. The simulator packages that (host) result into the data structure representing a (target) operand and adds it to the belt data structure in the same way that the result of a normal call would have been. The whole process permits replacing a normal function with an outcall or vice versa with no other change to the rest of the program.