Skip to content

Interaction with the OS

clarus edited this page Nov 13, 2014 · 8 revisions

We give here the history of the ways we explored to communicate with the OS from Coq.

Free asynchronous messages

At first there was a system to output individual messages, from a given sum type. At each input message, an event handler would be launched.

This system is primitive and could be used to solve any problem in theory. But, in practice, we needed a nice and generic way to handle:

  • the association of an answer with its request, without having to explicitly use a global store remembering what requests were done
  • the ordering of answers (packets from a socket, ...)

System of ids

Each emitted message is given a fresh id. The OS responds to each message by one or many answers. A callback handles the results. Since a callback is a closure, it can contain data: this removes the need of a global store in most cases.

An open question is: how to handle a possibly infinite number of answers per request (like when listening to a socket)?

Fold with a state and a break

The first solution is to have a handler of type:

State -> Input -> M (option State)

The handler reacts to each input. It has a state to remember the previous inputs, if needed. It can return the new state, which will be given with the next input, or None in case it stops listening. So the handler way finish after a finite number of inputs or not.

We show that a program with a finite number of answers per request terminates. This is not obvious a priori: for example, if each handler creates one request, even if there just one answer per request, the program will not terminate.

Finite fold

We may want to enforce the termination of each fold. We can do so with an inductive type, hiding the state in a closure, using this kind of type:

Inductive t (sig : Signature.t) (I : Type) (A : Type) : Type :=
| Stop : t sig I A
| Continue : (I -> Memory.t sig -> t sig I A * Memory.t sig * A) -> t sig I A.

It is then possible to define an eval function by induction on t which will terminate by construction, given a list of inputs and memories. An analogous definition can be made with co-inductive types to represent non-terminating listeners.

But we are not sure yet that the termination is that important to enforce at this level. There are also many other ways to block. For example, a handler expecting two answers for a system call responding only once will not terminate by waiting indefinitely, and this a kind of non-termination the user may want to be protected against.

However, our hope is that more termination will bring simpler specifications, because everything will get a value and trace will be inductive instead of co-inductive. It also removes a whole class of bugs, with looping inputs/outputs.

One answer per request

We need to investigate now this option. The hope is to get a simpler architecture, with explicit termination, at the cost of performances.

Clone this wiki locally