diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index fef2c5e09660..f7c330b0d3b7 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -467,9 +467,11 @@ u_int nfds, int timeout); } 253 AUE_NULL MSTD { int issetugid(void); } 254 AUE_NULL MSTD { int lchown(char *path, int uid, int gid); } -255 AUE_NULL UNIMPL nosys -256 AUE_NULL UNIMPL nosys -257 AUE_NULL UNIMPL nosys +255 AUE_NULL NOSTD { int aio_read(struct aiocb *aiocbp); } +256 AUE_NULL NOSTD { int aio_write(struct aiocb *aiocbp); } +257 AUE_NULL NOSTD { int lio_listio(int mode, \ + struct aiocb * const *acb_list, \ + int nent, struct sigevent *sig); } 258 AUE_NULL UNIMPL nosys 259 AUE_NULL UNIMPL nosys 260 AUE_NULL UNIMPL nosys @@ -551,11 +553,11 @@ 316 AUE_NULL NOSTD { int aio_cancel(int fd, \ struct aiocb *aiocbp); } 317 AUE_NULL NOSTD { int aio_error(struct aiocb *aiocbp); } -318 AUE_NULL NOSTD { int aio_read(struct aiocb *aiocbp); } -319 AUE_NULL NOSTD { int aio_write(struct aiocb *aiocbp); } -320 AUE_NULL NOSTD { int lio_listio(int mode, \ - struct aiocb * const *acb_list, \ - int nent, struct sigevent *sig); } +318 AUE_NULL NOSTD { int oaio_read(struct oaiocb *aiocbp); } +319 AUE_NULL NOSTD { int oaio_write(struct oaiocb *aiocbp); } +320 AUE_NULL NOSTD { int olio_listio(int mode, \ + struct oaiocb * const *acb_list, \ + int nent, struct osigevent *sig); } 321 AUE_NULL MSTD { int yield(void); } 322 AUE_NULL OBSOL thr_sleep 323 AUE_NULL OBSOL thr_wakeup diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 2d550da7d0c6..007d1ed246cb 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -170,6 +170,17 @@ static int max_buf_aio = MAX_BUF_AIO; SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0, "Maximum buf aio requests per process (stored in the process)"); +typedef struct oaiocb { + int aio_fildes; /* File descriptor */ + off_t aio_offset; /* File offset for I/O */ + volatile void *aio_buf; /* I/O buffer in process space */ + size_t aio_nbytes; /* Number of bytes for I/O */ + struct osigevent aio_sigevent; /* Signal to deliver */ + int aio_lio_opcode; /* LIO opcode */ + int aio_reqprio; /* Request priority -- ignored */ + struct __aiocb_private _aiocb_private; +} oaiocb_t; + struct aiocblist { TAILQ_ENTRY(aiocblist) list; /* List of jobs */ TAILQ_ENTRY(aiocblist) plist; /* List of jobs for proc */ @@ -254,7 +265,8 @@ static void aio_onceonly(void); static int aio_free_entry(struct aiocblist *aiocbe); static void aio_process(struct aiocblist *aiocbe); static int aio_newproc(void); -static int aio_aqueue(struct thread *td, struct aiocb *job, int type); +static int aio_aqueue(struct thread *td, struct aiocb *job, int type, + int osigev); static void aio_physwakeup(struct buf *bp); static void aio_proc_rundown(void *arg, struct proc *p); static int aio_fphysio(struct aiocblist *aiocbe); @@ -271,6 +283,8 @@ static int filt_lio(struct knote *kn, long hint); #define DONE_BUF 1 #define DONE_QUEUE 2 static void aio_bio_done_notify( struct proc *userp, struct aiocblist *aiocbe, int type); +static int do_lio_listio(struct thread *td, struct lio_listio_args *uap, + int oldsigev); /* * Zones for: @@ -328,6 +342,9 @@ SYSCALL_MODULE_HELPER(aio_read); SYSCALL_MODULE_HELPER(aio_write); SYSCALL_MODULE_HELPER(aio_waitcomplete); SYSCALL_MODULE_HELPER(lio_listio); +SYSCALL_MODULE_HELPER(oaio_read); +SYSCALL_MODULE_HELPER(oaio_write); +SYSCALL_MODULE_HELPER(olio_listio); DECLARE_MODULE(aio, aio_mod, SI_SUB_VFS, SI_ORDER_ANY); @@ -1320,7 +1337,8 @@ aio_swake_cb(struct socket *so, struct sockbuf *sb) * technique is done in this code. */ static int -_aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, int type) +_aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, + int type, int oldsigev) { struct proc *p = td->td_proc; struct filedesc *fdp; @@ -1348,7 +1366,14 @@ _aio_aqueue(struct thread *td, struct aiocb *job, struct aio_liojob *lj, int typ suword(&job->_aiocb_private.error, 0); suword(&job->_aiocb_private.kernelinfo, -1); - error = copyin(job, &aiocbe->uaiocb, sizeof(aiocbe->uaiocb)); + if (oldsigev) { + bzero(&aiocbe->uaiocb, sizeof(struct aiocb)); + error = copyin(job, &aiocbe->uaiocb, sizeof(struct oaiocb)); + bcopy(&aiocbe->uaiocb.__spare__, &aiocbe->uaiocb.aio_sigevent, + sizeof(struct osigevent)); + } else { + error = copyin(job, &aiocbe->uaiocb, sizeof(struct aiocb)); + } if (error) { suword(&job->_aiocb_private.error, error); uma_zfree(aiocb_zone, aiocbe); @@ -1558,7 +1583,7 @@ done: * This routine queues an AIO request, checking for quotas. */ static int -aio_aqueue(struct thread *td, struct aiocb *job, int type) +aio_aqueue(struct thread *td, struct aiocb *job, int type, int oldsigev) { struct proc *p = td->td_proc; struct kaioinfo *ki; @@ -1573,7 +1598,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, int type) if (ki->kaio_queue_count >= ki->kaio_qallowed_count) return (EAGAIN); - return _aio_aqueue(td, job, NULL, type); + return _aio_aqueue(td, job, NULL, type, oldsigev); } /* @@ -1956,24 +1981,51 @@ aio_error(struct thread *td, struct aio_error_args *uap) } /* syscall - asynchronous read from a file (REALTIME) */ +int +oaio_read(struct thread *td, struct oaio_read_args *uap) +{ + + return aio_aqueue(td, (struct aiocb *)uap->aiocbp, LIO_READ, 1); +} + int aio_read(struct thread *td, struct aio_read_args *uap) { - return aio_aqueue(td, uap->aiocbp, LIO_READ); + return aio_aqueue(td, uap->aiocbp, LIO_READ, 0); } /* syscall - asynchronous write to a file (REALTIME) */ +int +oaio_write(struct thread *td, struct oaio_write_args *uap) +{ + + return aio_aqueue(td, (struct aiocb *)uap->aiocbp, LIO_WRITE, 1); +} + int aio_write(struct thread *td, struct aio_write_args *uap) { - return aio_aqueue(td, uap->aiocbp, LIO_WRITE); + return aio_aqueue(td, uap->aiocbp, LIO_WRITE, 0); +} + +/* syscall - list directed I/O (REALTIME) */ +int +olio_listio(struct thread *td, struct olio_listio_args *uap) +{ + return do_lio_listio(td, (struct lio_listio_args *)uap, 1); } /* syscall - list directed I/O (REALTIME) */ int lio_listio(struct thread *td, struct lio_listio_args *uap) +{ + return do_lio_listio(td, uap, 0); +} + +static int +do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev) { struct proc *p = td->td_proc; int nent, nentqueued; @@ -2023,8 +2075,10 @@ lio_listio(struct thread *td, struct lio_listio_args *uap) * Setup signal. */ if (uap->sig && (uap->mode == LIO_NOWAIT)) { + bzero(&lj->lioj_signal, sizeof(&lj->lioj_signal)); error = copyin(uap->sig, &lj->lioj_signal, - sizeof(lj->lioj_signal)); + oldsigev ? sizeof(struct osigevent) : + sizeof(struct sigevent)); if (error) { uma_zfree(aiolio_zone, lj); return (error); @@ -2071,7 +2125,7 @@ lio_listio(struct thread *td, struct lio_listio_args *uap) for (i = 0; i < uap->nent; i++) { iocb = (struct aiocb *)(intptr_t)fuword(&cbptr[i]); if (((intptr_t)iocb != -1) && ((intptr_t)iocb != 0)) { - error = _aio_aqueue(td, iocb, lj, 0); + error = _aio_aqueue(td, iocb, lj, 0, oldsigev); if (error == 0) nentqueued++; else diff --git a/sys/sys/aio.h b/sys/sys/aio.h index f0c2a11576ed..1b09e490ecee 100644 --- a/sys/sys/aio.h +++ b/sys/sys/aio.h @@ -66,10 +66,11 @@ typedef struct aiocb { off_t aio_offset; /* File offset for I/O */ volatile void *aio_buf; /* I/O buffer in process space */ size_t aio_nbytes; /* Number of bytes for I/O */ - struct sigevent aio_sigevent; /* Signal to deliver */ + char __spare__[sizeof(int) * 2 + sizeof(void *)]; /* osigevent. */ int aio_lio_opcode; /* LIO opcode */ int aio_reqprio; /* Request priority -- ignored */ struct __aiocb_private _aiocb_private; + struct sigevent aio_sigevent; /* Signal to deliver */ } aiocb_t; #ifndef _KERNEL diff --git a/sys/sys/signal.h b/sys/sys/signal.h index 7e273e30dd50..d6dc895e71da 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -158,28 +158,31 @@ union sigval { #if __POSIX_VISIBLE >= 199309 struct sigevent { int sigev_notify; /* Notification type */ - union { - int __sigev_signo; /* Signal number */ - int __sigev_notify_kqueue; - } __sigev_u; + int sigev_signo; /* Signal number */ union sigval sigev_value; /* Signal value */ -/* - * XXX missing sigev_notify_function, sigev_notify_attributes. - */ + union { + __lwpid_t _threadid; + struct { + void (*_function)(union sigval *); + void *_attribute; /* pthread_attr_t * */ + } _sigev_thread; + } _sigev_un; }; -#define sigev_signo __sigev_u.__sigev_signo -#if __BSD_VISIBLE -#define sigev_notify_kqueue __sigev_u.__sigev_notify_kqueue -#endif -#define SIGEV_NONE 0 /* No async notification */ -#define SIGEV_SIGNAL 1 /* Generate a queued signal */ #if __BSD_VISIBLE -#define SIGEV_KEVENT 3 /* Generate a kevent */ +#define sigev_notify_kqueue sigev_signo +#define sigev_notify_thread_id _sigev_un._threadid +#endif +#define sigev_notify_function _sigev_un._sigev_thread._function +#define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +#define SIGEV_NONE 0 /* No async notification. */ +#define SIGEV_SIGNAL 1 /* Generate a queued signal. */ +#define SIGEV_THREAD 2 /* Call back from another pthread. */ +#if __BSD_VISIBLE +#define SIGEV_KEVENT 3 /* Generate a kevent. */ +#define SIGEV_THREAD_ID 4 /* Send signal to a kernel thread. */ #endif -/* - * XXX missing SIGEV_THREAD. - */ #endif /* __POSIX_VISIBLE >= 199309 */ #if __POSIX_VISIBLE >= 199309 || __XSI_VISIBLE diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 124ff970301d..cde9742dfcae 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -199,6 +199,15 @@ __sigseteq(sigset_t *set1, sigset_t *set2) return (1); } +struct osigevent { + int sigev_notify; /* Notification type */ + union { + int __sigev_signo; /* Signal number */ + int __sigev_notify_kqueue; + } __sigev_u; + union sigval sigev_value; /* Signal value */ +}; + typedef struct ksiginfo { TAILQ_ENTRY(ksiginfo) ksi_link; siginfo_t ksi_info;