Coverage report: /home/ellis/comp/core/ffi/uring/pkg.lisp

KindCoveredAll%
expression135 2.9
branch00nil
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; uring/pkg.lisp --- URING Systems
2
 
3
 ;; /usr/include/liburing.h
4
 
5
 ;;; Commentary:
6
 
7
 ;; IO_URING is our preferred means of IO on Linux. The bindings here
8
 ;; are used by the high-level library IO.
9
 
10
 ;; As a point of reference, we look to the SB-SYS:SERVE-EVENT function
11
 ;; in SBCL. This is an async event loop which dispatches to a backend
12
 ;; based on features. On Linux it will use either poll or select(2),
13
 ;; neither of which are particularly fast.
14
 
15
 ;; Using the bindings provided by this library we will implement an
16
 ;; alternative backend to dispatch to.
17
 
18
 ;; ref: https://kernel.dk/io_uring.pdf
19
 
20
 ;; guide: https://unixism.net/loti/low_level.html
21
 
22
 ;; tokio/io-uring: https://github.com/tokio-rs/io-uring
23
 
24
 #|
25
 
26
 There are two fundamental operations associated with an async
27
 interface: the act of submitting a request, and the event that is
28
 associated with the completion of said request.
29
 
30
 For submitting IO, the application is the producer and the kernel is
31
 the consumer. The opposite is true for completions - here the kernel
32
 produces completion events and the application consumes them.
33
 
34
 Hence, we need a pair of rings to provide an effective communication
35
 channel between an application and the kernel. That pair of rings is
36
 at the core of the new interface, io_uring.
37
 
38
 They are suitably named submission queue (SQ), and completion
39
 queue (CQ), and form the foundation of the new interface.
40
 
41
 |#
42
 ;;; Code:
43
 (defpackage :uring
44
   (:use :cl :std :sb-alien)
45
   (:import-from :sb-posix :file-descriptor :sap-or-nil)
46
   (:shadow :build :build-from)
47
   (:export :load-uring :io-uring-cq :io-uring-cq*
48
    :completion-queue-offsets :completion-queue
49
    :completion-queue-entry :completion-queue-entry-32
50
    :io-uring-sq :io-uring-sq* :submission-queue-offsets :submission-queue
51
    :io-uring-cqe :io-uring-cqe* :io-uring-sqe :io-uring-sqe*
52
    :submission-queue-entry :submission-queue-entry-128
53
    :io-memory-map :parse-io-uring-params :io-params :io-uring
54
    :uring :*default-io-params* :uring-builder :setup-uring-queue
55
    :make-uring-queue :build-submitter :sigset-t :cpu-set-t
56
    :cpu-mask-t :recv-msg-out :cancel-builder :mmapped-region
57
    :with-io-uring :with-new-io-uring :io-uring-get-sqe :io-uring-sqe-set-flags
58
    :with-io-sqe :with-new-io-sqe :with-io-cqe :with-new-io-cqe
59
    :io-uring-prep-rw :io-uring* :make-io-restriction :io-restriction
60
    :io-restriction-p :*default-io-params* :*default-io-entry-count* :io-submitter
61
    :make-io-submitter))
62
    
63
 (in-package :uring)
64
 (define-alien-loader uring "/usr/lib/")
65
 ;; defaults on x86_64
66
 (defconstant +cpu-setsize+ 16) 
67
 (defconstant +sigset-nwords+ 16)
68
 (defconstant +ncpu-bits+ 16)
69
 
70
 (define-alien-type kernel-rwf-t int)
71
 
72
 (define-alien-type io-uring-op unsigned-int)
73
 
74
 (define-alien-type io-uring-restriction-slot2
75
   (union io-uring-restriction-slot2
76
          (register-op unsigned-char)
77
          (sqe-op unsigned-char)
78
          (sqe-flags unsigned-char)))
79
 
80
 (define-alien-type io-uring-restriction
81
   (struct io-uring-restriction
82
           (opcode unsigned-short)
83
           (op-or-flags (union io-uring-restriction-slot2))
84
           (resv unsigned-char)
85
           (resv2 (array unsigned-int 3))))
86
 
87
 (define-alien-type io-uring-buf-ring-resv-and-tail
88
   (struct io-uring-buf-ring-resv-and-tail
89
           (resv1 unsigned-long)
90
           (resv2 unsigned-int)
91
           (resv3 unsigned-short)
92
           (tail unsigned-short)))
93
 
94
 (define-alien-type io-uring-buf-ring-slot1
95
   (union io-uring-buf-ring-slot1
96
          (resv-and-tail io-uring-buf-ring-resv-and-tail)
97
          (bufs (* (struct io-uring-buf)))))
98
 
99
 (define-alien-type io-uring-buf-ring
100
   (struct io-uring-buf-ring
101
           (tail-or-bufs (union io-uring-buf-ring-slot1))))
102
 
103
 (define-alien-type io-uring-sqe-cmd-op-and-pad
104
   (struct io-uring-sqe-cmd-op-and-pad
105
           (cmd-op unsigned-int)
106
           (pad unsigned-int)))
107
 
108
 (define-alien-type io-uring-sqe-slot5
109
   (union io-uring-sqe-slot5
110
          (off unsigned-long)
111
          (addr2 unsigned-long)
112
          (cmd-op-and-pad (struct io-uring-sqe-cmd-op-and-pad))))
113
 
114
 (define-alien-type io-uring-sqe-slot6
115
   (union io-uring-sqe-slot6
116
          (addr unsigned-long)
117
          (splice-off-in unsigned-long)))
