libxtc
0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_accel.h
1
/*-
2
* Copyright (c) 2026, The XTC Project
3
* @stability experimental
4
* Use of this source code is governed by the ISC License,
5
* a copy of which is in the file LICENSE in the top-level directory
6
* of this distribution.
7
*
8
* src/inc/xtc_accel.h
9
* Attached-compute (GPU / NPU) access -- the FIBER-PARKING BRIDGE
10
* over an async accelerator completion.
11
*
12
* SCOPE, stated up front because it is deliberately narrow. An
13
* accelerator (a discrete/integrated GPU, or an NPU / VPU) is, at
14
* the layer a concurrency runtime cares about, an ASYNC I/O DEVICE:
15
* you submit an opaque command buffer / compiled graph, it runs on
16
* a coprocessor, and it signals completion via a FENCE -- on Linux,
17
* a pollable sync_file / dma-fence fd, exactly the object epoll
18
* already waits on. That is the ONLY thing this module does: it
19
* parks a fiber on such a completion and wakes it when the device
20
* is done, deterministically-testable under the sim backend.
21
*
22
* WHAT THIS MODULE IS NOT, and never becomes:
23
* - NOT a tensor / compute library. It marshals no weights, runs
24
* no kernels, owns no model format.
25
* - NOT a device-memory allocator. Host<->device transfer and
26
* buffer lifetime are the consumer's (or the vendor runtime's).
27
* - NOT a vendor-SDK portability shim. libxtc does NOT link
28
* Level Zero / CUDA / Vulkan / OpenVINO / ONNX. The CONSUMER
29
* links whichever runtime drives the device, does the submit,
30
* and hands us the resulting fence fd (or a blocking closure).
31
* The abstraction stops at the fence. Submission and math live
32
* above us; that boundary is what keeps this a concurrency
33
* primitive and not a decades-deep accelerator-runtime tarpit.
34
*
35
* GPU AND NPU ARE ONE ABSTRACTION HERE. On Linux both are DRM
36
* devices (/dev/dri/renderD* for a render GPU, /dev/accel/accel*
37
* for an NPU via the accel subsystem) whose completions are the
38
* SAME kernel object: a dma-fence exported to a sync_file fd. A
39
* GPU fence fd and an NPU fence fd are indistinguishable to poll(2),
40
* so they are indistinguishable to us. The device KIND
41
* (xtc_accel_kind_t) is a stats/observability tag only, never a
42
* behavioral branch.
43
*
44
* TWO WAYS TO WAIT (pick per submission):
45
* 1. FENCE-FD (preferred, no OS thread held): the consumer's
46
* runtime submits work and returns a completion fence exported
47
* as an fd (Level Zero event/fence -> sync_file,
48
* drmSyncobjExportSyncFile, VK_KHR_external_fence_fd, a CUDA
49
* event bridged to an eventfd, ...). xtc_accel_wait_fence
50
* parks the calling fiber on that fd via the normal loop
51
* readiness path and resumes it when the fence signals.
52
* 2. BLOCKING FALLBACK (a whole OS thread parked for the call):
53
* when a runtime exposes only a synchronous "run and block"
54
* call and no pollable fence, xtc_accel_run_blocking routes it
55
* through the xtc_blocking thread pool -- correct, but holds a
56
* pool thread for the duration, so it suits coarse-grained
57
* inference, not thousands of tiny ops/sec.
58
*
59
* AVAILABILITY. When the build was configured without accelerator
60
* support (XTC_HAVE_ACCEL undefined -- no DRM/accel present, or
61
* --without-accel), the probe reports zero devices and the fence
62
* wait returns XTC_E_NOSYS, following the same "always linkable,
63
* NOSYS when unsupported" convention as the TLS and crypto modules.
64
* xtc_accel_run_blocking works regardless (it needs no device
65
* support -- it just runs the consumer's closure on the pool).
66
*/
67
68
#ifndef XTC_ACCEL_H
69
#define XTC_ACCEL_H
70
71
#include "xtc_export.h"
72
73
#include <stddef.h>
74
#include <stdint.h>
75
76
#include "xtc.h"
77
78
/* Device kind -- an OBSERVABILITY TAG only (see the header comment); it
79
* never changes how a fence is waited on. */
80
typedef
enum
xtc_accel_kind {
81
XTC_ACCEL_KIND_UNKNOWN = 0,
82
XTC_ACCEL_KIND_GPU,
/* render node (/dev/dri/renderD*) */
83
XTC_ACCEL_KIND_NPU
/* accel subsystem (/dev/accel/accel*) */
84
} xtc_accel_kind_t;
85
86
/* One discovered device. `name` is a short human/stat label (e.g.
87
* "renderD128", "accel0"); `node` is the device node path. `driver`
88
* is the kernel driver name if cheaply known (e.g. "xe", "intel_vpu"),
89
* else "". These are for selection/observability by the consumer and
90
* its runtime -- libxtc itself opens none of them. */
91
typedef
struct
xtc_accel_dev {
92
xtc_accel_kind_t kind;
93
char
name[32];
94
char
node[64];
95
char
driver[32];
96
}
xtc_accel_dev_t
;
97
98
/*
99
* PUBLIC: int xtc_accel_probe __P((xtc_accel_dev_t *, int, int *));
100
*
101
* Enumerate accelerator devices present on the host into out[0..max),
102
* writing the total count found to *out_n (which may exceed max if the
103
* buffer was too small -- only the first max are written). Returns
104
* XTC_OK on success (including zero devices), XTC_E_INVAL on a bad
105
* argument. When the build lacks accelerator support this reports
106
* zero devices and returns XTC_OK (there is nothing to enumerate;
107
* absence is not an error). Pure discovery -- opens/submits nothing.
108
*/
109
XTC_API
int
xtc_accel_probe(
xtc_accel_dev_t
*out,
int
max,
int
*out_n);
110
111
/*
112
* PUBLIC: int xtc_accel_wait_fence __P((int, int64_t));
113
*
114
* Park the CALLING FIBER until the completion fence `fence_fd` (a
115
* pollable sync_file / dma-fence / eventfd the consumer's runtime
116
* produced when it submitted work) signals, or `timeout_ns` elapses
117
* (< 0 = wait forever). On the fence signalling, resumes the fiber
118
* and returns XTC_OK. Returns XTC_E_AGAIN on timeout (the fence never
119
* fired), XTC_E_INVAL on a bad fd, XTC_E_NOSYS when the build lacks
120
* accelerator support.
121
*
122
* libxtc does NOT own, dup, or close `fence_fd` -- the caller retains
123
* ownership and closes it after this returns. This must be called
124
* from within a fiber (it parks); calling it off a loop is an error.
125
* It holds NO OS thread while waiting (that is the point vs
126
* run_blocking).
127
*/
128
XTC_API
int
xtc_accel_wait_fence(
int
fence_fd, int64_t timeout_ns);
129
130
/*
131
* PUBLIC: int xtc_accel_run_blocking __P((int (*)(void *), void *, int *));
132
*
133
* Run a synchronous accelerator call `fn(arg)` on the xtc_blocking
134
* thread pool, parking the calling fiber until it returns; the fiber
135
* resumes with fn's return value in *out_result (may be NULL). For
136
* runtimes that expose only a blocking submit-and-wait with no
137
* pollable fence. Returns XTC_OK (fn ran; see *out_result), or the
138
* xtc_blocking error if the work could not be dispatched. Holds one
139
* pool thread for the duration of fn -- prefer xtc_accel_wait_fence
140
* when a fence fd is available. Works regardless of XTC_HAVE_ACCEL
141
* (it needs no device support -- fn is the consumer's own closure).
142
*/
143
XTC_API
int
xtc_accel_run_blocking(
int
(*fn)(
void
*),
void
*arg,
144
int
*out_result);
145
146
#endif
/* XTC_ACCEL_H */
xtc_accel_dev_t
Definition
xtc_accel.h:91
src
inc
xtc_accel.h
Generated by
1.9.8