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:
parent
0fb3a41200
commit
c6fa9f78d2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69002
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user