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