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.sys.posix.signal;
12 import core.sys.posix.sys.types;
13 
14 version (OSX)
15     version = Darwin;
16 else version (iOS)
17     version = Darwin;
18 else version (TVOS)
19     version = Darwin;
20 else version (WatchOS)
21     version = Darwin;
22 
version(Posix)23 version (Posix):
24 
25 extern (C):
26 @system:
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     import core.sys.posix.config;
103     import core.sys.posix.sys.types;
104 
105     struct aiocb
106     {
107         int aio_fildes;
108         int aio_lio_opcode;
109         int aio_reqprio;
110         void* aio_buf;   //volatile
111         size_t aio_nbytes;
112         sigevent aio_sigevent;
113 
114         aiocb* __next_prio;
115         int __abs_prio;
116         int __policy;
117         int __error_code;
118         ssize_t __return_value;
119 
120         static if (__USE_LARGEFILE64)
121         {
122             off_t aio_offset;
123             ubyte[off64_t.sizeof - off_t.sizeof] __pad;
124         }
125         else
126         {
127             off64_t aio_offset;
128         }
129         ubyte[32] __unused;
130     }
131 
132     static if (__USE_LARGEFILE64)
133     {
134         struct aiocb64
135         {
136             int aio_fildes;
137             int aio_lio_opcode;
138             int aio_reqprio;
139             void* aio_buf;   //volatile
140             size_t aio_nbytes;
141             sigevent aio_sigevent;
142 
143             aiocb* __next_prio;
144             int __abs_prio;
145             int __policy;
146             int __error_code;
147             ssize_t __return_value;
148 
149             off64_t aio_offset;
150             ubyte[32] __unused;
151         }
152     }
153 }
154 else version (Darwin)
155 {
156     struct aiocb
157     {
158         int aio_filedes;
159         off_t aio_offset;
160         void* aio_buf;   // volatile
161         size_t aio_nbytes;
162         int reqprio;
163         sigevent aio_sigevent;
164         int aio_lio_opcode;
165     }
166 }
167 else version (FreeBSD)
168 {
169     struct __aiocb_private
170     {
171         long status;
172         long error;
173         void* kernelinfo;
174     }
175 
176     struct aiocb
177     {
178         int aio_fildes;
179         off_t aio_offset;
180         void* aio_buf;   // volatile
181         size_t aio_nbytes;
182         private int[2] __spare;
183         private void* _spare2__;
184         int aio_lio_opcode;
185         int aio_reqprio;
186         private __aiocb_private _aiocb_private;
187         sigevent aio_sigevent;
188     }
189 
190     version = BSD_Posix;
191 }
192 else version (NetBSD)
193 {
194     struct aiocb
195     {
196         off_t aio_offset;
197         void* aio_buf;   // volatile
198         size_t aio_nbytes;
199         int aio_fildes;
200         int aio_lio_opcode;
201         int aio_reqprio;
202         sigevent aio_sigevent;
203         private int _state;
204         private int _errno;
205         private ssize_t _retval;
206     }
207 
208     version = BSD_Posix;
209 }
210 else version (OpenBSD)
211 {
212     // OpenBSD does not define aiocb.
213 }
214 else version (DragonFlyBSD)
215 {
216     struct aiocb
217     {
218         int aio_fildes;
219         off_t aio_offset;
220         void* aio_buf;   // volatile
221         size_t aio_nbytes;
222         sigevent aio_sigevent;
223         int aio_lio_opcode;
224         int aio_reqprio;
225         private int _aio_val;
226         private int _aio_err;
227     }
228 
229     version = BSD_Posix;
230 }
231 else version (Solaris)
232 {
233     struct aio_result_t
234     {
235         ssize_t aio_return;
236         int aio_errno;
237     }
238 
239     struct aiocb
240     {
241         int aio_fildes;
242         void* aio_buf;   // volatile
243         size_t aio_nbytes;
244         off_t aio_offset;
245         int aio_reqprio;
246         sigevent aio_sigevent;
247         int aio_lio_opcode;
248         aio_result_t aio_resultp;
249         int aio_state;
250         int[1] aio__pad;
251     }
252 }
253 else
254     static assert(false, "Unsupported platform");
255 
256 /* Return values of cancelation function.  */
257 version (CRuntime_Glibc)
258 {
259     enum
260     {
261         AIO_CANCELED,
262         AIO_NOTCANCELED,
263         AIO_ALLDONE
264     }
265 }
266 else version (CRuntime_Musl)
267 {
268     enum
269     {
270         AIO_CANCELED,
271         AIO_NOTCANCELED,
272         AIO_ALLDONE
273     }
274 }
275 else version (CRuntime_UClibc)
276 {
277     enum
278     {
279         AIO_CANCELED,
280         AIO_NOTCANCELED,
281         AIO_ALLDONE
282     }
283 }
284 else version (Darwin)
285 {
286     enum
287     {
288         AIO_ALLDONE = 0x1,
289         AIO_CANCELED = 0x2,
290         AIO_NOTCANCELED = 0x4,
291     }
292 }
293 else version (Solaris)
294 {
295     enum
296     {
297         AIO_CANCELED,
298         AIO_ALLDONE,
299         AIO_NOTCANCELED
300     }
301 }
302 else version (BSD_Posix)
303 {
304     enum
305     {
306         AIO_CANCELED,
307         AIO_NOTCANCELED,
308         AIO_ALLDONE
309     }
310 }
311 
312 /* Operation codes for `aio_lio_opcode'.  */
313 version (CRuntime_Glibc)
314 {
315     enum
316     {
317         LIO_READ,
318         LIO_WRITE,
319         LIO_NOP
320     }
321 }
322 else version (CRuntime_Musl)
323 {
324     enum
325     {
326         LIO_READ,
327         LIO_WRITE,
328         LIO_NOP
329     }
330 }
331 else version (CRuntime_UClibc)
332 {
333     enum
334     {
335         LIO_READ,
336         LIO_WRITE,
337         LIO_NOP
338     }
339 }
340 else version (Darwin)
341 {
342     enum
343     {
344         LIO_NOP = 0x0,
345         LIO_READ = 0x1,
346         LIO_WRITE = 0x2,
347     }
348 }
349 else version (Solaris)
350 {
351     enum
352     {
353         LIO_NOP,
354         LIO_READ,
355         LIO_WRITE,
356     }
357 }
358 else version (BSD_Posix)
359 {
360     enum
361     {
362         LIO_NOP,
363         LIO_WRITE,
364         LIO_READ
365     }
366 }
367 
368 /* Synchronization options for `lio_listio' function.  */
369 version (CRuntime_Glibc)
370 {
371     enum
372     {
373         LIO_WAIT,
374         LIO_NOWAIT
375     }
376 }
377 else version (CRuntime_Musl)
378 {
379     enum
380     {
381         LIO_WAIT,
382         LIO_NOWAIT
383     }
384 }
385 else version (CRuntime_UClibc)
386 {
387     enum
388     {
389         LIO_WAIT,
390         LIO_NOWAIT
391     }
392 }
393 else version (Darwin)
394 {
395     enum
396     {
397         LIO_NOWAIT = 0x1,
398         LIO_WAIT = 0x2,
399     }
400 }
401 else version (Solaris)
402 {
403     enum
404     {
405         LIO_NOWAIT,
406         LIO_WAIT
407     }
408 }
409 else version (BSD_Posix)
410 {
411     enum
412     {
413         LIO_NOWAIT,
414         LIO_WAIT
415     }
416 }
417 
418 /* Functions implementing POSIX AIO.  */
419 version (CRuntime_Glibc)
420 {
421     static if (__USE_LARGEFILE64)
422     {
423         int aio_read64(aiocb64* aiocbp);
424         int aio_write64(aiocb64* aiocbp);
425         int aio_fsync64(int op, aiocb64* aiocbp);
426         int aio_error64(const(aiocb64)* aiocbp);
427         ssize_t aio_return64(aiocb64* aiocbp);
428         int aio_suspend64(const(aiocb64*)* aiocb_list, int nitems, const(timespec)* timeout);
429         int aio_cancel64(int fd, aiocb64* aiocbp);
430         int lio_listio64(int mode, const(aiocb64*)* aiocb_list, int nitems, sigevent* sevp);
431 
432         alias aio_read = aio_read64;
433         alias aio_write = aio_write64;
434         alias aio_fsync = aio_fsync64;
435         alias aio_error = aio_error64;
436         alias aio_return = aio_return64;
437         alias aio_suspend = aio_suspend64;
438         alias aio_cancel = aio_cancel64;
439         alias lio_listio = lio_listio64;
440     }
441     else
442     {
443         int aio_read(aiocb* aiocbp);
444         int aio_write(aiocb* aiocbp);
445         int aio_fsync(int op, aiocb* aiocbp);
446         int aio_error(const(aiocb)* aiocbp);
447         ssize_t aio_return(aiocb* aiocbp);
448         int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
449         int aio_cancel(int fd, aiocb* aiocbp);
450         int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
451     }
452 }
453 else version (CRuntime_Bionic)
454 {
455     // Bionic does not implement aio.h
456 }
457 else version (CRuntime_UClibc)
458 {
459     static if (__USE_LARGEFILE64)
460     {
461         int aio_read64(aiocb64* aiocbp);
462         int aio_write64(aiocb64* aiocbp);
463         int aio_fsync64(int op, aiocb64* aiocbp);
464         int aio_error64(const(aiocb64)* aiocbp);
465         ssize_t aio_return64(aiocb64* aiocbp);
466         int aio_suspend64(const(aiocb64*)* aiocb_list, int nitems, const(timespec)* timeout);
467         int aio_cancel64(int fd, aiocb64* aiocbp);
468         int lio_listio64(int mode, const(aiocb64*)* aiocb_list, int nitems, sigevent* sevp);
469 
470         alias aio_read = aio_read64;
471         alias aio_write = aio_write64;
472         alias aio_fsync = aio_fsync64;
473         alias aio_error = aio_error64;
474         alias aio_return = aio_return64;
475         alias aio_suspend = aio_suspend64;
476         alias aio_cancel = aio_cancel64;
477         alias lio_listio = lio_listio64;
478     }
479     else
480     {
481         int aio_read(aiocb* aiocbp);
482         int aio_write(aiocb* aiocbp);
483         int aio_fsync(int op, aiocb* aiocbp);
484         int aio_error(const(aiocb)* aiocbp);
485         ssize_t aio_return(aiocb* aiocbp);
486         int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
487         int aio_cancel(int fd, aiocb* aiocbp);
488         int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
489     }
490 }
491 else version (OpenBSD)
492 {
493     // OpenBSD does not implement aio.h
494 }
495 else
496 {
497     int aio_read(aiocb* aiocbp);
498     int aio_write(aiocb* aiocbp);
499     int aio_fsync(int op, aiocb* aiocbp);
500     int aio_error(const(aiocb)* aiocbp);
501     ssize_t aio_return(aiocb* aiocbp);
502     int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
503     int aio_cancel(int fd, aiocb* aiocbp);
504     int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
505 }
506 
507 /* Functions outside/extending POSIX requirement.  */
508 version (CRuntime_Glibc)
509 {
510     static if (__USE_GNU)
511     {
512         /* To customize the implementation one can use the following struct.  */
513         struct aioinit
514         {
515             int aio_threads;
516             int aio_num;
517             int aio_locks;
518             int aio_usedba;
519             int aio_debug;
520             int aio_numusers;
521             int aio_idle_time;
522             int aio_reserved;
523         }
524 
525         void aio_init(const(aioinit)* init);
526     }
527 }
528 else version (CRuntime_UClibc)
529 {
530     static if (__USE_GNU)
531     {
532         /* To customize the implementation one can use the following struct.  */
533         struct aioinit
534         {
535             int aio_threads;
536             int aio_num;
537             int aio_locks;
538             int aio_usedba;
539             int aio_debug;
540             int aio_numusers;
541             int aio_idle_time;
542             int aio_reserved;
543         }
544 
545         void aio_init(const(aioinit)* init);
546     }
547 }
548 else version (FreeBSD)
549 {
550     int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
551     int aio_mlock(aiocb* aiocbp);
552 }
553 else version (DragonFlyBSD)
554 {
555     int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
556 }
557