Using libfdb in unikernel without preemptive threading

I’m interested in using libfdb in the context of MirageOS, a library operating system for constructing secure, high-perfomance unikernels. The challenge is that MirageOS is fully event-driven, with no support for preemptive threading. This means I cannot construct a thread for running fdb_run_network as instructed in the documentation:

Unless your program is entirely event-driven based on results of asynchronous functions in this API and has no event loop of its own, you will want to invoke this function on an auxiliary thread (which it is your responsibility to create).

I assume both MirageOS and libfdb ultimately end up dispatching to select or epoll, so in a sense, the approaches should be compatible. The question is whether the two event-loops of libfdb and MirageOS can be bridged/consolidated somehow.

Any input on how to achieve this would be greatly appreciated. Thanks in advance! :pray:

My OCaml knowledge is very limited, so I am not sure whether this is possible and if it is, how it would be.

The good news is, that fdb is single threaded and completely event driven. So in theory this would be great. However, libfdb_c (which is the C language bindings) uses a dispatch thread. Therefore, you probably can’t use libfdb_c. Therefore you would need to implement a new flow-aware OCaml binding.

As I see it, there are two ways of achieving what you want:

  1. You can try to execute your OCaml tasks in the context of the flow main loop. I know that this is possible in Python (I did this once some time back as an experiment). This would probably be the preferred way.
  2. You can try to implement a new run_once method in and execute this in the OCaml main loop.

Either solution would require you to program directly against the C++ API or write a new C API. If you program against C++, it will come with all the caveats of linking directly against C++ (but you should be mostly fine as long as you recompile for every version you are going to use).

Sadly, none of these two options can be implemented quickly or eaily…

Thanks for your input @markus.pilman!

Your proposed solutions make sense, though I agree they are probably quite costly to implement. I also considered implementing INetwork specifically for MirageOS, but that seems like a sizeable task as well.

Even if you worked out how to stitch MirageOS and FDB’s event loops together, I suspect you’d also run into trouble with the multi version client library requiring dlopen() support? I imagine you’re missing a dynamic linker as well.

You could use directly use NativeAPI. In that case you wouldn’t be able to use the multiversion client anyways… This would currently mean that you would need to upgrade all clients at the same time you upgrade the servers. If we ever get downwards compatible clients, this would be easier.

The multiversion client also runs through the C bindings and starts a thread for the other version’s event loop, so that would be another obstacle to its use.

Thanks for the input. It sounds quite challenging to pull this off, so I’ll leave it be for now.