Author: kib
Date: Fri Mar 19 11:08:43 2010
New Revision: 205324
URL: http://svn.freebsd.org/changeset/base/205324

Log:
  Implement compat32 shims for ksem syscalls.
  
  Reviewed by:  jhb
  MFC after:    2 weeks

Modified:
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/uipc_sem.c

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master   Fri Mar 19 11:04:42 2010        
(r205323)
+++ head/sys/compat/freebsd32/syscalls.master   Fri Mar 19 11:08:43 2010        
(r205324)
@@ -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); }

Modified: head/sys/kern/uipc_sem.c
==============================================================================
--- head/sys/kern/uipc_sem.c    Fri Mar 19 11:04:42 2010        (r205323)
+++ head/sys/kern/uipc_sem.c    Fri Mar 19 11:08:43 2010        (r205324)
@@ -34,6 +34,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_compat.h"
 #include "opt_posix.h"
 
 #include <sys/param.h>
@@ -112,7 +113,7 @@ static struct ksem *ksem_alloc(struct uc
                    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, str
        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 cha
         * 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
 {
 
        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
        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 @@ err:
        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);
-
-#define        SYSCALL_REGISTER(syscallname) do {                              
\
-       error = syscall_register(& syscallname##_syscall,               \
-           & syscallname##_sysent, & syscallname##_old_sysent);        \
-       if (error)                                                      \
-               return (error);                                         \
-       syscallname##_registered = 1;                                   \
-} while(0)
-
-#define        SYSCALL_DEREGISTER(syscallname) do {                            
\
-       if (syscallname##_registered) {                                 \
-               syscallname##_registered = 0;                           \
-               syscall_deregister(& syscallname##_syscall,             \
-                   & syscallname##_old_sysent);                        \
-       }                                                               \
-} while(0)
-
-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);
+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
+};
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/freebsd32/freebsd32_syscall.h>
+#include <compat/freebsd32/freebsd32_util.h>
+
+int
+freebsd32_ksem_init(struct thread *td, struct freebsd32_ksem_init_args *uap)
+{
+
+       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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to