-
-
Notifications
You must be signed in to change notification settings - Fork 183
Description
Ok, this is quite a hard one. Now, there's barely any memory protection in EFI (there some fundamental alloc functions for you to write a page allocator IIRC, as seen in the allocator written in this repo) and so everything by default is not "thread-safe".
But worse, we all know that EFI is pretty much running on bare-metal so there's no multi-threading either.
This means we cannot have the true async experience like we do with tokio/async-std that features work stealing from multiple threads. We are set to have the libuv/Node experience where we have one core, multiple promises, aka cooperative scheduling without preemption.
If we are fortunate enough and we have hardware interrupts/polling mechanism, then we can still have some degree of asynchronicity. This is a well-documented practice done by various hardware engineers using Rust on ARM/RISC-V who exploits such features. There's no way we can't do it in EFI.
But the sad reality is, this is not really supported by EFI either, due to EFI being able to target multiple platforms. but I do found some gems on the boot service table:
https://github.com/tianocore/edk2/blob/f1567720b13a578ffa54716119f826df622babcd/MdePkg/Include/Uefi/UefiSpec.h#L1896-L1901
I suppose this is a primitive FCFS event system, i.e. without scheduling, but at least we are saved from the hassle of writing from scratch ourselves.
My idea is shown as follows:
- Call
CreateEventfor eachFutureallocation; on debug mode, tag future and the event primitives to each other for better debugging. (not necessary on release mode, keeping either one is okay) - We store the pointer to the
Futurein each context. - Call
CheckEventon eachpoll - We do not call
WaitForEventfor each await call. Instead we let Rust to handle the polling pending and resend it to the event queue since that's supposed to be the way Rust is. - When
Futurecompletes/fails we can callSignalEvent. - After the future has been consumed/droppable, free the underlying event primitives by
CloseEvent.
This is a very good reference point to write an executor.
Keep in mind that this is only available during boot service, there's no equivalent in runtime service.
Also according to here the EFI_EVENT is an opaque structure, this mean we might not have a consistent behavior on different platforms. Intensive testing should be needed.