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
This commit is contained in:
Alan Cox 2000-11-21 19:36:36 +00:00
parent 0fb3a41200
commit c6fa9f78d2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69002
3 changed files with 48 additions and 32 deletions

View File

@ -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);
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 ((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:
suword(&job->_aiocb_private.error, EINPROGRESS);
aiocbe->uaiocb._aiocb_private.error = EINPROGRESS;

View File

@ -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 */

View File

@ -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 */