summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2000-11-21 19:36:36 +0000
committeralc <alc@FreeBSD.org>2000-11-21 19:36:36 +0000
commitdfa19cb0cec51bbb1fba802ceae5f4b58cad3892 (patch)
treef94c70c4fa02e59eaa647c43646fa01b3f50e088
parente4af8551d901ed0a27dbc1149b09d6ce974fd1ae (diff)
downloadFreeBSD-src-dfa19cb0cec51bbb1fba802ceae5f4b58cad3892.zip
FreeBSD-src-dfa19cb0cec51bbb1fba802ceae5f4b58cad3892.tar.gz
Provide a new interface for the user of aio_read() and aio_write() to request
a kevent upon completion of the I/O. Specifically, introduce a new type of sigevent notification, SIGEV_EVENT. If sigev_notify is SIGEV_EVENT, then sigev_notify_kqueue names the kqueue that should receive the event and sigev_value contains the "void *" is copied into the kevent's udata field. In contrast to the existing interface, this one: 1) works on the Alpha 2) avoids the extra copyin() call for the kevent because all of the information needed is in the sigevent and 3) could be applied to request a single kevent upon completion of an entire lio_listio(). Reviewed by: jlemon
-rw-r--r--sys/kern/vfs_aio.c62
-rw-r--r--sys/sys/_sigset.h8
-rw-r--r--sys/sys/signal.h8
3 files changed, 47 insertions, 31 deletions
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index d4a226c..8758ebd 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -1207,6 +1207,9 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
struct aiocblist *aiocbe;
struct aioproclist *aiop;
struct kaioinfo *ki;
+ struct kevent kev;
+ struct kqueue *kq;
+ struct file *kq_fp;
if ((aiocbe = TAILQ_FIRST(&aio_freejobs)) != NULL)
TAILQ_REMOVE(&aio_freejobs, aiocbe, list);
@@ -1303,16 +1306,18 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
fhold(fp);
- /*
- * XXX
- * Figure out how to do this properly. This currently won't
- * work on the alpha, since we're passing in a pointer via
- * aio_lio_opcode, which is an int.
- */
- {
- struct kevent kev, *kevp;
- struct kqueue *kq;
- struct file *kq_fp;
+ if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_KEVENT) {
+ kev.ident = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue;
+ kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sigval_ptr;
+ }
+ else {
+ /*
+ * This method for requesting kevent-based notification won't
+ * work on the alpha, since we're passing in a pointer
+ * via aio_lio_opcode, which is an int. Use the SIGEV_KEVENT-
+ * based method instead.
+ */
+ struct kevent *kevp;
kevp = (struct kevent *)job->aio_lio_opcode;
if (kevp == NULL)
@@ -1321,27 +1326,26 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
error = copyin((caddr_t)kevp, (caddr_t)&kev, sizeof(kev));
if (error)
goto aqueue_fail;
-
- if ((u_int)kev.ident >= fdp->fd_nfiles ||
- (kq_fp = fdp->fd_ofiles[kev.ident]) == NULL ||
- (kq_fp->f_type != DTYPE_KQUEUE)) {
- error = EBADF;
- goto aqueue_fail;
- }
- kq = (struct kqueue *)kq_fp->f_data;
- kev.ident = (u_long)aiocbe;
- kev.filter = EVFILT_AIO;
- kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
- error = kqueue_register(kq, &kev, p);
+ }
+ if ((u_int)kev.ident >= fdp->fd_nfiles ||
+ (kq_fp = fdp->fd_ofiles[kev.ident]) == NULL ||
+ (kq_fp->f_type != DTYPE_KQUEUE)) {
+ error = EBADF;
+ goto aqueue_fail;
+ }
+ kq = (struct kqueue *)kq_fp->f_data;
+ kev.ident = (uintptr_t)aiocbe;
+ kev.filter = EVFILT_AIO;
+ kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
+ error = kqueue_register(kq, &kev, p);
aqueue_fail:
- if (error) {
- TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
- if (type == 0)
- suword(&job->_aiocb_private.error, error);
- goto done;
- }
-no_kqueue:
+ if (error) {
+ TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
+ if (type == 0)
+ suword(&job->_aiocb_private.error, error);
+ goto done;
}
+no_kqueue:
suword(&job->_aiocb_private.error, EINPROGRESS);
aiocbe->uaiocb._aiocb_private.error = EINPROGRESS;
diff --git a/sys/sys/_sigset.h b/sys/sys/_sigset.h
index e3bef90..95891ff 100644
--- a/sys/sys/_sigset.h
+++ b/sys/sys/_sigset.h
@@ -133,12 +133,18 @@ union sigval {
struct sigevent {
int sigev_notify; /* Notification type */
- int sigev_signo; /* Signal number */
+ union {
+ int __sigev_signo; /* Signal number */
+ int __sigev_notify_kqueue;
+ } __sigev_u;
union sigval sigev_value; /* Signal value */
};
+#define sigev_signo __sigev_u.__sigev_signo
+#define sigev_notify_kqueue __sigev_u.__sigev_notify_kqueue
#define SIGEV_NONE 0 /* No async notification */
#define SIGEV_SIGNAL 1 /* Generate a queued signal */
+#define SIGEV_KEVENT 3 /* Generate a kevent */
typedef struct __siginfo {
int si_signo; /* signal number */
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
index e3bef90..95891ff 100644
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -133,12 +133,18 @@ union sigval {
struct sigevent {
int sigev_notify; /* Notification type */
- int sigev_signo; /* Signal number */
+ union {
+ int __sigev_signo; /* Signal number */
+ int __sigev_notify_kqueue;
+ } __sigev_u;
union sigval sigev_value; /* Signal value */
};
+#define sigev_signo __sigev_u.__sigev_signo
+#define sigev_notify_kqueue __sigev_u.__sigev_notify_kqueue
#define SIGEV_NONE 0 /* No async notification */
#define SIGEV_SIGNAL 1 /* Generate a queued signal */
+#define SIGEV_KEVENT 3 /* Generate a kevent */
typedef struct __siginfo {
int si_signo; /* signal number */
OpenPOWER on IntegriCloud