librt -- AIO: Implement SIGEV_THREAD for AIO completion notification.
[dragonfly.git] / lib / librt / aio.c
blob7c87c1e98dae3707809994617ed8b8cd1b3a183d
1 /*-
2 * Copyright (c) 2011 Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
21 * routines.
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.
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>
43 #include <pthread.h>
45 static void *_aio_thr_start(void *);
47 static void
48 _aio_notify(struct sigevent *sigevp)
50 int sig;
51 union sigval sv;
52 pid_t pid;
53 pthread_t thr;
55 switch (sigevp->sigev_notify) {
56 case SIGEV_NONE:
57 return;
59 case SIGEV_THREAD:
60 pthread_create(&thr,
61 sigevp->sigev_notify_attributes,
62 _aio_thr_start,
63 sigevp);
64 break;
66 case SIGEV_SIGNAL:
67 #ifdef notyet
68 pid = getpid();
69 sig = sigevp->sigev_signo;
70 sv = sigevp->sigev_value;
71 sigqueue(pid, sig, sv);
72 #endif
73 break;
75 case SIGEV_KEVENT:
76 #ifdef notyet
77 #endif
78 break;
82 static void *
83 _aio_thr_start(void *vsigevp)
85 struct sigevent *sigevp = vsigevp;
86 sigevp->sigev_notify_function(sigevp->sigev_value);
87 return (NULL);
91 * aio_read()
93 * Asynchronously read from a file
95 int
96 aio_read(struct aiocb *ap)
98 #ifndef notyet
99 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
100 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
101 return (ENOSYS);
102 #endif
104 ap->_aio_val = pread(ap->aio_fildes,
105 (void *) ap->aio_buf,
106 ap->aio_nbytes,
107 ap->aio_offset);
108 ap->_aio_err = errno;
110 _aio_notify(&ap->aio_sigevent);
112 return (0);
115 int
116 aio_write(struct aiocb *ap)
118 #ifndef notyet
119 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
120 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
121 return (ENOSYS);
122 #endif
124 ap->_aio_val = pwrite(ap->aio_fildes,
125 (void *) ap->aio_buf,
126 ap->aio_nbytes,
127 ap->aio_offset);
128 ap->_aio_err = errno;
130 _aio_notify(&ap->aio_sigevent);
132 return (0);
136 aio_fsync(int op, struct aiocb *ap)
138 #ifndef notyet
139 if ((ap->aio_sigevent.sigev_notify != SIGEV_NONE) &&
140 (ap->aio_sigevent.sigev_notify != SIGEV_THREAD))
141 return (ENOSYS);
142 #endif
144 ap->_aio_val = fsync(ap->aio_fildes);
145 ap->_aio_err = errno;
147 _aio_notify(&ap->aio_sigevent);
149 return(0);
152 int
153 lio_listio(int mode, struct aiocb *const apv[], int nent,
154 struct sigevent *sigevp)
156 int i;
158 #ifndef notyet
159 if ((sigevp->sigev_notify != SIGEV_NONE) &&
160 (sigevp->sigev_notify != SIGEV_THREAD))
161 return (ENOSYS);
162 #endif
164 for (i = 0; i < nent; i++)
165 switch (apv[i]->aio_lio_opcode) {
166 case LIO_READ:
167 aio_read(apv[i]);
168 break;
169 case LIO_WRITE:
170 aio_write(apv[i]);
171 break;
172 case LIO_NOP:
173 break;
176 if (sigevp &&
177 (mode == LIO_NOWAIT)
179 _aio_notify(sigevp);
182 return (0);
186 * aio_error()
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.
195 int
196 aio_error(const struct aiocb *ap)
198 return (ap->_aio_err);
202 * aio_return()
204 * Finish up I/O, releasing I/O resources and returns the value
205 * that would have been associated with a synchronous request.
207 ssize_t
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)
222 return (0);