1 /**
2  * D header file to interface with the
3  * $(HTTP pubs.opengroup.org/onlinepubs/9699919799/basedefs/aio.h.html, Posix AIO API).
4  *
5  * Copyright: Copyright D Language Foundation 2018.
6  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Authors:   $(HTTPS github.com/darredevil, Alexandru Razvan Caciulescu)
8  */
9 module core.sys.posix.aio;
10 
11 import core.stdc.config;
12 import core.sys.posix.signal;
13 import core.sys.posix.sys.types;
14 
15 version (OSX)
16     version = Darwin;
17 else version (iOS)
18     version = Darwin;
19 else version (TVOS)
20     version = Darwin;
21 else version (WatchOS)
22     version = Darwin;
23 
24 version (Posix):
25 
26 extern (C):
27 @nogc:
28 nothrow:
29 
30 version (CRuntime_Glibc)
31 {
32     import core.sys.posix.config;
33 
34     struct aiocb
35     {
36         int aio_fildes;
37         int aio_lio_opcode;
38         int aio_reqprio;
39         void* aio_buf;   //volatile
40         size_t aio_nbytes;
41         sigevent aio_sigevent;
42 
43         aiocb* __next_prio;
44         int __abs_prio;
45         int __policy;
46         int __error_code;
47         ssize_t __return_value;
48 
49         off_t aio_offset;
50         ubyte[32] __glibc_reserved;
51     }
52 
53     static if (__USE_LARGEFILE64)
54     {
55         struct aiocb64
56         {
57             int aio_fildes;
58             int aio_lio_opcode;
59             int aio_reqprio;
60             void* aio_buf;   //volatile
61             size_t aio_nbytes;
62             sigevent aio_sigevent;
63 
64             aiocb* __next_prio;
65             int __abs_prio;
66             int __policy;
67             int __error_code;
68             ssize_t __return_value;
69 
70             off_t aio_offset;
71             ubyte[32] __glibc_reserved;
72         }
73     }
74 }
75 else version (CRuntime_Bionic)
76 {
77     // Bionic does not define aiocb.
78 }
79 else version (CRuntime_Musl)
80 {
81     // https://git.musl-libc.org/cgit/musl/tree/include/aio.h
82     struct aiocb
83     {
84         int aio_fildes;
85         int aio_lio_opcode;
86         int aio_reqprio;
87         void* aio_buf;   //volatile
88         size_t aio_nbytes;
89         sigevent aio_sigevent;
90         void* __td;
91         int[2] __lock;
92         int __err;   //volatile
93         ssize_t __ret;
94         off_t aio_offset;
95         void* __next;
96         void* __prev;
97         ubyte[32-2*(void*).sizeof] __dummy4;
98     }
99 }
100 else version (CRuntime_UClibc)
101 {
102     // UClibc does not implement aiocb.
103 }
104 else version (Darwin)
105 {
106     struct aiocb
107     {
108         int aio_filedes;
109         off_t aio_offset;
110         void* aio_buf;   // volatile
111         size_t aio_nbytes;
112         int reqprio;
113         sigevent aio_sigevent;
114         int aio_lio_opcode;
115     }
116 }
117 else version (FreeBSD)
118 {
119     struct __aiocb_private
120     {
121         long status;
122         long error;
123         void* kernelinfo;
124     }
125 
126     struct aiocb
127     {
128         int aio_fildes;
129         off_t aio_offset;
130         void* aio_buf;   // volatile
131         size_t aio_nbytes;
132         private int[2] __spare;
133         private void* _spare2__;
134         int aio_lio_opcode;
135         int aio_reqprio;
136         private __aiocb_private _aiocb_private;
137         sigevent aio_sigevent;
138     }
139 
140     version = BSD_Posix;
141 }
142 else version (NetBSD)
143 {
144     struct aiocb
145     {
146         off_t aio_offset;
147         void* aio_buf;   // volatile
148         size_t aio_nbytes;
149         int aio_fildes;
150         int aio_lio_opcode;
151         int aio_reqprio;
152         sigevent aio_sigevent;
153         private int _state;
154         private int _errno;
155         private ssize_t _retval;
156     }
157 
158     version = BSD_Posix;
159 }
160 else version (OpenBSD)
161 {
162     // OpenBSD does not define aiocb.
163 }
164 else version (DragonFlyBSD)
165 {
166     struct aiocb
167     {
168         int aio_fildes;
169         off_t aio_offset;
170         void* aio_buf;   // volatile
171         size_t aio_nbytes;
172         sigevent aio_sigevent;
173         int aio_lio_opcode;
174         int aio_reqprio;
175         private int _aio_val;
176         private int _aio_err;
177     }
178 
179     version = BSD_Posix;
180 }
181 else version (Solaris)
182 {
183     struct aio_result_t
184     {
185         ssize_t aio_return;
186         int aio_errno;
187     }
188 
189     struct aiocb
190     {
191         int aio_fildes;
192         void* aio_buf;   // volatile
193         size_t aio_nbytes;
194         off_t aio_offset;
195         int aio_reqprio;
196         sigevent aio_sigevent;
197         int aio_lio_opcode;
198         aio_result_t aio_resultp;
199         int aio_state;
200         int[1] aio__pad;
201     }
202 }
203 else
204     static assert(false, "Unsupported platform");
205 
206 /* Return values of cancelation function.  */
207 version (CRuntime_Glibc)
208 {
209     enum
210     {
211         AIO_CANCELED,
212         AIO_NOTCANCELED,
213         AIO_ALLDONE
214     }
215 }
216 else version (CRuntime_Musl)
217 {
218     enum
219     {
220         AIO_CANCELED,
221         AIO_NOTCANCELED,
222         AIO_ALLDONE
223     }
224 }
225 else version (Darwin)
226 {
227     enum
228     {
229         AIO_ALLDONE = 0x1,
230         AIO_CANCELED = 0x2,
231         AIO_NOTCANCELED = 0x4,
232     }
233 }
234 else version (Solaris)
235 {
236     enum
237     {
238         AIO_CANCELED,
239         AIO_ALLDONE,
240         AIO_NOTCANCELED
241     }
242 }
243 else version (BSD_Posix)
244 {
245     enum
246     {
247         AIO_CANCELED,
248         AIO_NOTCANCELED,
249         AIO_ALLDONE
250     }
251 }
252 
253 /* Operation codes for `aio_lio_opcode'.  */
254 version (CRuntime_Glibc)
255 {
256     enum
257     {
258         LIO_READ,
259         LIO_WRITE,
260         LIO_NOP
261     }
262 }
263 else version (CRuntime_Musl)
264 {
265     enum
266     {
267         LIO_READ,
268         LIO_WRITE,
269         LIO_NOP
270     }
271 }
272 else version (Darwin)
273 {
274     enum
275     {
276         LIO_NOP = 0x0,
277         LIO_READ = 0x1,
278         LIO_WRITE = 0x2,
279     }
280 }
281 else version (Solaris)
282 {
283     enum
284     {
285         LIO_NOP,
286         LIO_READ,
287         LIO_WRITE,
288     }
289 }
290 else version (BSD_Posix)
291 {
292     enum
293     {
294         LIO_NOP,
295         LIO_WRITE,
296         LIO_READ
297     }
298 }
299 
300 /* Synchronization options for `lio_listio' function.  */
301 version (CRuntime_Glibc)
302 {
303     enum
304     {
305         LIO_WAIT,
306         LIO_NOWAIT
307     }
308 }
309 else version (CRuntime_Musl)
310 {
311     enum
312     {
313         LIO_WAIT,
314         LIO_NOWAIT
315     }
316 }
317 else version (Darwin)
318 {
319     enum
320     {
321         LIO_NOWAIT = 0x1,
322         LIO_WAIT = 0x2,
323     }
324 }
325 else version (Solaris)
326 {
327     enum
328     {
329         LIO_NOWAIT,
330         LIO_WAIT
331     }
332 }
333 else version (BSD_Posix)
334 {
335     enum
336     {
337         LIO_NOWAIT,
338         LIO_WAIT
339     }
340 }
341 
342 /* Functions implementing POSIX AIO.  */
343 version (CRuntime_Glibc)
344 {
345     static if (__USE_LARGEFILE64)
346     {
347         int aio_read64(aiocb64* aiocbp);
348         int aio_write64(aiocb64* aiocbp);
349         int aio_fsync64(int op, aiocb64* aiocbp);
350         int aio_error64(const(aiocb64)* aiocbp);
351         ssize_t aio_return64(aiocb64* aiocbp);
352         int aio_suspend64(const(aiocb64*)* aiocb_list, int nitems, const(timespec)* timeout);
353         int aio_cancel64(int fd, aiocb64* aiocbp);
354         int lio_listio64(int mode, const(aiocb64*)* aiocb_list, int nitems, sigevent* sevp);
355 
356         alias aio_read = aio_read64;
357         alias aio_write = aio_write64;
358         alias aio_fsync = aio_fsync64;
359         alias aio_error = aio_error64;
360         alias aio_return = aio_return64;
361         alias aio_suspend = aio_suspend64;
362         alias aio_cancel = aio_cancel64;
363         alias lio_listio = lio_listio64;
364     }
365     else
366     {
367         int aio_read(aiocb* aiocbp);
368         int aio_write(aiocb* aiocbp);
369         int aio_fsync(int op, aiocb* aiocbp);
370         int aio_error(const(aiocb)* aiocbp);
371         ssize_t aio_return(aiocb* aiocbp);
372         int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
373         int aio_cancel(int fd, aiocb* aiocbp);
374         int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
375     }
376 }
377 else version (CRuntime_Bionic)
378 {
379     // Bionic does not implement aio.h
380 }
381 else version (CRuntime_UClibc)
382 {
383     // UClibc does not implement aio.h
384 }
385 else version (OpenBSD)
386 {
387     // OpenBSD does not implement aio.h
388 }
389 else
390 {
391     int aio_read(aiocb* aiocbp);
392     int aio_write(aiocb* aiocbp);
393     int aio_fsync(int op, aiocb* aiocbp);
394     int aio_error(const(aiocb)* aiocbp);
395     ssize_t aio_return(aiocb* aiocbp);
396     pragma(mangle, muslRedirTime64Mangle!("aio_suspend", "__aio_suspend_time64"))
397     int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
398     int aio_cancel(int fd, aiocb* aiocbp);
399     int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
400 }
401 
402 /* Functions outside/extending POSIX requirement.  */
403 version (CRuntime_Glibc)
404 {
405     static if (_GNU_SOURCE)
406     {
407         /* To customize the implementation one can use the following struct.  */
408         struct aioinit
409         {
410             int aio_threads;
411             int aio_num;
412             int aio_locks;
413             int aio_usedba;
414             int aio_debug;
415             int aio_numusers;
416             int aio_idle_time;
417             int aio_reserved;
418         }
419 
420         void aio_init(const(aioinit)* init);
421     }
422 }
423 else version (FreeBSD)
424 {
425     int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
426     int aio_mlock(aiocb* aiocbp);
427 }
428 else version (DragonFlyBSD)
429 {
430     int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
431 }