skip to content
==> include/mesh/abi/words.h <==
1/* @ajax/mesh-abi-words: Word and byte access to the mailbox at mailbox offsets: the interface pipes run over.
2 *
3 * Part of alpha-c-mesh, a C port of alpha-rust-mesh (README.md says from where). */
4#ifndef MESH_ABI_WORDS_H
5#define MESH_ABI_WORDS_H
6
7#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10#include <stdatomic.h>
11
12/* Word access to the mailbox, at mailbox offsets (every runtime maps the
13 * offsets to its own addresses): Rust's `Words` trait (and `Bytes`, its byte
14 * copies for the host runtimes), as a table of functions over a context.
15 * A GPU runtime fills it with its own atomics; static inline callers given a
16 * constant table are devirtualised by the compiler. */
17typedef struct mesh_words {
18    void *ctx;
19    uint32_t (*load_acquire)(void *ctx, size_t a);
20    void (*store_release)(void *ctx, size_t a, uint32_t v);
21    /* Returns the old value. */
22    uint32_t (*cas)(void *ctx, size_t a, uint32_t cmp, uint32_t desired);
23    /* Returns the old value. */
24    uint32_t (*add)(void *ctx, size_t a, uint32_t v);
25    /* A sequentially consistent fence (a store before it is ordered before a
26     * load after it). NULL: atomic_thread_fence(memory_order_seq_cst). */
27    void (*fence)(void *ctx);
28    /* Bytes: copies for the host runtimes (wasm lanes, native workers); a GPU
29     * warp copies with all its lanes between reserve and commit instead. NULL
30     * where only words are used. */
31    void (*read)(void *ctx, size_t a, uint8_t *out, size_t n);
32    void (*write)(void *ctx, size_t a, const uint8_t *b, size_t n);
33} mesh_words;
34
35static inline uint32_t mesh_words_load(const mesh_words *w, size_t a) { return w->load_acquire(w->ctx, a); }
36static inline void mesh_words_store(const mesh_words *w, size_t a, uint32_t v) { w->store_release(w->ctx, a, v); }
37static inline uint32_t mesh_words_cas(const mesh_words *w, size_t a, uint32_t cmp, uint32_t desired) {
38    return w->cas(w->ctx, a, cmp, desired);
39}
40static inline uint32_t mesh_words_add(const mesh_words *w, size_t a, uint32_t v) { return w->add(w->ctx, a, v); }
41static inline void mesh_words_fence(const mesh_words *w) {
42    if (w->fence) w->fence(w->ctx);
43    else atomic_thread_fence(memory_order_seq_cst);
44}
45static inline void mesh_words_read(const mesh_words *w, size_t a, uint8_t *out, size_t n) { w->read(w->ctx, a, out, n); }
46static inline void mesh_words_write(const mesh_words *w, size_t a, const uint8_t *b, size_t n) { w->write(w->ctx, a, b, n); }
47
48#endif