118
 
119
 (define-alien-type io-uring-sqe-slot8
120
   (union io-uring-sqe-slot8
121
          (rw-flags kernel-rwf-t)
122
          (fsync-flags unsigned-int)
123
          (poll-events unsigned-short)
124
          (poll32-events unsigned-int)
125
          (sync-range-flags unsigned-int)
126
          (msg-flags unsigned-int)
127
          (timeout-flags unsigned-int)
128
          (accept-flags unsigned-int)
129
          (cancel-flags unsigned-int)
130
          (open-flags unsigned-int)
131
          (statx-flags unsigned-int)
132
          (fadvise-advice unsigned-int)
133
          (splice-flags unsigned-int)
134
          (rename-flags unsigned-int)
135
          (unlink-flags unsigned-int)
136
          (hardlink-flags unsigned-int)
137
          (xattr-flags unsigned-int)
138
          (msg-ring-flags unsigned-int)
139
          (uring-cmd-flags unsigned-int)))
140
          
141
 (define-alien-type io-uring-sqe-slot10
142
   (union io-uring-sqe-slot10
143
          (buf-index unsigned-short)
144
          (buf-group unsigned-short)))
145
 
146
 (define-alien-type io-uring-sqe-addr-len-and-pad
147
   (struct io-uring-sqe-addr-len-and-pad
148
           (addr-len unsigned-short)
149
           (pad3 (array unsigned-short 1))))
150
 
151
 (define-alien-type io-uring-sqe-slot12
152
   (union io-uring-sqe-slot12
153
          (splice-fd-in int)
154
          (file-index unsigned-int)
155
          (addr-len-and-pad (struct io-uring-sqe-addr-len-and-pad))))
156
 
157
 (define-alien-type io-uring-sqe-addr3-and-pad
158
   (struct io-uring-sqe-addr3-and-pad
159
           (addr3 unsigned-long)
160
           (pad2 (array unsigned-long 1))))
161
 
162
 (define-alien-type io-uring-sqe-slot13
163
   (union io-uring-sqe-slot13
164
          (addr3-and-pad (struct io-uring-sqe-addr3-and-pad))
165
          (cmd (array unsigned-char 0))))
166
 
167
 (define-alien-type io-uring-sqe
168
   (struct io-uring-sqe
169
           (opcode unsigned-char)
170
           (flags unsigned-char)
171
           (ioprio unsigned-short)
172
           (fd int)
173
           (off-addr-cmd (union io-uring-sqe-slot5))
174
           (addr-or-splice-off-in (union io-uring-sqe-slot6))
175
           (len unsigned-int)
176
           (flags2 (union io-uring-sqe-slot8))
177
           (user-data unsigned-long)
178
           (buf-opt (union io-uring-sqe-slot10))
179
           (personality unsigned-short)
180
           (splice-index-addr (union io-uring-sqe-slot12))
181
           (addr-or-cmd (union io-uring-sqe-slot13))))
182
           
183
 (define-alien-type io-uring-sqe* (* (struct io-uring-sqe)))
184
 (define-alien-type io-uring-cqe* (* (struct io-uring-cqe)))
185
 
186
 ;; NOTE 2024-05-12: alpha and mips use 535,536,537
187
 (defconstant +nr-io-uring-setup+ 425)
188
 (defconstant +nr-io-uring-enter+ 426)
189
 (defconstant +nr-io-uring-register+ 427)
190
 
191
 (define-alien-type io-uring-sq
192
   (struct io-uring-sq
193
           (khead (* unsigned))
194
           (ktail (* unsigned))
195
           (kring-mask (* unsigned))
196
           (kring-entries (* unsigned))
197
           (kflags (* unsigned))
198
           (kdropped (* unsigned))
199
           (array (* unsigned))
200
           (sqes (* (struct io-uring-sqe)))
201
           (sqe-head unsigned)
202
           (sqe-tail unsigned)
203
           (ring-sz sb-unix:size-t)
204
           (ring-ptr (* t))
205
           (ring-mask unsigned)
206
           (ring-entries unsigned)
207
           (pad (array unsigned 2))))
208
 
209
 (define-alien-type io-uring-sq* (* (struct io-uring-sq)))
210
 
211
 (define-alien-type io-uring-cq
212
   (struct io-uring-cq
213
           (khead (* unsigned))
214
           (ktail (* unsigned))
215
           (kring-mask (* unsigned))
216
           (kring-entries (* unsigned))
217
           (kflags (* unsigned))
218
           (koverflow (* unsigned))
219
           (cqes (* (struct io-uring-cqe)))
220
           (ring-sz sb-unix:size-t)
221
           (ring-ptr (* t))
222
           (ring-mask unsigned)
223
           (ring-entries unsigned)
224
           (pad (array unsigned-int 2))))
225
 
226
 (define-alien-type io-uring-cq* (* (struct io-uring-cq)))
227
 
228
 (define-alien-type io-uring
229
     (struct io-uring
230
             (sq (struct io-uring-sq))
231
             (cq (struct io-uring-cq))
232
             (flags unsigned)
233
             (ring-fd int)
234
             (features unsigned)
235
             (enter-ring-fd int)
236
             (int-flags unsigned-char)
237
             (pad (array unsigned-char 3))
238
             (pad2 unsigned)))
239
 
240
 (define-alien-type io-uring* (* io-uring))
241
 
242
 (define-alien-type io-uring-probe* (* (struct io-uring-probe)))