1295011Sandrew/**
2295011Sandrew * D header file to interface with the
3295011Sandrew * $(HTTP pubs.opengroup.org/onlinepubs/9699919799/basedefs/aio.h.html, Posix AIO API).
4295011Sandrew *
5295011Sandrew * Copyright: Copyright D Language Foundation 2018.
6295011Sandrew * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7295011Sandrew * Authors:   $(HTTPS github.com/darredevil, Alexandru Razvan Caciulescu)
8295011Sandrew */
9295011Sandrewmodule core.sys.posix.aio;
10295011Sandrew
11295011Sandrewimport core.sys.posix.signal;
12295011Sandrewimport core.sys.posix.sys.types;
13295011Sandrew
14295011Sandrewversion (OSX)
15295011Sandrew    version = Darwin;
16295011Sandrewelse version (iOS)
17295011Sandrew    version = Darwin;
18295011Sandrewelse version (TVOS)
19295011Sandrew    version = Darwin;
20295011Sandrewelse version (WatchOS)
21295011Sandrew    version = Darwin;
22295011Sandrew
23295011Sandrewversion (Posix):
24295011Sandrew
25295011Sandrewextern (C):
26295011Sandrew@system:
27295011Sandrew@nogc:
28295011Sandrewnothrow:
29295011Sandrew
30295011Sandrewversion (CRuntime_Glibc)
31295011Sandrew{
32295011Sandrew    import core.sys.posix.config;
33295011Sandrew
34295011Sandrew    struct aiocb
35295011Sandrew    {
36295011Sandrew        int aio_fildes;
37295011Sandrew        int aio_lio_opcode;
38295011Sandrew        int aio_reqprio;
39295011Sandrew        void* aio_buf;   //volatile
40295011Sandrew        size_t aio_nbytes;
41295011Sandrew        sigevent aio_sigevent;
42295011Sandrew
43295011Sandrew        aiocb* __next_prio;
44295011Sandrew        int __abs_prio;
45295011Sandrew        int __policy;
46295011Sandrew        int __error_code;
47295011Sandrew        ssize_t __return_value;
48295011Sandrew
49295011Sandrew        off_t aio_offset;
50295011Sandrew        ubyte[32] __glibc_reserved;
51295011Sandrew    }
52295011Sandrew
53295011Sandrew    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}
75else version (CRuntime_Bionic)
76{
77    // Bionic does not define aiocb.
78}
79else 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}
100else version (CRuntime_UClibc)
101{
102    // UClibc does not implement aiocb.
103}
104else 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}
117else 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}
142else 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}
160else version (OpenBSD)
161{
162    // OpenBSD does not define aiocb.
163}
164else 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}
181else 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}
203else
204    static assert(false, "Unsupported platform");
205
206/* Return values of cancelation function.  */
207version (CRuntime_Glibc)
208{
209    enum
210    {
211        AIO_CANCELED,
212        AIO_NOTCANCELED,
213        AIO_ALLDONE
214    }
215}
216else version (CRuntime_Musl)
217{
218    enum
219    {
220        AIO_CANCELED,
221        AIO_NOTCANCELED,
222        AIO_ALLDONE
223    }
224}
225else version (Darwin)
226{
227    enum
228    {
229        AIO_ALLDONE = 0x1,
230        AIO_CANCELED = 0x2,
231        AIO_NOTCANCELED = 0x4,
232    }
233}
234else version (Solaris)
235{
236    enum
237    {
238        AIO_CANCELED,
239        AIO_ALLDONE,
240        AIO_NOTCANCELED
241    }
242}
243else 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'.  */
254version (CRuntime_Glibc)
255{
256    enum
257    {
258        LIO_READ,
259        LIO_WRITE,
260        LIO_NOP
261    }
262}
263else version (CRuntime_Musl)
264{
265    enum
266    {
267        LIO_READ,
268        LIO_WRITE,
269        LIO_NOP
270    }
271}
272else version (Darwin)
273{
274    enum
275    {
276        LIO_NOP = 0x0,
277        LIO_READ = 0x1,
278        LIO_WRITE = 0x2,
279    }
280}
281else version (Solaris)
282{
283    enum
284    {
285        LIO_NOP,
286        LIO_READ,
287        LIO_WRITE,
288    }
289}
290else 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.  */
301version (CRuntime_Glibc)
302{
303    enum
304    {
305        LIO_WAIT,
306        LIO_NOWAIT
307    }
308}
309else version (CRuntime_Musl)
310{
311    enum
312    {
313        LIO_WAIT,
314        LIO_NOWAIT
315    }
316}
317else version (Darwin)
318{
319    enum
320    {
321        LIO_NOWAIT = 0x1,
322        LIO_WAIT = 0x2,
323    }
324}
325else version (Solaris)
326{
327    enum
328    {
329        LIO_NOWAIT,
330        LIO_WAIT
331    }
332}
333else version (BSD_Posix)
334{
335    enum
336    {
337        LIO_NOWAIT,
338        LIO_WAIT
339    }
340}
341
342/* Functions implementing POSIX AIO.  */
343version (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}
377else version (CRuntime_Bionic)
378{
379    // Bionic does not implement aio.h
380}
381else version (CRuntime_UClibc)
382{
383    // UClibc does not implement aio.h
384}
385else version (OpenBSD)
386{
387    // OpenBSD does not implement aio.h
388}
389else
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    int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
397    int aio_cancel(int fd, aiocb* aiocbp);
398    int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
399}
400
401/* Functions outside/extending POSIX requirement.  */
402version (CRuntime_Glibc)
403{
404    static if (_GNU_SOURCE)
405    {
406        /* To customize the implementation one can use the following struct.  */
407        struct aioinit
408        {
409            int aio_threads;
410            int aio_num;
411            int aio_locks;
412            int aio_usedba;
413            int aio_debug;
414            int aio_numusers;
415            int aio_idle_time;
416            int aio_reserved;
417        }
418
419        void aio_init(const(aioinit)* init);
420    }
421}
422else version (FreeBSD)
423{
424    int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
425    int aio_mlock(aiocb* aiocbp);
426}
427else version (DragonFlyBSD)
428{
429    int aio_waitcomplete(aiocb** aiocb_list, const(timespec)* timeout);
430}
431