librt -- aio: lio_listio: Do not dereference NULL sigevp.
[dragonfly.git] / lib / librt / aio.c
CommitLineData
ea3ab097
VS
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
84c33861 24 * on DragonFly via SIGEV_SIGNAL.
ea3ab097
VS
25 *
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.
31 *
32 * It would be possible for this version to support SIGEV_KEVENT.
33 */
34
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/time.h>
38#include <sys/signal.h>
39#include <sys/queue.h>
40#include <unistd.h>
41#include <errno.h>
42#include <sys/aio.h>
84c33861
VS
43#include <pthread.h>
44
45static void *_aio_thr_start(void *);
ea3ab097
VS
46
47static void
84c33861 48_aio_notify(struct sigevent *sigevp)
ea3ab097 49{
dacb3008 50#if 0 /* not yet */
ea3ab097
VS
51 int sig;
52 union sigval sv;
53 pid_t pid;
dacb3008 54#endif
84c33861 55 pthread_t thr;
ea3ab097 56
84c33861
VS
57 switch (sigevp->sigev_notify) {
58 case SIGEV_NONE:
ea3ab097
VS
59 return;
60
84c33861
VS
61 case SIGEV_THREAD:
62 pthread_create(&thr,
63 sigevp->sigev_notify_attributes,
64 _aio_thr_start,
65 sigevp);
66 break;
ea3ab097 67
84c33861 68 case SIGEV_SIGNAL:
dacb3008 69#if 0 /* not yet */
84c33861
VS
70 pid = getpid();
71 sig = sigevp->sigev_signo;
72 sv = sigevp->sigev_value;
73 sigqueue(pid, sig, sv);
74#endif
75 break;
ea3ab097 76
84c33861 77 case SIGEV_KEVENT:
dacb3008 78 /* not yet */
84c33861
VS
79 break;
80 }
81}
82
83static void *
84_aio_thr_start(void *vsigevp)
85{
86 struct sigevent *sigevp = vsigevp;
87 sigevp->sigev_notify_function(sigevp->sigev_value);
88 return (NULL);
ea3ab097
VS
89}
90
91/*
92 * aio_read()
93 *
94 * Asynchronously read from a file
95 */
96int
97aio_read(struct aiocb *ap)
98{
99#ifndef notyet
84c33861
VS
100 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
101 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
102 return (ENOSYS);
103#endif
104
105 ap->_aio_val = pread(ap->aio_fildes,
106 (void *) ap->aio_buf,
107 ap->aio_nbytes,
108 ap->aio_offset);
109 ap->_aio_err = errno;
110
84c33861 111 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
112
113 return (0);
114}
115
116int
117aio_write(struct aiocb *ap)
118{
119#ifndef notyet
84c33861
VS
120 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
121 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
122 return (ENOSYS);
123#endif
124
125 ap->_aio_val = pwrite(ap->aio_fildes,
126 (void *) ap->aio_buf,
127 ap->aio_nbytes,
128 ap->aio_offset);
129 ap->_aio_err = errno;
130
84c33861 131 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
132
133 return (0);
134}
135
136int
137aio_fsync(int op, struct aiocb *ap)
138{
139#ifndef notyet
84c33861
VS
140 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
141 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
ea3ab097
VS
142 return (ENOSYS);
143#endif
144
145 ap->_aio_val = fsync(ap->aio_fildes);
146 ap->_aio_err = errno;
147
84c33861 148 _aio_notify(&ap->aio_sigevent);
ea3ab097
VS
149
150 return(0);
151}
152
153int
154lio_listio(int mode, struct aiocb *const apv[], int nent,
155 struct sigevent *sigevp)
156{
157 int i;
158
159#ifndef notyet
019e715a
VS
160 if (sigevp &&
161 (sigevp->sigev_notify != SIGEV_NONE) &&
84c33861 162 (sigevp->sigev_notify != SIGEV_THREAD))
ea3ab097
VS
163 return (ENOSYS);
164#endif
165
166 for (i = 0; i < nent; i++)
167 switch (apv[i]->aio_lio_opcode) {
168 case LIO_READ:
169 aio_read(apv[i]);
170 break;
171 case LIO_WRITE:
172 aio_write(apv[i]);
173 break;
174 case LIO_NOP:
175 break;
176 }
177
178 if (sigevp &&
84c33861 179 (mode == LIO_NOWAIT)
ea3ab097 180 ) {
84c33861 181 _aio_notify(sigevp);
ea3ab097
VS
182 }
183
184 return (0);
185}
186
187/*
188 * aio_error()
189 *
190 * Get I/O completion status
191 *
192 * Returns EINPROGRESS until I/O is complete. Returns ECANCELED if
193 * I/O is canceled. Returns I/O status if operation completed.
194 *
195 * This routine does not block.
196 */
197int
198aio_error(const struct aiocb *ap)
199{
200 return (ap->_aio_err);
201}
202
203/*
204 * aio_return()
205 *
206 * Finish up I/O, releasing I/O resources and returns the value
207 * that would have been associated with a synchronous request.
208 */
209ssize_t
210aio_return(struct aiocb *ap)
211{
212 return (ap->_aio_val);
213}
214
215int
216aio_cancel(int fildes, struct aiocb *aiocbp)
217{
218 return (AIO_ALLDONE);
219}
220
221int
222aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timo)
223{
224 return (0);
225}
226