-
Notifications
You must be signed in to change notification settings - Fork 89
Toolchain conventions and context.get
#485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Can we use thread-local storage (as implemented by e.g. LLVM) as a guiding precedent here? I.e. can we teach LLVM to manage task-local storage using an analogous mechanism to how it does thread-local storage and build abstractions on top of that for |
That'd help keep, in the example above, A/B's state separate for exports yeah. That wouldn't solve C's problem though where C may not be in control of exports but it still wants to register a waitable in theory. In essence C's problem is "ok root of whatever async computation I'm in, add this thing to your waitable set and re-poll me when it's ready". That's out of the scope of data storage and more about runtime semantics. There'll be other management intrinsics as well such as removing waitables, etc. |
Yeah, it seems analogous to the challenge of writing runtime-agnostic async libraries in Rust; in absence of a stable, "official" abstraction which runtimes can implement and libraries can target, you end up having to "pick one and stick with it" and then hope nobody tries to compose your library with another one that picked a different runtime (or different major version of the same runtime). Given that |
I think that's what I'm concluding as well though. Ideally though something really really small is all that goes in wasi-libc, all of Trying to think this through, what I think we sort of want is something like: struct cm32p3_task {
// theoretical future-compat? (e.g. v2 means more fields for some future
// definition of this structure).
int version;
// passed to callbacks below
void *ptr;
// For the current exported task, register `callback(ptr)` to happen when `waitable`
// gets signaled. Basically add `waitable` to a waitable set and arrange for the
// callback to get invoked when the current exported task gets the notification
// the waitable is ready.
//
// If already registered this removes the previous callback.
//
// TODO: how to manage the lifetime of `callback` and `ptr`? Second function
// for dtor? Unsure.
void (*waitable_register)(void *cm32p3_task_ptr, uint32_t waitable, void(*callback)(void*), void *ptr);
// Dual of the above, but removes it from the waitable set and/or tracking.
void (*waitable_unregister)(void *cm32p3_task_ptr, uint32_t waitable);
};
// Set the current task (runtimes call this when an async task is entered)
//
// Basically sets some global to this value.
void cm32p3_task_set(struct cm32p3_task *task);
// Get the current task (runtimes call this when a new waitable is being
// registered, such as when an async import blocked).
struct cm32p3_task *cm32p3_task_get(void); or... something along those lines. |
Ok thinking through this some more. Here's what I'd like to propose: The
|
cc @vados-cosmonic from our discussion this morning too |
SGTM. I like the idea of starting with this in |
This commit is an implementation of a solution for WebAssembly/component-model#485 for Rust. This should enable releasing multiple versions of `wit-bindgen` into the wild and have them all work together for now. Integration with `wasi-libc` will come in the future in theory.
* Implement a C ABI for async import/export communication This commit is an implementation of a solution for WebAssembly/component-model#485 for Rust. This should enable releasing multiple versions of `wit-bindgen` into the wild and have them all work together for now. Integration with `wasi-libc` will come in the future in theory. * Refactor with separate objects Try to work around symbol/export trickery * Update crates/guest-rust/rt/src/async_support/waitable.rs Co-authored-by: Joel Dice <[email protected]> * Update wasi-sdk in CI * Review comments * Get crate compiling on native --------- Co-authored-by: Joel Dice <[email protected]>
Currently in
wit-bindgen
it usescontext.get
to store a per-exported-task data structure which manages waitable sets and and child tasks from Rust's perspectives (not component-model tasks, Rust tasks). This is not going to work, however, once there are multiple versions ofwit-bindgen
in the ecosystem with async bindings. For example within a component there could be multiple versions ofwit-bindgen
:0.A.0
: used for one export0.B.0
: used for one export0.C.0
: used for some importsIn these situations the per-task data structure may not be the same across versions
A
,B
, andC
, and naively usingcontext.get
is going to lead everyone to sharing the same pointer but silently corrupting data at runtime as the data structures change.I don't have a great idea of a solution yet, but it feels like this is going to lie somewhere in the realm of tooling conventions rather than the component model itself. What exactly such a convention is, though, I'm not sure.
The text was updated successfully, but these errors were encountered: