Module: xenomai-gch
Branch: for-forge
Commit: 9dc2882c499fab4ff111e661012ee62ce4c26cdf
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=9dc2882c499fab4ff111e661012ee62ce4c26cdf

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Tue Nov 22 00:57:00 2011 +0100

cobalt: move semaphore syscalls to sem.c

---

 include/cobalt/semaphore.h |   39 +---
 kernel/cobalt/internal.h   |    2 -
 kernel/cobalt/sem.c        |  608 ++++++++++++++++++++++++--------------------
 kernel/cobalt/sem.h        |   47 +++-
 kernel/cobalt/syscall.c    |  311 ++---------------------
 kernel/cobalt/timer.c      |    8 +-
 lib/cobalt/semaphore.c     |  118 ++++++---
 7 files changed, 464 insertions(+), 669 deletions(-)

diff --git a/include/cobalt/semaphore.h b/include/cobalt/semaphore.h
index 3804bcb..c7a29c3 100644
--- a/include/cobalt/semaphore.h
+++ b/include/cobalt/semaphore.h
@@ -69,44 +69,7 @@ union __xeno_sem {
     } shadow_sem;
 };
 
-#if defined(__KERNEL__) || defined(__XENO_SIM__)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#undef sem_init
-#define sem_init cobalt_sem_init
-
-int cobalt_sem_init(sem_t *sem,
-                   int pshared,
-                   unsigned int value);
-
-int sem_destroy(sem_t *sem);
-
-int sem_post(sem_t *sem);
-
-int sem_trywait(sem_t *sem);
-
-int sem_wait(sem_t *sem);
-
-int sem_timedwait(sem_t *sem,
-                 const struct timespec *abs_timeout);
-
-int sem_getvalue(sem_t *sem,
-                int *value);
-
-sem_t *sem_open(const char *name, int oflag, ...);
-
-int sem_close(sem_t *sem);
-
-int sem_unlink(const char *name);
-
-#ifdef __cplusplus
-}
-#endif
-
-#else /* !(__KERNEL__ || __XENO_SIM__) */
+#if !(defined(__KERNEL__) || defined(__XENO_SIM__))
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/kernel/cobalt/internal.h b/kernel/cobalt/internal.h
index 1d5237f..280c5e7 100644
--- a/kernel/cobalt/internal.h
+++ b/kernel/cobalt/internal.h
@@ -38,13 +38,11 @@
 #define COBALT_THREAD_ATTR_MAGIC COBALT_MAGIC(02)
 #define COBALT_MUTEX_ATTR_MAGIC  (COBALT_MAGIC(04) & ((1 << 24) - 1))
 #define COBALT_COND_ATTR_MAGIC   (COBALT_MAGIC(06) & ((1 << 24) - 1))
-#define COBALT_SEM_MAGIC         COBALT_MAGIC(07)
 #define COBALT_KEY_MAGIC         COBALT_MAGIC(08)
 #define COBALT_ONCE_MAGIC        COBALT_MAGIC(09)
 #define COBALT_MQ_MAGIC          COBALT_MAGIC(0A)
 #define COBALT_MQD_MAGIC         COBALT_MAGIC(0B)
 #define COBALT_INTR_MAGIC        COBALT_MAGIC(0C)
-#define COBALT_NAMED_SEM_MAGIC   COBALT_MAGIC(0D)
 #define COBALT_TIMER_MAGIC       COBALT_MAGIC(0E)
 #define COBALT_SHM_MAGIC         COBALT_MAGIC(0F)
 
diff --git a/kernel/cobalt/sem.c b/kernel/cobalt/sem.c
index 0184f67..75ea1c1 100644
--- a/kernel/cobalt/sem.c
+++ b/kernel/cobalt/sem.c
@@ -62,7 +62,7 @@ typedef struct cobalt_named_sem {
        union __xeno_sem descriptor;
 } nsem_t;
 
-#define sem2named_sem(saddr) ((nsem_t *) (saddr))
+#define sem2named_sem(saddr) ((nsem_t *)(saddr))
 #define node2sem(naddr) container_of(naddr, nsem_t, nodebase)
 
 #ifndef __XENO_SIM__
@@ -78,7 +78,7 @@ typedef struct cobalt_uptr {
 
 #endif /* !__XENO_SIM__ */
 
-static int sem_destroy_inner(cobalt_sem_t * sem, cobalt_kqueues_t *q)
+static int sem_destroy_inner(cobalt_sem_t *sem, cobalt_kqueues_t *q)
 {
        int ret = 0;
        spl_t s;
@@ -100,12 +100,12 @@ static int sem_destroy_inner(cobalt_sem_t * sem, 
cobalt_kqueues_t *q)
 }
 
 /* Called with nklock locked, irq off. */
-static int sem_init_inner(cobalt_sem_t * sem, int flags, unsigned int value)
+static int sem_init_inner(cobalt_sem_t *sem, int flags, unsigned int value)
 {
        int pshared, sflags;
 
        if (value > (unsigned)SEM_VALUE_MAX)
-               return EINVAL;
+               return -EINVAL;
 
        pshared = !!(flags & SEM_PSHARED);
        sflags = flags & SEM_FIFO ? 0 : XNSYNCH_PRIO;
@@ -121,37 +121,32 @@ static int sem_init_inner(cobalt_sem_t * sem, int flags, 
unsigned int value)
        return 0;
 }
 
-static int do_sem_init(sem_t *sm, int flags, unsigned int value)
+static int do_sem_init(struct __shadow_sem *sm, int flags, unsigned int value)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        xnholder_t *holder;
        cobalt_sem_t *sem;
        xnqueue_t *semq;
        int ret;
        spl_t s;
 
-       if ((flags & SEM_PULSE) != 0 && value > 0) {
-               ret = EINVAL;
-               goto error;
-       }
+       if ((flags & SEM_PULSE) != 0 && value > 0)
+               return -EINVAL;
 
-       sem = xnmalloc(sizeof(cobalt_sem_t));
-       if (sem == NULL) {
-               ret = ENOSPC;
-               goto error;
-       }
+       sem = (cobalt_sem_t *)xnmalloc(sizeof(*sem));
+       if (sem == NULL)
+               return -ENOSPC;
 
        xnlock_get_irqsave(&nklock, s);
 
        semq = &cobalt_kqueues(!!(flags & SEM_PSHARED))->semq;
 
-       if (shadow->magic == COBALT_SEM_MAGIC
-           || shadow->magic == COBALT_NAMED_SEM_MAGIC
-           || shadow->magic == ~COBALT_NAMED_SEM_MAGIC) {
+       if (sm->magic == COBALT_SEM_MAGIC
+           || sm->magic == COBALT_NAMED_SEM_MAGIC
+           || sm->magic == ~COBALT_NAMED_SEM_MAGIC) {
                for (holder = getheadq(semq); holder;
                     holder = nextq(semq, holder))
-                       if (holder == &shadow->sem->link) {
-                               ret = EBUSY;
+                       if (holder == &sm->sem->link) {
+                               ret = -EBUSY;
                                goto err_lock_put;
                        }
        }
@@ -160,8 +155,8 @@ static int do_sem_init(sem_t *sm, int flags, unsigned int 
value)
        if (ret)
                goto err_lock_put;
 
-       shadow->magic = COBALT_SEM_MAGIC;
-       shadow->sem = sem;
+       sm->magic = COBALT_SEM_MAGIC;
+       sm->sem = sem;
        xnlock_put_irqrestore(&nklock, s);
 
        return 0;
@@ -169,101 +164,8 @@ static int do_sem_init(sem_t *sm, int flags, unsigned int 
value)
   err_lock_put:
        xnlock_put_irqrestore(&nklock, s);
        xnfree(sem);
-  error:
-       thread_set_errno(ret);
-
-       return -1;
-}
-
-/**
- * Initialize an unnamed semaphore.
- *
- * This service initializes the semaphore @a sm, with the value @a value.
- *
- * This service fails if @a sm is already initialized or is a named semaphore.
- *
- * @param sm the semaphore to be initialized;
- *
- * @param pshared if zero, means that the new semaphore may only be used by
- * threads in the same process as the thread calling sem_init(); if non zero,
- * means that the new semaphore may be used by any thread that has access to 
the
- * memory where the semaphore is allocated.
- *
- * @param value the semaphore initial value.
- *
- * @retval 0 on success,
- * @retval -1 with @a errno set if:
- * - EBUSY, the semaphore @a sm was already initialized;
- * - ENOSPC, insufficient memory exists in the system heap to initialize the
- *   semaphore, increase CONFIG_XENO_OPT_SYS_HEAPSZ;
- * - EINVAL, the @a value argument exceeds @a SEM_VALUE_MAX.
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/sem_init.html";>
- * Specification.</a>
- *
- */
-int sem_init(sem_t *sm, int pshared, unsigned int value)
-{
-       return do_sem_init(sm, pshared ? SEM_PSHARED : 0, value);
-}
 
-/**
- * Initialize a non-standard, extended semaphore.
- *
- * This service initializes the unnamed semaphore @a sm, with the
- * value @a value. An additional set of flags allows to specify a
- * non-standard behavior for the semaphore.
- *
- * This service fails if @a sm is already initialized or is a named semaphore.
- *
- * @param sm the semaphore to be initialized;
- *
- * @param flags A set of extension flags. The following flags can be
- * OR'ed into this bitmask, each of them affecting the new semaphore:
- *
- * - SEM_FIFO makes threads pend by FIFO order on the semaphore. By
- * default, threads pend by priority order.
- *
- * - SEM_PULSE causes the semaphore to behave in "pulse" mode. In this
- * mode, sem_post() attempts to release a single waiter each time it
- * is called, but without incrementing the semaphore count if no
- * waiter is pending. For this reason, the semaphore count in pulse
- * mode remains zero. If SEM_PULSE is mentioned, @a value can only be
- * zero.
- *
- * - SEM_PSHARED controls the scope of the new semaphore. When set, it
- * has the same meaning as passing 1 for the pshared parameter to the
- * regular sem_init() call.
- *
- * - SEM_REPORT tells whether sem_getvalue() should report the number
- * of waiters as a negative value, for a fully depleted semaphore. By
- * default, sem_getvalue() returns a current value of zero for a
- * depleted semaphore with waiters.
- *
- * - SEM_WARNDEL causes sem_destroy() to return a strictly positive
- *   value instead of zero, in case threads were pending on the
- *   successfully deleted semaphore.
- *
- * @param value the semaphore initial value.
- *
- * @retval 0 on success,
- * @retval -1 with @a errno set if:
- * - EBUSY, the semaphore @a sm was already initialized;
- * - ENOSPC, insufficient memory exists in the system heap to initialize the
- *   semaphore, increase CONFIG_XENO_OPT_SYS_HEAPSZ;
- * - EINVAL, the @a value argument exceeds @a SEM_VALUE_MAX, or this
- * value is non-zero albeit SEM_PULSE is mentioned in @a flags. EINVAL
- * is also returned if an invalid flag appears in @a flags.
- */
-int sem_init_np(sem_t *sm, int flags, unsigned int value)
-{
-       if (flags & ~(SEM_FIFO|SEM_PULSE|SEM_PSHARED|SEM_REPORT|SEM_WARNDEL)) {
-               thread_set_errno(EINVAL);
-               return -1;
-       }
-
-       return do_sem_init(sm, flags, value);
+       return ret;
 }
 
 /**
@@ -293,28 +195,27 @@ int sem_init_np(sem_t *sm, int flags, unsigned int value)
  * Specification.</a>
  *
  */
-int sem_destroy(sem_t * sm)
+static int sem_destroy(struct __shadow_sem *sm)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        cobalt_sem_t *sem;
        int warn, ret;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
-       if (shadow->magic != COBALT_SEM_MAGIC
-           || shadow->sem->magic != COBALT_SEM_MAGIC) {
-               thread_set_errno(EINVAL);
+       if (sm->magic != COBALT_SEM_MAGIC
+           || sm->sem->magic != COBALT_SEM_MAGIC) {
+               ret = -EINVAL;
                goto error;
        }
 
-       sem = shadow->sem;
+       sem = sm->sem;
        if (sem_kqueue(sem) != sem->owningq) {
-               thread_set_errno(EPERM);
+               ret = -EPERM;
                goto error;
        }
 
        warn = sem->flags & SEM_WARNDEL;
-       cobalt_mark_deleted(shadow);
+       cobalt_mark_deleted(sm);
        cobalt_mark_deleted(sem);
        xnlock_put_irqrestore(&nklock, s);
 
@@ -326,7 +227,7 @@ int sem_destroy(sem_t * sm)
 
        xnlock_put_irqrestore(&nklock, s);
 
-       return -1;
+       return ret;
 }
 
 /**
@@ -383,7 +284,7 @@ sem_t *sem_open(const char *name, int oflags, ...)
        int err;
 
        xnlock_get_irqsave(&nklock, s);
-       err = cobalt_node_get(&node, name, COBALT_NAMED_SEM_MAGIC, oflags);
+       err = -cobalt_node_get(&node, name, COBALT_NAMED_SEM_MAGIC, oflags);
        xnlock_put_irqrestore(&nklock, s);
 
        if (err)
@@ -394,9 +295,9 @@ sem_t *sem_open(const char *name, int oflags, ...)
                goto got_sem;
        }
 
-       named_sem = (nsem_t *) xnmalloc(sizeof(*named_sem));
+       named_sem = (nsem_t *)xnmalloc(sizeof(*named_sem));
        if (!named_sem) {
-               err = ENOSPC;
+               err = -ENOSPC;
                goto error;
        }
        named_sem->descriptor.shadow_sem.sem = &named_sem->sembase;
@@ -414,12 +315,12 @@ sem_t *sem_open(const char *name, int oflags, ...)
                goto error;
        }
 
-       err = cobalt_node_add(&named_sem->nodebase, name, 
COBALT_NAMED_SEM_MAGIC);
-       if (err && err != EEXIST)
+       err = -cobalt_node_add(&named_sem->nodebase, name, 
COBALT_NAMED_SEM_MAGIC);
+       if (err && err != -EEXIST)
                goto err_put_lock;
 
-       if (err == EEXIST) {
-               err = cobalt_node_get(&node, name, COBALT_NAMED_SEM_MAGIC, 
oflags);
+       if (err == -EEXIST) {
+               err = -cobalt_node_get(&node, name, COBALT_NAMED_SEM_MAGIC, 
oflags);
                if (err)
                        goto err_put_lock;
 
@@ -441,8 +342,7 @@ sem_t *sem_open(const char *name, int oflags, ...)
        xnlock_put_irqrestore(&nklock, s);
        sem_destroy_inner(&named_sem->sembase, sem_kqueue(&named_sem->sembase));
   error:
-       thread_set_errno(err);
-       return SEM_FAILED;
+       return (sem_t *)ERR_PTR(err);
 }
 
 /**
@@ -469,22 +369,21 @@ sem_t *sem_open(const char *name, int oflags, ...)
  * Specification.</a>
  *
  */
-int sem_close(sem_t * sm)
+int sem_close(struct __shadow_sem *sm)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        nsem_t *named_sem;
        spl_t s;
        int err;
 
        xnlock_get_irqsave(&nklock, s);
 
-       if (shadow->magic != COBALT_NAMED_SEM_MAGIC
-           || shadow->sem->magic != COBALT_SEM_MAGIC) {
+       if (sm->magic != COBALT_NAMED_SEM_MAGIC
+           || sm->sem->magic != COBALT_SEM_MAGIC) {
                err = EINVAL;
                goto error;
        }
 
-       named_sem = sem2named_sem(shadow->sem);
+       named_sem = sem2named_sem(sm->sem);
 
        err = cobalt_node_put(&named_sem->nodebase);
 
@@ -493,14 +392,14 @@ int sem_close(sem_t * sm)
 
        if (cobalt_node_removed_p(&named_sem->nodebase)) {
                /* unlink was called, and this semaphore is no longer 
referenced. */
-               cobalt_mark_deleted(shadow);
+               cobalt_mark_deleted(sm);
                cobalt_mark_deleted(&named_sem->sembase);
                xnlock_put_irqrestore(&nklock, s);
 
                sem_destroy_inner(&named_sem->sembase, cobalt_kqueues(1));
        } else if (!cobalt_node_ref_p(&named_sem->nodebase)) {
                /* this semaphore is no longer referenced, but not unlinked. */
-               cobalt_mark_deleted(shadow);
+               cobalt_mark_deleted(sm);
                xnlock_put_irqrestore(&nklock, s);
        } else
                xnlock_put_irqrestore(&nklock, s);
@@ -510,9 +409,7 @@ int sem_close(sem_t * sm)
       error:
        xnlock_put_irqrestore(&nklock, s);
 
-       thread_set_errno(err);
-
-       return -1;
+       return -err;
 }
 
 /**
@@ -567,29 +464,21 @@ int sem_unlink(const char *name)
       error:
        xnlock_put_irqrestore(&nklock, s);
 
-       thread_set_errno(err);
-
-       return -1;
+       return -err;
 }
 
-static inline int sem_trywait_internal(struct __shadow_sem *shadow)
+static inline int sem_trywait_internal(cobalt_sem_t *sem)
 {
-       cobalt_sem_t *sem;
-
-       if ((shadow->magic != COBALT_SEM_MAGIC
-            && shadow->magic != COBALT_NAMED_SEM_MAGIC)
-           || shadow->sem->magic != COBALT_SEM_MAGIC)
-               return EINVAL;
-
-       sem = shadow->sem;
+       if (sem->magic != COBALT_SEM_MAGIC)
+               return -EINVAL;
 
 #if XENO_DEBUG(POSIX)
        if (sem->owningq != sem_kqueue(sem))
-               return EPERM;
+               return -EPERM;
 #endif /* XENO_DEBUG(POSIX) */
 
        if (sem->value == 0)
-               return EAGAIN;
+               return -EAGAIN;
 
        --sem->value;
 
@@ -617,39 +506,30 @@ static inline int sem_trywait_internal(struct 
__shadow_sem *shadow)
  * Specification.</a>
  *
  */
-int sem_trywait(sem_t * sm)
+static int sem_trywait(cobalt_sem_t *sem)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        int err;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
-
-       err = sem_trywait_internal(shadow);
-
+       err = sem_trywait_internal(sem);
        xnlock_put_irqrestore(&nklock, s);
 
-       if (err) {
-               thread_set_errno(err);
-               return -1;
-       }
-
-       return 0;
+       return err;
 }
 
-static inline int sem_timedwait_internal(struct __shadow_sem *shadow,
-                                        int timed, xnticks_t to)
+static inline int
+sem_timedwait_internal(cobalt_sem_t *sem, int timed, xnticks_t to)
 {
-       cobalt_sem_t *sem = shadow->sem;
        xnthread_t *cur;
        int err;
 
        if (xnpod_unblockable_p())
-               return EPERM;
+               return -EPERM;
 
        cur = xnpod_current_thread();
 
-       if ((err = sem_trywait_internal(shadow)) != EAGAIN)
+       if ((err = sem_trywait_internal(sem)) != -EAGAIN)
                return err;
 
        thread_cancellation_point(cur);
@@ -663,13 +543,13 @@ static inline int sem_timedwait_internal(struct 
__shadow_sem *shadow,
        thread_cancellation_point(cur);
 
        if (xnthread_test_info(cur, XNRMID))
-               return EINVAL;
+               return -EINVAL;
 
        if (xnthread_test_info(cur, XNBREAK))
-               return EINTR;
+               return -EINTR;
 
        if (xnthread_test_info(cur, XNTIMEO))
-               return ETIMEDOUT;
+               return -ETIMEDOUT;
 
        return 0;
 }
@@ -707,22 +587,16 @@ static inline int sem_timedwait_internal(struct 
__shadow_sem *shadow,
  * Specification.</a>
  *
  */
-int sem_wait(sem_t * sm)
+static int sem_wait(cobalt_sem_t *sem)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        spl_t s;
        int err;
 
        xnlock_get_irqsave(&nklock, s);
-       err = sem_timedwait_internal(shadow, 0, XN_INFINITE);
+       err = sem_timedwait_internal(sem, 0, XN_INFINITE);
        xnlock_put_irqrestore(&nklock, s);
 
-       if (err) {
-               thread_set_errno(err);
-               return -1;
-       }
-
-       return 0;
+       return err;
 }
 
 /**
@@ -757,48 +631,33 @@ int sem_wait(sem_t * sm)
  * Specification.</a>
  *
  */
-int sem_timedwait(sem_t * sm, const struct timespec *abs_timeout)
+static int sem_timedwait(cobalt_sem_t *sem, const struct timespec *abs_timeout)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        spl_t s;
        int err;
 
-       if (abs_timeout->tv_nsec > ONE_BILLION) {
-               err = EINVAL;
-               goto error;
-       }
+       if (abs_timeout->tv_nsec > ONE_BILLION)
+               return -EINVAL;
 
        xnlock_get_irqsave(&nklock, s);
-       err = sem_timedwait_internal(shadow, 1, ts2ns(abs_timeout) + 1);
+       err = sem_timedwait_internal(sem, 1, ts2ns(abs_timeout) + 1);
        xnlock_put_irqrestore(&nklock, s);
 
-  error:
-       if (err) {
-               thread_set_errno(err);
-               return -1;
-       }
-
-       return 0;
+       return err;
 }
 
-int sem_post_inner(struct cobalt_sem *sem, cobalt_kqueues_t *ownq, int bcast)
+int sem_post_inner(cobalt_sem_t *sem, cobalt_kqueues_t *ownq, int bcast)
 {
-       if (sem->magic != COBALT_SEM_MAGIC) {
-               thread_set_errno(EINVAL);
-               return -1;
-       }
+       if (sem->magic != COBALT_SEM_MAGIC)
+               return -EINVAL;
 
 #if XENO_DEBUG(POSIX)
-       if (ownq && ownq != sem_kqueue(sem)) {
-               thread_set_errno(EPERM);
-               return -1;
-       }
+       if (ownq && ownq != sem_kqueue(sem))
+               return -EPERM;
 #endif /* XENO_DEBUG(POSIX) */
 
-       if (sem->value == SEM_VALUE_MAX) {
-               thread_set_errno(EAGAIN);
-               return -1;
-       }
+       if (sem->value == SEM_VALUE_MAX)
+               return -EINVAL;
 
        if (!bcast) {
                if (xnsynch_wakeup_one_sleeper(&sem->synchbase) != NULL)
@@ -838,23 +697,13 @@ int sem_post_inner(struct cobalt_sem *sem, 
cobalt_kqueues_t *ownq, int bcast)
  * Specification.</a>
  *
  */
-int sem_post(sem_t * sm)
+static int sem_post(cobalt_sem_t *sm)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
        int ret;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
-
-       if (shadow->magic != COBALT_SEM_MAGIC
-           && shadow->magic != COBALT_NAMED_SEM_MAGIC) {
-               thread_set_errno(EINVAL);
-               ret = -1;
-               goto out;
-       }
-
-       ret = sem_post_inner(shadow->sem, shadow->sem->owningq, 0);
-out:
+       ret = sem_post_inner(sm, sm->owningq, 0);
        xnlock_put_irqrestore(&nklock, s);
 
        return ret;
@@ -888,28 +737,22 @@ out:
  * Specification.</a>
  *
  */
-int sem_getvalue(sem_t * sm, int *value)
+int sem_getvalue(cobalt_sem_t *sem, int *value)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
-       cobalt_sem_t *sem;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
 
-       if ((shadow->magic != COBALT_SEM_MAGIC
-            && shadow->magic != COBALT_NAMED_SEM_MAGIC)
-           || shadow->sem->magic != COBALT_SEM_MAGIC) {
+       if (sem->magic != COBALT_SEM_MAGIC) {
                xnlock_put_irqrestore(&nklock, s);
-               thread_set_errno(EINVAL);
-               return -1;
-       }
 
-       sem = shadow->sem;
+               return -EINVAL;
+       }
 
        if (sem->owningq != sem_kqueue(sem)) {
                xnlock_put_irqrestore(&nklock, s);
-               thread_set_errno(EPERM);
-               return -1;
+
+               return -EPERM;
        }
 
        if (sem->value == 0 && (sem->flags & SEM_REPORT) != 0)
@@ -922,45 +765,259 @@ int sem_getvalue(sem_t * sm, int *value)
        return 0;
 }
 
-/**
- * Broadcast a semaphore.
- *
- * This service is a non-standard extension for broadcasting the
- * semaphore @a sm.
- *
- * All threads waiting on the semaphore are unblocked, as if the
- * semaphore has been signaled. The semaphore count is zeroed as a
- * result of the operation.
- *
- * @param sm the semaphore to be broadcast.
- *
- * @retval 0 on success;
- * @retval -1 with errno set if:
- * - EINVAL, the specified semaphore is invalid or uninitialized;
- * - EPERM, the semaphore @a sm is not process-shared and does not belong to 
the
- *   current process;
- *
- */
-int sem_broadcast_np(sem_t *sm)
+int cobalt_sem_init(struct __shadow_sem __user *u_sem, int pshared, unsigned 
value)
 {
-       struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem;
-       int ret;
+       struct __shadow_sem sm;
+       int err;
+
+       if (__xn_safe_copy_from_user(&sm, u_sem, sizeof(sm)))
+               return -EFAULT;
+
+       err = do_sem_init(&sm, pshared ? SEM_PSHARED : 0, value);
+       if (err < 0)
+               return err;
+
+       return __xn_safe_copy_to_user(u_sem, &sm, sizeof(*u_sem));
+}
+
+int cobalt_sem_post(struct __shadow_sem __user *u_sem)
+{
+       cobalt_sem_t *sm;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       return sem_post(sm);
+}
+
+int cobalt_sem_wait(struct __shadow_sem __user *u_sem)
+{
+       cobalt_sem_t *sm;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       return sem_wait(sm);
+}
+
+int cobalt_sem_timedwait(struct __shadow_sem __user *u_sem,
+                        struct timespec __user *u_ts)
+{
+       struct timespec ts;
+       cobalt_sem_t *sm;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       if (__xn_safe_copy_from_user(&ts, u_ts, sizeof(ts)))
+               return -EFAULT;
+
+       return sem_timedwait(sm, &ts);
+}
+
+int cobalt_sem_trywait(struct __shadow_sem __user *u_sem)
+{
+       cobalt_sem_t *sm;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       return sem_trywait(sm);
+}
+
+int cobalt_sem_getvalue(struct __shadow_sem __user *u_sem, int __user *u_sval)
+{
+       cobalt_sem_t *sm;
+       int err, sval;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       err = sem_getvalue(sm, &sval);
+       if (err < 0)
+               return err;
+
+       return __xn_safe_copy_to_user(u_sval, &sval, sizeof(sval));
+}
+
+int cobalt_sem_destroy(struct __shadow_sem __user *u_sem)
+{
+       struct __shadow_sem sm;
+       int err;
+
+       if (__xn_safe_copy_from_user(&sm, u_sem, sizeof(sm)))
+               return -EFAULT;
+
+       err = sem_destroy(&sm);
+       if (err < 0)
+               return err;
+
+       return __xn_safe_copy_to_user(u_sem, &sm, sizeof(*u_sem)) ?: err;
+}
+
+int cobalt_sem_open(unsigned long __user *u_addr,
+                   const char __user *u_name,
+                   int oflags, mode_t mode, unsigned value)
+{
+       char name[COBALT_MAXNAME];
+       struct __shadow_sem *sm;
+       cobalt_assoc_t *assoc;
+       unsigned long uaddr;
+       cobalt_usem_t *usm;
+       long len;
+       int err;
        spl_t s;
 
-       xnlock_get_irqsave(&nklock, s);
+       if (__xn_safe_copy_from_user(&uaddr, u_addr, sizeof(uaddr)))
+               return -EFAULT;
+
+       len = __xn_safe_strncpy_from_user(name, u_name, sizeof(name));
+       if (len < 0)
+               return len;
+       if (len >= sizeof(name))
+               return -ENAMETOOLONG;
+       if (len == 0)
+               return -EINVAL;
+
+       if (!(oflags & O_CREAT))
+               sm = &((union __xeno_sem *)sem_open(name, oflags))->shadow_sem;
+       else
+               sm = &((union __xeno_sem *)sem_open(name, oflags, mode, 
value))->shadow_sem;
+
+       if (IS_ERR(sm))
+               return PTR_ERR(sm);
 
-       if (shadow->magic != COBALT_SEM_MAGIC
-           && shadow->magic != COBALT_NAMED_SEM_MAGIC) {
-               thread_set_errno(EINVAL);
-               ret = -1;
-               goto out;
+       xnlock_get_irqsave(&cobalt_assoc_lock, s);
+       assoc = cobalt_assoc_lookup(&cobalt_queues()->usems, (u_long)sm->sem);
+
+       if (assoc) {
+               usm = assoc2usem(assoc);
+               ++usm->refcnt;
+               xnlock_put_irqrestore(&nklock, s);
+               goto got_usm;
+       }
+
+       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
+
+       usm = xnmalloc(sizeof(*usm));
+       if (usm == NULL) {
+               sem_close(sm);
+               return -ENOSPC;
        }
 
-       ret = sem_post_inner(shadow->sem, shadow->sem->owningq, 1);
-out:
+       usm->uaddr = uaddr;
+       usm->refcnt = 1;
+
+       xnlock_get_irqsave(&cobalt_assoc_lock, s);
+       assoc =
+           cobalt_assoc_lookup(&cobalt_queues()->usems, (u_long)sm->sem);
+
+       if (assoc) {
+               assoc2usem(assoc)->refcnt++;
+               xnlock_put_irqrestore(&nklock, s);
+               xnfree(usm);
+               usm = assoc2usem(assoc);
+               goto got_usm;
+       }
+
+       cobalt_assoc_insert(&cobalt_queues()->usems,
+                           &usm->assoc, (u_long)sm->sem);
+       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
+
+      got_usm:
+
+       if (usm->uaddr == uaddr)
+               /* First binding by this process. */
+               err = __xn_safe_copy_to_user((void __user *)usm->uaddr,
+                                            sm, sizeof(*sm));
+       else
+               /* Semaphore already bound by this process in user-space. */
+               err = __xn_safe_copy_to_user(u_addr,
+                                            &usm->uaddr, sizeof(*u_addr));
+
+       return err;
+}
+
+int cobalt_sem_close(unsigned long uaddr, int __user *u_closed)
+{
+       struct __shadow_sem sm;
+       cobalt_assoc_t *assoc;
+       int closed = 0, err;
+       cobalt_usem_t *usm;
+       spl_t s;
+
+       if (__xn_safe_copy_from_user(&sm, (void __user *)uaddr, sizeof(sm)))
+               return -EFAULT;
+
+       xnlock_get_irqsave(&cobalt_assoc_lock, s);
+
+       assoc =
+           cobalt_assoc_lookup(&cobalt_queues()->usems, (u_long)sm.sem);
+
+       if (!assoc) {
+               xnlock_put_irqrestore(&cobalt_assoc_lock, s);
+               return -EINVAL;
+       }
+
+       usm = assoc2usem(assoc);
+
+       err = sem_close(&sm);
+
+       if (!err && (closed = (--usm->refcnt == 0)))
+               cobalt_assoc_remove(&cobalt_queues()->usems, (u_long)sm.sem);
+
+       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
+
+       if (err < 0)
+               return err;
+
+       if (closed)
+               xnfree(usm);
+
+       return __xn_safe_copy_to_user(u_closed, &closed, sizeof(*u_closed));
+}
+
+int cobalt_sem_unlink(const char __user *u_name)
+{
+       char name[COBALT_MAXNAME];
+       long len;
+
+       len = __xn_safe_strncpy_from_user(name, u_name, sizeof(name));
+       if (len < 0)
+               return len;
+       if (len >= sizeof(name))
+               return -ENAMETOOLONG;
+
+       return sem_unlink(name);
+}
+
+int cobalt_sem_init_np(struct __shadow_sem __user *u_sem,
+                      int flags, unsigned value)
+{
+       struct __shadow_sem sm;
+       int err;
+
+       if (__xn_safe_copy_from_user(&sm, u_sem, sizeof(sm)))
+               return -EFAULT;
+
+       if (flags & ~(SEM_FIFO|SEM_PULSE|SEM_PSHARED|SEM_REPORT|SEM_WARNDEL))
+               return -EINVAL;
+
+       err = do_sem_init(&sm, flags, value);
+       if (err < 0)
+               return err;
+
+       return __xn_safe_copy_to_user(u_sem, &sm, sizeof(*u_sem));
+}
+
+int cobalt_sem_broadcast_np(struct __shadow_sem __user *u_sem)
+{
+       cobalt_sem_t *sm;
+       spl_t s;
+       int err;
+
+       __xn_get_user(sm, &u_sem->sem);
+
+       xnlock_get_irqsave(&nklock, s);
+       err = sem_post_inner(sm, sm->owningq, 1);
        xnlock_put_irqrestore(&nklock, s);
 
-       return ret;
+       return err;
 }
 
 #ifndef __XENO_SIM__
@@ -973,7 +1030,7 @@ static void usem_cleanup(cobalt_assoc_t *assoc)
 #if XENO_DEBUG(POSIX)
        xnprintf("Posix: closing semaphore \"%s\".\n", nsem->nodebase.name);
 #endif /* XENO_DEBUG(POSIX) */
-       sem_close(&nsem->descriptor.native_sem);
+       sem_close(&nsem->descriptor.shadow_sem);
        xnfree(usem);
 }
 
@@ -1025,16 +1082,3 @@ void cobalt_sem_pkg_cleanup(void)
 }
 
 /*@}*/
-
-EXPORT_SYMBOL_GPL(sem_init);
-EXPORT_SYMBOL_GPL(sem_destroy);
-EXPORT_SYMBOL_GPL(sem_post);
-EXPORT_SYMBOL_GPL(sem_trywait);
-EXPORT_SYMBOL_GPL(sem_wait);
-EXPORT_SYMBOL_GPL(sem_timedwait);
-EXPORT_SYMBOL_GPL(sem_getvalue);
-EXPORT_SYMBOL_GPL(sem_open);
-EXPORT_SYMBOL_GPL(sem_close);
-EXPORT_SYMBOL_GPL(sem_unlink);
-EXPORT_SYMBOL_GPL(sem_init_np);
-EXPORT_SYMBOL_GPL(sem_broadcast_np);
diff --git a/kernel/cobalt/sem.h b/kernel/cobalt/sem.h
index e2a73e2..7cff922 100644
--- a/kernel/cobalt/sem.h
+++ b/kernel/cobalt/sem.h
@@ -23,20 +23,53 @@
                                   cobalt_thread_t definition. */
 #include <nucleus/registry.h>     /* For assocq */
 
-#ifndef __XENO_SIM__
+#ifdef __KERNEL__
 
 typedef struct {
     u_long uaddr;
     unsigned refcnt;
     cobalt_assoc_t assoc;
 
-#define assoc2usem(laddr) \
-    ((cobalt_usem_t *)((unsigned long) (laddr) - offsetof(cobalt_usem_t, 
assoc)))
+#define assoc2usem(laddr) container_of(laddr, cobalt_usem_t, assoc)
 } cobalt_usem_t;
 
 void cobalt_sem_usems_cleanup(cobalt_queues_t *q);
 
-#endif /* !__XENO_SIM__ */
+struct cobalt_sem;
+
+int sem_getvalue(struct cobalt_sem *sem, int *value);
+
+int sem_post_inner(struct cobalt_sem *sem,
+                  cobalt_kqueues_t *ownq, int bcast);
+
+int cobalt_sem_init(struct __shadow_sem __user *u_sem,
+                   int pshared, unsigned value);
+
+int cobalt_sem_post(struct __shadow_sem __user *u_sem);
+
+int cobalt_sem_wait(struct __shadow_sem __user *u_sem);
+
+int cobalt_sem_timedwait(struct __shadow_sem __user *u_sem,
+                        struct timespec __user *u_ts);
+
+int cobalt_sem_trywait(struct __shadow_sem __user *u_sem);
+
+int cobalt_sem_getvalue(struct __shadow_sem __user *u_sem, int __user *u_sval);
+
+int cobalt_sem_destroy(struct __shadow_sem __user *u_sem);
+
+int cobalt_sem_open(unsigned long __user *u_addr,
+                   const char __user *u_name,
+                   int oflags, mode_t mode, unsigned value);
+
+int cobalt_sem_close(unsigned long uaddr, int __user *u_closed);
+
+int cobalt_sem_unlink(const char __user *u_name);
+
+int cobalt_sem_init_np(struct __shadow_sem __user *u_sem,
+                      int flags, unsigned value);
+
+int cobalt_sem_broadcast_np(struct __shadow_sem __user *u_sem);
 
 void cobalt_semq_cleanup(cobalt_kqueues_t *q);
 
@@ -44,7 +77,9 @@ void cobalt_sem_pkg_init(void);
 
 void cobalt_sem_pkg_cleanup(void);
 
-int sem_post_inner(struct cobalt_sem *sem,
-                  cobalt_kqueues_t *ownq, int bcast);
+#endif /* __KERNEL__ */
+
+#define COBALT_SEM_MAGIC (0x86860707)
+#define COBALT_NAMED_SEM_MAGIC (0x86860D0D)
 
 #endif /* !_POSIX_SEM_H */
diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c
index 0233d8a..96c7634 100644
--- a/kernel/cobalt/syscall.c
+++ b/kernel/cobalt/syscall.c
@@ -584,286 +584,6 @@ static int __pthread_stat(unsigned long tid,
        return __xn_safe_copy_to_user(u_stat, &stat, sizeof(stat));
 }
 
-static int __sem_init(union __xeno_sem __user *u_sem,
-                     int pshared, unsigned value)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       if (sem_init(&sm.native_sem, pshared, value) == -1)
-               return -thread_get_errno();
-
-       return __xn_safe_copy_to_user(&u_sem->shadow_sem,
-                                     &sm.shadow_sem, 
sizeof(u_sem->shadow_sem));
-}
-
-static int __sem_post(union __xeno_sem __user *u_sem)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       return sem_post(&sm.native_sem) == 0 ? 0 : -thread_get_errno();
-}
-
-static int __sem_wait(union __xeno_sem __user *u_sem)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       return sem_wait(&sm.native_sem) == 0 ? 0 : -thread_get_errno();
-}
-
-static int __sem_timedwait(union __xeno_sem __user *u_sem,
-                          struct timespec __user *u_ts)
-{
-       union __xeno_sem sm;
-       struct timespec ts;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       if (__xn_safe_copy_from_user(&ts, u_ts, sizeof(ts)))
-               return -EFAULT;
-
-       return sem_timedwait(&sm.native_sem,
-                            &ts) == 0 ? 0 : -thread_get_errno();
-}
-
-static int __sem_trywait(union __xeno_sem __user *u_sem)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       return sem_trywait(&sm.native_sem) == 0 ? 0 : -thread_get_errno();
-}
-
-static int __sem_getvalue(union __xeno_sem __user *u_sem,
-                         int __user *u_sval)
-{
-       union __xeno_sem sm;
-       int err, sval;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       err = sem_getvalue(&sm.native_sem, &sval);
-       if (err)
-               return -thread_get_errno();
-
-       return __xn_safe_copy_to_user(u_sval, &sval, sizeof(sval));
-}
-
-static int __sem_destroy(union __xeno_sem __user *u_sem)
-{
-       union __xeno_sem sm;
-       int err;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       err = sem_destroy(&sm.native_sem);
-       if (err < 0)
-               return -thread_get_errno();
-
-       return __xn_safe_copy_to_user(&u_sem->shadow_sem,
-                                     &sm.shadow_sem, 
sizeof(u_sem->shadow_sem)) ?: err;
-}
-
-static int __sem_open(unsigned long __user *u_addr,
-                     const char __user *u_name,
-                     int oflags,
-                     mode_t mode,
-                     unsigned value)
-{
-       char name[COBALT_MAXNAME];
-       union __xeno_sem *sm;
-       cobalt_assoc_t *assoc;
-       unsigned long uaddr;
-       cobalt_usem_t *usm;
-       long len;
-       int err;
-       spl_t s;
-
-       if (__xn_safe_copy_from_user(&uaddr, u_addr, sizeof(uaddr)))
-               return -EFAULT;
-
-       len = __xn_safe_strncpy_from_user(name, u_name, sizeof(name));
-       if (len < 0)
-               return len;
-       if (len >= sizeof(name))
-               return -ENAMETOOLONG;
-       if (len == 0)
-               return -EINVAL;
-
-       if (!(oflags & O_CREAT))
-               sm = (union __xeno_sem *)sem_open(name, oflags);
-       else
-               sm = (union __xeno_sem *)sem_open(name, oflags, mode, value);
-
-       if (sm == SEM_FAILED)
-               return -thread_get_errno();
-
-       xnlock_get_irqsave(&cobalt_assoc_lock, s);
-       assoc = cobalt_assoc_lookup(&cobalt_queues()->usems,
-                                  (u_long)sm->shadow_sem.sem);
-
-       if (assoc) {
-               usm = assoc2usem(assoc);
-               ++usm->refcnt;
-               xnlock_put_irqrestore(&nklock, s);
-               goto got_usm;
-       }
-
-       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
-
-       usm = xnmalloc(sizeof(*usm));
-       if (usm == NULL) {
-               sem_close(&sm->native_sem);
-               return -ENOSPC;
-       }
-
-       usm->uaddr = uaddr;
-       usm->refcnt = 1;
-
-       xnlock_get_irqsave(&cobalt_assoc_lock, s);
-       assoc =
-           cobalt_assoc_lookup(&cobalt_queues()->usems,
-                              (u_long)sm->shadow_sem.sem);
-
-       if (assoc) {
-               assoc2usem(assoc)->refcnt++;
-               xnlock_put_irqrestore(&nklock, s);
-               xnfree(usm);
-               usm = assoc2usem(assoc);
-               goto got_usm;
-       }
-
-       cobalt_assoc_insert(&cobalt_queues()->usems,
-                          &usm->assoc, (u_long)sm->shadow_sem.sem);
-       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
-
-      got_usm:
-
-       if (usm->uaddr == uaddr)
-               /* First binding by this process. */
-               err = __xn_safe_copy_to_user((void __user *)usm->uaddr,
-                                            &sm->shadow_sem, 
sizeof(sm->shadow_sem));
-       else
-               /* Semaphore already bound by this process in user-space. */
-               err = __xn_safe_copy_to_user(u_addr, &usm->uaddr,
-                                            sizeof(unsigned long));
-
-       return err;
-}
-
-static int __sem_close(unsigned long uaddr,
-                      int __user *u_closed)
-{
-       cobalt_assoc_t *assoc;
-       union __xeno_sem sm;
-       int closed = 0, err;
-       cobalt_usem_t *usm;
-       spl_t s;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    (void __user *)uaddr, 
sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       xnlock_get_irqsave(&cobalt_assoc_lock, s);
-
-       assoc =
-           cobalt_assoc_lookup(&cobalt_queues()->usems,
-                              (u_long)sm.shadow_sem.sem);
-
-       if (!assoc) {
-               xnlock_put_irqrestore(&cobalt_assoc_lock, s);
-               return -EINVAL;
-       }
-
-       usm = assoc2usem(assoc);
-
-       err = sem_close(&sm.native_sem);
-
-       if (!err && (closed = (--usm->refcnt == 0)))
-               cobalt_assoc_remove(&cobalt_queues()->usems,
-                                  (u_long)sm.shadow_sem.sem);
-
-       xnlock_put_irqrestore(&cobalt_assoc_lock, s);
-
-       if (err)
-               return -thread_get_errno();
-
-       if (closed)
-               xnfree(usm);
-
-       return __xn_safe_copy_to_user(u_closed, &closed, sizeof(int));
-}
-
-static int __sem_unlink(const char __user *u_name)
-{
-       char name[COBALT_MAXNAME];
-       long len;
-
-       len = __xn_safe_strncpy_from_user(name, u_name, sizeof(name));
-       if (len < 0)
-               return len;
-       if (len >= sizeof(name))
-               return -ENAMETOOLONG;
-
-       return sem_unlink(name) == 0 ? 0 : -thread_get_errno();
-}
-
-static int __sem_init_np(union __xeno_sem __user *u_sem,
-                        int flags, unsigned value)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       if (sem_init_np(&sm.native_sem, flags, value) == -1)
-               return -thread_get_errno();
-
-       return __xn_safe_copy_to_user(&u_sem->shadow_sem,
-                                     &sm.shadow_sem, 
sizeof(u_sem->shadow_sem));
-}
-
-static int __sem_broadcast_np(union __xeno_sem __user *u_sem)
-{
-       union __xeno_sem sm;
-
-       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                    &u_sem->shadow_sem,
-                                    sizeof(sm.shadow_sem)))
-               return -EFAULT;
-
-       return sem_broadcast_np(&sm.native_sem) == 0 ? 0 : -thread_get_errno();
-}
-
 static int __clock_getres(clockid_t clock_id,
                          struct timespec __user *u_ts)
 {
@@ -1496,12 +1216,13 @@ static int __timer_create(clockid_t clock,
        if (u_sev) {
                if (__xn_safe_copy_from_user(&sev, u_sev, sizeof(sev)))
                        return -EFAULT;
+
                if (sev.sigev_notify == SIGEV_THREAD_ID) {
                        u_sem = sev.sigev_value.sival_ptr;
-                       if (__xn_safe_copy_from_user(&sm.shadow_sem,
-                                                    &u_sem->shadow_sem,
-                                                    sizeof(sm.shadow_sem)))
+
+                       if (__xn_safe_copy_from_user(&sm, u_sem, sizeof(sm)))
                                return -EFAULT;
+
                        sev.sigev_value.sival_ptr = &sm.native_sem;
                }
        } else
@@ -2029,18 +1750,18 @@ static struct xnsysent __systab[] = {
        SKINCALL_DEF(__cobalt_thread_probe, __pthread_probe_np, any),
        SKINCALL_DEF(__cobalt_thread_kill, __pthread_kill, any),
        SKINCALL_DEF(__cobalt_thread_getstat, __pthread_stat, any),
-       SKINCALL_DEF(__cobalt_sem_init, __sem_init, any),
-       SKINCALL_DEF(__cobalt_sem_destroy, __sem_destroy, any),
-       SKINCALL_DEF(__cobalt_sem_post, __sem_post, any),
-       SKINCALL_DEF(__cobalt_sem_wait, __sem_wait, primary),
-       SKINCALL_DEF(__cobalt_sem_timedwait, __sem_timedwait, primary),
-       SKINCALL_DEF(__cobalt_sem_trywait, __sem_trywait, primary),
-       SKINCALL_DEF(__cobalt_sem_getvalue, __sem_getvalue, any),
-       SKINCALL_DEF(__cobalt_sem_open, __sem_open, any),
-       SKINCALL_DEF(__cobalt_sem_close, __sem_close, any),
-       SKINCALL_DEF(__cobalt_sem_unlink, __sem_unlink, any),
-       SKINCALL_DEF(__cobalt_sem_init_np, __sem_init_np, any),
-       SKINCALL_DEF(__cobalt_sem_broadcast_np, __sem_broadcast_np, any),
+       SKINCALL_DEF(__cobalt_sem_init, cobalt_sem_init, any),
+       SKINCALL_DEF(__cobalt_sem_destroy, cobalt_sem_destroy, any),
+       SKINCALL_DEF(__cobalt_sem_post, cobalt_sem_post, any),
+       SKINCALL_DEF(__cobalt_sem_wait, cobalt_sem_wait, primary),
+       SKINCALL_DEF(__cobalt_sem_timedwait, cobalt_sem_timedwait, primary),
+       SKINCALL_DEF(__cobalt_sem_trywait, cobalt_sem_trywait, primary),
+       SKINCALL_DEF(__cobalt_sem_getvalue, cobalt_sem_getvalue, any),
+       SKINCALL_DEF(__cobalt_sem_open, cobalt_sem_open, any),
+       SKINCALL_DEF(__cobalt_sem_close, cobalt_sem_close, any),
+       SKINCALL_DEF(__cobalt_sem_unlink, cobalt_sem_unlink, any),
+       SKINCALL_DEF(__cobalt_sem_init_np, cobalt_sem_init_np, any),
+       SKINCALL_DEF(__cobalt_sem_broadcast_np, cobalt_sem_broadcast_np, any),
        SKINCALL_DEF(__cobalt_clock_getres, __clock_getres, any),
        SKINCALL_DEF(__cobalt_clock_gettime, __clock_gettime, any),
        SKINCALL_DEF(__cobalt_clock_settime, __clock_settime, any),
diff --git a/kernel/cobalt/timer.c b/kernel/cobalt/timer.c
index 671ffb7..2e71ba0 100644
--- a/kernel/cobalt/timer.c
+++ b/kernel/cobalt/timer.c
@@ -70,7 +70,7 @@ static void cobalt_base_timer_handler(xntimer_t *xntimer)
 
        /* Null signo means to post a semaphore instead. */
        sem = timer->si.info.si_value.sival_ptr;
-       if (sem && sem_post_inner(sem, NULL, 0))
+       if (sem && sem_post_inner(sem, NULL, 0) < 0)
                /*
                 * On error, forget sema4 for next shots. In essence,
                 * the timer stops notifying anyone at expiry.
@@ -177,10 +177,10 @@ int timer_create(clockid_t clockid,
                        sem = evp->sigev_value.sival_ptr;
                        if (sem == NULL)
                                goto error;
-                       err = sem_getvalue(sem, &semval);
-                       if (err)
-                               return -1; /* errno already set */
                        shadow_sem = &((union __xeno_sem *)sem)->shadow_sem;
+                       err = sem_getvalue(shadow_sem->sem, &semval);
+                       if (err)
+                               goto error;
                        signo = 0;
                        break;
 
diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c
index 72d0dd2..d8bda87 100644
--- a/lib/cobalt/semaphore.c
+++ b/lib/cobalt/semaphore.c
@@ -21,19 +21,19 @@
 #include <errno.h>
 #include <fcntl.h>             /* For O_CREAT. */
 #include <pthread.h>           /* For pthread_setcanceltype. */
+#include <kernel/cobalt/sem.h>
 #include <cobalt/syscall.h>
 #include <semaphore.h>
 
 extern int __cobalt_muxid;
 
-int __wrap_sem_init(sem_t * sem, int pshared, unsigned value)
+int __wrap_sem_init(sem_t *sem, int pshared, unsigned value)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
        err = -XENOMAI_SKINCALL3(__cobalt_muxid,
-                                __cobalt_sem_init,
-                                &_sem->shadow_sem, pshared, value);
+                                __cobalt_sem_init, _sem, pshared, value);
        if (!err)
                return 0;
 
@@ -42,45 +42,58 @@ int __wrap_sem_init(sem_t * sem, int pshared, unsigned 
value)
        return -1;
 }
 
-int __wrap_sem_destroy(sem_t * sem)
+int __wrap_sem_destroy(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                __cobalt_sem_destroy, &_sem->shadow_sem);
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_sem_destroy, _sem);
        if (err >= 0)
                return err;
 
        errno = err;
-
        return -1;
 }
 
-int __wrap_sem_post(sem_t * sem)
+int __wrap_sem_post(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                __cobalt_sem_post, &_sem->shadow_sem);
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_sem_post, _sem);
        if (!err)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
-int __wrap_sem_wait(sem_t * sem)
+int __wrap_sem_wait(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err, oldtype;
 
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                __cobalt_sem_wait, &_sem->shadow_sem);
+       err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_sem_wait, _sem);
 
        pthread_setcanceltype(oldtype, NULL);
 
@@ -88,19 +101,24 @@ int __wrap_sem_wait(sem_t * sem)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
-int __wrap_sem_timedwait(sem_t * sem, const struct timespec *ts)
+int __wrap_sem_timedwait(sem_t *sem, const struct timespec *ts)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err, oldtype;
 
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
        err = -XENOMAI_SKINCALL2(__cobalt_muxid,
-                                __cobalt_sem_timedwait, &_sem->shadow_sem, ts);
+                                __cobalt_sem_timedwait, _sem, ts);
 
        pthread_setcanceltype(oldtype, NULL);
 
@@ -108,37 +126,45 @@ int __wrap_sem_timedwait(sem_t * sem, const struct 
timespec *ts)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
-int __wrap_sem_trywait(sem_t * sem)
+int __wrap_sem_trywait(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                __cobalt_sem_trywait, &_sem->shadow_sem);
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_sem_trywait, _sem);
        if (!err)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
-int __wrap_sem_getvalue(sem_t * sem, int *sval)
+int __wrap_sem_getvalue(sem_t *sem, int *sval)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
        err = -XENOMAI_SKINCALL2(__cobalt_muxid,
-                                __cobalt_sem_getvalue, &_sem->shadow_sem, 
sval);
+                                __cobalt_sem_getvalue, _sem, sval);
        if (!err)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
@@ -180,13 +206,18 @@ sem_t *__wrap_sem_open(const char *name, int oflags, ...)
        return SEM_FAILED;
 }
 
-int __wrap_sem_close(sem_t * sem)
+int __wrap_sem_close(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err, closed;
 
+       if (_sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
        err = -XENOMAI_SKINCALL2(__cobalt_muxid,
-                                __cobalt_sem_close, &_sem->shadow_sem, 
&closed);
+                                __cobalt_sem_close, _sem, &closed);
 
        if (!err) {
                if (closed)
@@ -213,31 +244,34 @@ int __wrap_sem_unlink(const char *name)
 
 int sem_init_np(sem_t *sem, int flags, unsigned int value)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
        err = -XENOMAI_SKINCALL3(__cobalt_muxid,
-                                __cobalt_sem_init_np,
-                                &_sem->shadow_sem, flags, value);
+                                __cobalt_sem_init_np, _sem, flags, value);
        if (!err)
                return 0;
 
        errno = err;
-
        return -1;
 }
 
 int sem_broadcast_np(sem_t *sem)
 {
-       union __xeno_sem *_sem = (union __xeno_sem *)sem;
+       struct __shadow_sem *_sem = &((union __xeno_sem *)sem)->shadow_sem;
        int err;
 
+       if (_sem->magic != COBALT_SEM_MAGIC
+           && _sem->magic != COBALT_NAMED_SEM_MAGIC) {
+               errno = EINVAL;
+               return -1;
+       }
+
        err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                __cobalt_sem_broadcast_np, &_sem->shadow_sem);
+                                __cobalt_sem_broadcast_np, _sem);
        if (!err)
                return 0;
 
        errno = err;
-
        return -1;
 }


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to