diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 03775961744c..584ffe58be22 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -697,16 +697,19 @@ 398 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \ struct statfs *buf); } 399 AUE_NULL UNIMPL nosys -; XXX implement these? -400 AUE_NULL UNIMPL ksem_close -401 AUE_NULL UNIMPL ksem_post -402 AUE_NULL UNIMPL ksem_wait -403 AUE_NULL UNIMPL ksem_trywait -404 AUE_NULL UNIMPL ksem_init -405 AUE_NULL UNIMPL ksem_open -406 AUE_NULL UNIMPL ksem_unlink -407 AUE_NULL UNIMPL ksem_getvalue -408 AUE_NULL UNIMPL ksem_destroy +400 AUE_NULL NOSTD|NOPROTO { int ksem_close(semid_t id); } +401 AUE_NULL NOSTD|NOPROTO { int ksem_post(semid_t id); } +402 AUE_NULL NOSTD|NOPROTO { int ksem_wait(semid_t id); } +403 AUE_NULL NOSTD|NOPROTO { int ksem_trywait(semid_t id); } +404 AUE_NULL NOSTD { int freebsd32_ksem_init(semid_t *idp, \ + unsigned int value); } +405 AUE_NULL NOSTD { int freebsd32_ksem_open(semid_t *idp, \ + const char *name, int oflag, \ + mode_t mode, unsigned int value); } +406 AUE_NULL NOSTD|NOPROTO { int ksem_unlink(const char *name); } +407 AUE_NULL NOSTD|NOPROTO { int ksem_getvalue(semid_t id, \ + int *val); } +408 AUE_NULL NOSTD|NOPROTO { int ksem_destroy(semid_t id); } 409 AUE_NULL UNIMPL __mac_get_pid 410 AUE_NULL UNIMPL __mac_get_link 411 AUE_NULL UNIMPL __mac_set_link @@ -765,7 +768,8 @@ const char *path, int attrnamespace, \ void *data, size_t nbytes); } 440 AUE_NULL UNIMPL kse_switchin -441 AUE_NULL UNIMPL ksem_timedwait +441 AUE_NULL NOSTD { int freebsd32_ksem_timedwait(semid_t id, \ + const struct timespec32 *abstime); } 442 AUE_NULL STD { int freebsd32_thr_suspend( \ const struct timespec32 *timeout); } 443 AUE_NULL NOPROTO { int thr_wake(long id); } diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index f41b49c63b97..a6b2f75f4013 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -34,6 +34,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_posix.h" #include @@ -112,7 +113,7 @@ static struct ksem *ksem_alloc(struct ucred *ucred, mode_t mode, unsigned int value); static int ksem_create(struct thread *td, const char *path, semid_t *semidp, mode_t mode, unsigned int value, - int flags); + int flags, int compat32); static void ksem_drop(struct ksem *ks); static int ksem_get(struct thread *td, semid_t id, struct file **fpp); static struct ksem *ksem_hold(struct ksem *ks); @@ -374,16 +375,44 @@ ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred) return (ENOENT); } +static int +ksem_create_copyout_semid(struct thread *td, semid_t *semidp, int fd, + int compat32) +{ + semid_t semid; +#ifdef COMPAT_FREEBSD32 + int32_t semid32; +#endif + void *ptr; + size_t ptrs; + +#ifdef COMPAT_FREEBSD32 + if (compat32) { + semid32 = fd; + ptr = &semid32; + ptrs = sizeof(semid32); + } else { +#endif + semid = fd; + ptr = &semid; + ptrs = sizeof(semid); + compat32 = 0; /* silence gcc */ +#ifdef COMPAT_FREEBSD32 + } +#endif + + return (copyout(ptr, semidp, ptrs)); +} + /* Other helper routines. */ static int ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, - unsigned int value, int flags) + unsigned int value, int flags, int compat32) { struct filedesc *fdp; struct ksem *ks; struct file *fp; char *path; - semid_t semid; Fnv32_t fnv; int error, fd; @@ -404,8 +433,7 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, * premature, but it is a lot easier to handle errors as opposed * to later when we've possibly created a new semaphore, etc. */ - semid = fd; - error = copyout(&semid, semidp, sizeof(semid)); + error = ksem_create_copyout_semid(td, semidp, fd, compat32); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); @@ -530,7 +558,7 @@ ksem_init(struct thread *td, struct ksem_init_args *uap) { return (ksem_create(td, NULL, uap->idp, S_IRWXU | S_IRWXG, uap->value, - 0)); + 0, 0)); } #ifndef _SYS_SYSPROTO_H_ @@ -551,7 +579,7 @@ ksem_open(struct thread *td, struct ksem_open_args *uap) if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0) return (EINVAL); return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value, - uap->oflag)); + uap->oflag, 0)); } #ifndef _SYS_SYSPROTO_H_ @@ -832,38 +860,85 @@ ksem_destroy(struct thread *td, struct ksem_destroy_args *uap) return (error); } -#define SYSCALL_DATA(syscallname) \ -static int syscallname##_syscall = SYS_##syscallname; \ -static int syscallname##_registered; \ -static struct sysent syscallname##_old_sysent; \ -MAKE_SYSENT(syscallname); +static struct syscall_helper_data ksem_syscalls[] = { + SYSCALL_INIT_HELPER(ksem_init), + SYSCALL_INIT_HELPER(ksem_open), + SYSCALL_INIT_HELPER(ksem_unlink), + SYSCALL_INIT_HELPER(ksem_close), + SYSCALL_INIT_HELPER(ksem_post), + SYSCALL_INIT_HELPER(ksem_wait), + SYSCALL_INIT_HELPER(ksem_timedwait), + SYSCALL_INIT_HELPER(ksem_trywait), + SYSCALL_INIT_HELPER(ksem_getvalue), + SYSCALL_INIT_HELPER(ksem_destroy), + SYSCALL_INIT_LAST +}; -#define SYSCALL_REGISTER(syscallname) do { \ - error = syscall_register(& syscallname##_syscall, \ - & syscallname##_sysent, & syscallname##_old_sysent); \ - if (error) \ - return (error); \ - syscallname##_registered = 1; \ -} while(0) +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include -#define SYSCALL_DEREGISTER(syscallname) do { \ - if (syscallname##_registered) { \ - syscallname##_registered = 0; \ - syscall_deregister(& syscallname##_syscall, \ - & syscallname##_old_sysent); \ - } \ -} while(0) +int +freebsd32_ksem_init(struct thread *td, struct freebsd32_ksem_init_args *uap) +{ -SYSCALL_DATA(ksem_init); -SYSCALL_DATA(ksem_open); -SYSCALL_DATA(ksem_unlink); -SYSCALL_DATA(ksem_close); -SYSCALL_DATA(ksem_post); -SYSCALL_DATA(ksem_wait); -SYSCALL_DATA(ksem_timedwait); -SYSCALL_DATA(ksem_trywait); -SYSCALL_DATA(ksem_getvalue); -SYSCALL_DATA(ksem_destroy); + return (ksem_create(td, NULL, uap->idp, S_IRWXU | S_IRWXG, uap->value, + 0, 1)); +} + +int +freebsd32_ksem_open(struct thread *td, struct freebsd32_ksem_open_args *uap) +{ + + if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0) + return (EINVAL); + return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value, + uap->oflag, 1)); +} + +int +freebsd32_ksem_timedwait(struct thread *td, + struct freebsd32_ksem_timedwait_args *uap) +{ + struct timespec32 abstime32; + struct timespec *ts, abstime; + int error; + + /* + * We allow a null timespec (wait forever). + */ + if (uap->abstime == NULL) + ts = NULL; + else { + error = copyin(uap->abstime, &abstime32, sizeof(abstime32)); + if (error != 0) + return (error); + CP(abstime32, abstime, tv_sec); + CP(abstime32, abstime, tv_nsec); + if (abstime.tv_nsec >= 1000000000 || abstime.tv_nsec < 0) + return (EINVAL); + ts = &abstime; + } + return (kern_sem_wait(td, uap->id, 0, ts)); +} + +static struct syscall_helper_data ksem32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_ksem_init), + SYSCALL32_INIT_HELPER(freebsd32_ksem_open), + SYSCALL32_INIT_HELPER(ksem_unlink), + SYSCALL32_INIT_HELPER(ksem_close), + SYSCALL32_INIT_HELPER(ksem_post), + SYSCALL32_INIT_HELPER(ksem_wait), + SYSCALL32_INIT_HELPER(freebsd32_ksem_timedwait), + SYSCALL32_INIT_HELPER(ksem_trywait), + SYSCALL32_INIT_HELPER(ksem_getvalue), + SYSCALL32_INIT_HELPER(ksem_destroy), + SYSCALL_INIT_LAST +}; +#endif static int ksem_module_init(void) @@ -877,16 +952,14 @@ ksem_module_init(void) p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX); p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX); - SYSCALL_REGISTER(ksem_init); - SYSCALL_REGISTER(ksem_open); - SYSCALL_REGISTER(ksem_unlink); - SYSCALL_REGISTER(ksem_close); - SYSCALL_REGISTER(ksem_post); - SYSCALL_REGISTER(ksem_wait); - SYSCALL_REGISTER(ksem_timedwait); - SYSCALL_REGISTER(ksem_trywait); - SYSCALL_REGISTER(ksem_getvalue); - SYSCALL_REGISTER(ksem_destroy); + error = syscall_helper_register(ksem_syscalls); + if (error) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(ksem32_syscalls); + if (error) + return (error); +#endif return (0); } @@ -894,16 +967,10 @@ static void ksem_module_destroy(void) { - SYSCALL_DEREGISTER(ksem_init); - SYSCALL_DEREGISTER(ksem_open); - SYSCALL_DEREGISTER(ksem_unlink); - SYSCALL_DEREGISTER(ksem_close); - SYSCALL_DEREGISTER(ksem_post); - SYSCALL_DEREGISTER(ksem_wait); - SYSCALL_DEREGISTER(ksem_timedwait); - SYSCALL_DEREGISTER(ksem_trywait); - SYSCALL_DEREGISTER(ksem_getvalue); - SYSCALL_DEREGISTER(ksem_destroy); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(ksem32_syscalls); +#endif + syscall_helper_unregister(ksem_syscalls); hashdestroy(ksem_dictionary, M_KSEM, ksem_hash); sx_destroy(&ksem_dict_lock);