diff options
author | alc <alc@FreeBSD.org> | 2000-11-21 19:36:36 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2000-11-21 19:36:36 +0000 |
commit | dfa19cb0cec51bbb1fba802ceae5f4b58cad3892 (patch) | |
tree | f94c70c4fa02e59eaa647c43646fa01b3f50e088 | |
parent | e4af8551d901ed0a27dbc1149b09d6ce974fd1ae (diff) | |
download | FreeBSD-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.c | 62 | ||||
-rw-r--r-- | sys/sys/_sigset.h | 8 | ||||
-rw-r--r-- | sys/sys/signal.h | 8 |
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 */ |