xref: /dflybsd-src/lib/librt/aio.c (revision 127a3eb4035f914ee311e89500f4d77abda51b3f)
1 /*-
2  * Copyright (c) 2011 Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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.
14  */
15 
16 /*
17  * This file contains support for the POSIX 1003.1B AIO/LIO facility.
18  *
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
21  * routines.
22  *
23  * This version cannot perform asynchronous notification of I/O completion
24  * on DragonFly via SIGEV_THREAD or SIGEV_SIGNAL.
25  *
26  *    1) SIGEV_THREAD is not supported by DFly's sigevent structure or any
27  *	 other machinery in libthread or librt.
28  *
29  *    2) SIGEV_SIGNAL code is present, but if-ed out under 'notyet'; Dfly
30  *	 does not support sigqueue(), so we cannot control the payload to
31  *	 a SIGINFO-signal from userspace. Programs using AIO signals use
32  *	 the payload field to carry pointers to the completed AIO structure,
33  *	 which is not yet possible here.
34  *
35  * It would be possible for this version to support SIGEV_KEVENT.
36  */
37 
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #include <sys/signal.h>
42 #include <sys/queue.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <sys/aio.h>
46 
47 static void
48 _aio_signal(struct aiocb *ap)
49 {
50 #ifdef notyet
51 	int sig;
52 	union sigval sv;
53 	pid_t pid;
54 
55 	if (ap->aio_sigevent.sigev_notify == SIGEV_NONE)
56 		return;
57 
58 	sig = ap->aio_sigevent.sigev_signo;
59 	sv = ap->aio_sigevent.sigev_value;
60 
61 	sigqueue(pid, sig, sv);
62 #endif
63 }
64 
65 static void
66 _lio_signal(struct sigevent *sigevp)
67 {
68 #ifdef notyet
69 	int sig;
70 	union sigval sv;
71 	pid_t pid;
72 
73 	pid = getpid();
74 	sig = sigevp->sigev_signo;
75 	sv = sigevp->sigev_value;
76 
77 	sigqueue(pid, sig, sv);
78 #endif
79 }
80 
81 /*
82  * aio_read()
83  *
84  *	Asynchronously read from a file
85  */
86 int
87 aio_read(struct aiocb *ap)
88 {
89 #ifndef notyet
90 	if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
91 		return (ENOSYS);
92 #endif
93 
94 	ap->_aio_val = pread(ap->aio_fildes,
95 			     (void *) ap->aio_buf,
96 			     ap->aio_nbytes,
97 			     ap->aio_offset);
98 	ap->_aio_err = errno;
99 
100 	_aio_signal(ap);
101 
102 	return (0);
103 }
104 
105 int
106 aio_write(struct aiocb *ap)
107 {
108 #ifndef notyet
109 	if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
110 		return (ENOSYS);
111 #endif
112 
113 	ap->_aio_val = pwrite(ap->aio_fildes,
114 			      (void *) ap->aio_buf,
115 			      ap->aio_nbytes,
116 			      ap->aio_offset);
117 	ap->_aio_err = errno;
118 
119 	_aio_signal(ap);
120 
121 	return (0);
122 }
123 
124 int
125 aio_fsync(int op, struct aiocb *ap)
126 {
127 #ifndef notyet
128 	if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
129 		return (ENOSYS);
130 #endif
131 
132 	ap->_aio_val = fsync(ap->aio_fildes);
133 	ap->_aio_err = errno;
134 
135 	_aio_signal(ap);
136 
137 	return(0);
138 }
139 
140 int
141 lio_listio(int mode, struct aiocb *const apv[], int nent,
142 	   struct sigevent *sigevp)
143 {
144 	int i;
145 
146 #ifndef notyet
147 	if (sigevp && sigevp->sigev_notify != SIGEV_NONE)
148 		return (ENOSYS);
149 #endif
150 
151 	for (i = 0; i < nent; i++)
152 		switch (apv[i]->aio_lio_opcode) {
153 		case LIO_READ:
154 			aio_read(apv[i]);
155 			break;
156 		case LIO_WRITE:
157 			aio_write(apv[i]);
158 			break;
159 		case LIO_NOP:
160 			break;
161 		}
162 
163 	if (sigevp &&
164 	    (mode == LIO_NOWAIT) &&
165 	    (sigevp->sigev_notify == SIGEV_SIGNAL)
166 	   ) {
167 		_lio_signal(sigevp);
168 	}
169 
170 	return (0);
171 }
172 
173 /*
174  * aio_error()
175  *
176  * 	Get I/O completion status
177  *
178  *      Returns EINPROGRESS until I/O is complete. Returns ECANCELED if
179  *	I/O is canceled. Returns I/O status if operation completed.
180  *
181  *      This routine does not block.
182  */
183 int
184 aio_error(const struct aiocb *ap)
185 {
186 	return (ap->_aio_err);
187 }
188 
189 /*
190  * aio_return()
191  *
192  *	Finish up I/O, releasing I/O resources and returns the value
193  *	that would have been associated with a synchronous request.
194  */
195 ssize_t
196 aio_return(struct aiocb *ap)
197 {
198 	return (ap->_aio_val);
199 }
200 
201 int
202 aio_cancel(int fildes, struct aiocb *aiocbp)
203 {
204 	return (AIO_ALLDONE);
205 }
206 
207 int
208 aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timo)
209 {
210 	return (0);
211 }
212 
213