2 * Copyright (c) 2011 Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
17 * This file contains support for the POSIX 1003.1B AIO/LIO facility.
19 * This version of AIO is aimed at standards compliance; it is not aimed
20 * at either reasonability or performance. It merely wraps synchronous I/O
23 * This version cannot perform asynchronous notification of I/O completion
24 * on DragonFly via SIGEV_SIGNAL.
26 * 2) SIGEV_SIGNAL code is present, but if-ed out under 'notyet'; Dfly
27 * does not support sigqueue(), so we cannot control the payload to
28 * a SIGINFO-signal from userspace. Programs using AIO signals use
29 * the payload field to carry pointers to the completed AIO structure,
30 * which is not yet possible here.
32 * It would be possible for this version to support SIGEV_KEVENT.
36 #include <sys/types.h>
38 #include <sys/signal.h>
39 #include <sys/queue.h>
45 static void *_aio_thr_start(void *);
48 _aio_notify(struct sigevent
*sigevp
)
55 switch (sigevp
->sigev_notify
) {
61 sigevp
->sigev_notify_attributes
,
69 sig
= sigevp
->sigev_signo
;
70 sv
= sigevp
->sigev_value
;
71 sigqueue(pid
, sig
, sv
);
83 _aio_thr_start(void *vsigevp
)
85 struct sigevent
*sigevp
= vsigevp
;
86 sigevp
->sigev_notify_function(sigevp
->sigev_value
);
93 * Asynchronously read from a file
96 aio_read(struct aiocb
*ap
)
99 if ((ap
->aio_sigevent
.sigev_notify
!= SIGEV_NONE
) &&
100 (ap
->aio_sigevent
.sigev_notify
!= SIGEV_THREAD
))
104 ap
->_aio_val
= pread(ap
->aio_fildes
,
105 (void *) ap
->aio_buf
,
108 ap
->_aio_err
= errno
;
110 _aio_notify(&ap
->aio_sigevent
);
116 aio_write(struct aiocb
*ap
)
119 if ((ap
->aio_sigevent
.sigev_notify
!= SIGEV_NONE
) &&
120 (ap
->aio_sigevent
.sigev_notify
!= SIGEV_THREAD
))
124 ap
->_aio_val
= pwrite(ap
->aio_fildes
,
125 (void *) ap
->aio_buf
,
128 ap
->_aio_err
= errno
;
130 _aio_notify(&ap
->aio_sigevent
);
136 aio_fsync(int op
, struct aiocb
*ap
)
139 if ((ap
->aio_sigevent
.sigev_notify
!= SIGEV_NONE
) &&
140 (ap
->aio_sigevent
.sigev_notify
!= SIGEV_THREAD
))
144 ap
->_aio_val
= fsync(ap
->aio_fildes
);
145 ap
->_aio_err
= errno
;
147 _aio_notify(&ap
->aio_sigevent
);
153 lio_listio(int mode
, struct aiocb
*const apv
[], int nent
,
154 struct sigevent
*sigevp
)
159 if ((sigevp
->sigev_notify
!= SIGEV_NONE
) &&
160 (sigevp
->sigev_notify
!= SIGEV_THREAD
))
164 for (i
= 0; i
< nent
; i
++)
165 switch (apv
[i
]->aio_lio_opcode
) {
188 * Get I/O completion status
190 * Returns EINPROGRESS until I/O is complete. Returns ECANCELED if
191 * I/O is canceled. Returns I/O status if operation completed.
193 * This routine does not block.
196 aio_error(const struct aiocb
*ap
)
198 return (ap
->_aio_err
);
204 * Finish up I/O, releasing I/O resources and returns the value
205 * that would have been associated with a synchronous request.
208 aio_return(struct aiocb
*ap
)
210 return (ap
->_aio_val
);
214 aio_cancel(int fildes
, struct aiocb
*aiocbp
)
216 return (AIO_ALLDONE
);
220 aio_suspend(const struct aiocb
*const list
[], int nent
, const struct timespec
*timo
)