Module: xenomai-forge
Branch: next
Commit: e4265fb13dc82868f6641731916005d1c6ce615f
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=e4265fb13dc82868f6641731916005d1c6ce615f

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Sep 11 12:35:51 2014 +0200

cobalt/kernel/cond, lib/cobalt: put shadow condvar descriptor on a diet

As we overlay the native pthread_cond_t type, our shadow structure for
the condition variable descriptor (cobalt_cond_shadow) must not exceed
the latter in size, which currently happens with linuxthreads.

This patch shrinks the condvar shadow structure down to 12 bytes on
32bit systems, which meets the requirement.

---

 include/cobalt/uapi/cond.h         |   17 +++---
 include/cobalt/uapi/kernel/synch.h |    6 ++
 include/cobalt/uapi/kernel/types.h |    5 +-
 kernel/cobalt/posix/cond.c         |  106 ++++++++++++++++-----------------
 kernel/cobalt/posix/cond.h         |    2 +-
 lib/cobalt/cond.c                  |  115 ++++++++++++++++++++----------------
 6 files changed, 136 insertions(+), 115 deletions(-)

diff --git a/include/cobalt/uapi/cond.h b/include/cobalt/uapi/cond.h
index cea0737..a6ff148 100644
--- a/include/cobalt/uapi/cond.h
+++ b/include/cobalt/uapi/cond.h
@@ -22,19 +22,22 @@
 
 #define COBALT_COND_MAGIC 0x86860505
 
+struct cobalt_cond_state {
+       __u32 pending_signals;
+       union {
+               __u32 mutex_datp_offset;
+               struct mutex_dat *mutex_datp;
+       };
+};
+
 union cobalt_cond_union {
        pthread_cond_t native_cond;
        struct cobalt_cond_shadow {
                __u32 magic;
-               struct cobalt_condattr attr;
                xnhandle_t handle;
                union {
-                       __u32 pending_signals_offset;
-                       __u32 *pending_signals;
-               };
-               union {
-                       __u32 mutex_datp_offset;
-                       struct mutex_dat *mutex_datp;
+                       __u32 state_offset;
+                       struct cobalt_cond_state *state;
                };
        } shadow_cond;
 };
diff --git a/include/cobalt/uapi/kernel/synch.h 
b/include/cobalt/uapi/kernel/synch.h
index 2a8c40c..6947058 100644
--- a/include/cobalt/uapi/kernel/synch.h
+++ b/include/cobalt/uapi/kernel/synch.h
@@ -75,4 +75,10 @@ int xnsynch_fast_release(atomic_t *fastlock, xnhandle_t 
cur_ownerh)
                == cur_ownerh;
 }
 
+/* Local/shared property */
+static inline int xnsynch_is_shared(xnhandle_t handle)
+{
+       return (handle & XNSYNCH_PSHARED) != 0;
+}
+
 #endif /* !_COBALT_UAPI_KERNEL_SYNCH_H */
diff --git a/include/cobalt/uapi/kernel/types.h 
b/include/cobalt/uapi/kernel/types.h
index 4454536..6064249 100644
--- a/include/cobalt/uapi/kernel/types.h
+++ b/include/cobalt/uapi/kernel/types.h
@@ -30,7 +30,10 @@ typedef __u32 xnhandle_t;
 #define XN_NO_HANDLE           ((xnhandle_t)0)
 #define XN_HANDLE_INDEX_MASK   ((xnhandle_t)0xf0000000)
 
-/* 3 spare special bits remaining. */
+/* Fixed bits (part of the identifier) */
+#define XNSYNCH_PSHARED                ((xnhandle_t)0x40000000)
+
+/* Transient bits (expressing a status) */
 #define XNSYNCH_FLCLAIM                ((xnhandle_t)0x80000000)
 
 #define XN_HANDLE_TRANSIENT_MASK       XNSYNCH_FLCLAIM
diff --git a/kernel/cobalt/posix/cond.c b/kernel/cobalt/posix/cond.c
index 4127f59..0e91f29 100644
--- a/kernel/cobalt/posix/cond.c
+++ b/kernel/cobalt/posix/cond.c
@@ -37,24 +37,27 @@ cond_destroy_internal(xnhandle_t handle, struct 
cobalt_kqueues *q)
        }
        xnregistry_remove(handle);
        list_del(&cond->link);
-       /* synchbase wait queue may not be empty only when this function is
-          called from cobalt_cond_pkg_cleanup, hence the absence of
-          xnsched_run(). */
+       /*
+        * synchbase wait queue may not be empty only when this
+        * function is called from cobalt_cond_pkg_cleanup, in which
+        * case we don't have to reschedule.
+        */
        xnsynch_destroy(&cond->synchbase);
        cobalt_mark_deleted(cond);
        xnlock_put_irqrestore(&nklock, s);
        cobalt_umm_free(&cobalt_ppd_get(cond->attr.pshared)->umm,
-                       cond->pending_signals);
+                       cond->state);
        xnfree(cond);
 }
 
 static inline int
 pthread_cond_init(struct cobalt_cond_shadow *cnd, const struct cobalt_condattr 
*attr)
 {
-       int synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP, err;
+       int synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP, ret;
        struct cobalt_cond *cond, *old_cond;
-       struct list_head *condq;
+       struct cobalt_cond_state *state;
        struct xnsys_ppd *sys_ppd;
+       struct list_head *condq;
        spl_t s;
 
        cond = xnmalloc(sizeof(*cond));
@@ -62,13 +65,14 @@ pthread_cond_init(struct cobalt_cond_shadow *cnd, const 
struct cobalt_condattr *
                return -ENOMEM;
 
        sys_ppd = cobalt_ppd_get(attr->pshared);
-       cond->pending_signals = cobalt_umm_alloc(&sys_ppd->umm,
-                               sizeof(*cond->pending_signals));
-       if (cond->pending_signals == NULL) {
-               err = -EAGAIN;
-               goto err_free_cond;
+       state = cobalt_umm_alloc(&sys_ppd->umm, sizeof(*state));
+       if (state == NULL) {
+               ret = -EAGAIN;
+               goto fail_umm;
        }
-       *cond->pending_signals = 0;
+       cond->state = state;
+       state->pending_signals = 0;
+       state->mutex_datp = (struct mutex_dat *)~0UL;
 
        xnlock_get_irqsave(&nklock, s);
 
@@ -88,25 +92,19 @@ pthread_cond_init(struct cobalt_cond_shadow *cnd, const 
struct cobalt_condattr *
                goto do_init;
 
        if (attr->pshared == 0) {
-               err = -EBUSY;
-               goto err_free_pending_signals;
+               ret = -EBUSY;
+               goto fail_register;
        }
        xnlock_put_irqrestore(&nklock, s);
        cond_destroy_internal(cnd->handle, cobalt_kqueues(1));
        xnlock_get_irqsave(&nklock, s);
 do_init:
-       err = xnregistry_enter_anon(cond, &cond->handle);
-       if (err < 0)
-               goto err_free_pending_signals;
-
-       cnd->handle = cond->handle;
-       cnd->attr = *attr;
-       cnd->pending_signals_offset =
-               cobalt_umm_offset(&sys_ppd->umm, cond->pending_signals);
-       cnd->mutex_datp = (struct mutex_dat *)~0UL;
-
-       cnd->magic = COBALT_COND_MAGIC;
+       ret = xnregistry_enter_anon(cond, &cond->handle);
+       if (ret < 0)
+               goto fail_register;
 
+       if (attr->pshared)
+               cond->handle |= XNSYNCH_PSHARED;
        cond->magic = COBALT_COND_MAGIC;
        xnsynch_init(&cond->synchbase, synch_flags, NULL);
        cond->attr = *attr;
@@ -114,17 +112,20 @@ do_init:
        cond->owningq = cobalt_kqueues(attr->pshared);
        list_add_tail(&cond->link, condq);
 
+       cnd->handle = cond->handle;
+       cnd->state_offset = cobalt_umm_offset(&sys_ppd->umm, state);
+       cnd->magic = COBALT_COND_MAGIC;
+
        xnlock_put_irqrestore(&nklock, s);
 
        return 0;
-
-  err_free_pending_signals:
+fail_register:
        xnlock_put_irqrestore(&nklock, s);
-       cobalt_umm_free(&cobalt_ppd_get(cond->attr.pshared)->umm,
-                       cond->pending_signals);
-  err_free_cond:
+       cobalt_umm_free(&cobalt_ppd_get(cond->attr.pshared)->umm, state);
+fail_umm:
        xnfree(cond);
-       return err;
+
+       return ret;
 }
 
 static inline int pthread_cond_destroy(struct cobalt_cond_shadow *cnd)
@@ -324,7 +325,7 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
                     struct timespec __user *u_ts))
 {
        struct xnthread *cur = xnthread_current();
-       struct cobalt_cond *cnd;
+       struct cobalt_cond *cond;
        struct cobalt_mutex *mx;
        struct mutex_dat *datp;
        struct us_cond_data d;
@@ -333,27 +334,27 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
        int err, perr = 0;
 
        handle = cobalt_get_handle_from_user(&u_cnd->handle);
-       cnd = xnregistry_lookup(handle, NULL);
+       cond = xnregistry_lookup(handle, NULL);
 
        handle = cobalt_get_handle_from_user(&u_mx->handle);
        mx = xnregistry_lookup(handle, NULL);
 
-       if (!cnd->mutex) {
+       if (cond->mutex == NULL) {
                __xn_get_user(datp, &u_mx->dat);
-               __xn_put_user(datp, &u_cnd->mutex_datp);
+               cond->state->mutex_datp = datp;
        }
 
        if (timed) {
                err = __xn_safe_copy_from_user(&ts, u_ts, sizeof(ts))?-EFAULT:0;
-               if (!err) {
+               if (err == 0) {
                        trace_cobalt_cond_timedwait(u_cnd, u_mx, &ts);
                        err = cobalt_cond_timedwait_prologue(cur,
-                                                            cnd, mx, timed,
+                                                            cond, mx, timed,
                                                             ts2ns(&ts) + 1);
                }
        } else {
                trace_cobalt_cond_wait(u_cnd, u_mx);
-               err = cobalt_cond_timedwait_prologue(cur, cnd,
+               err = cobalt_cond_timedwait_prologue(cur, cond,
                                                     mx, timed,
                                                     XN_INFINITE);
        }
@@ -362,7 +363,7 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
        case 0:
        case -ETIMEDOUT:
                perr = d.err = err;
-               err = cobalt_cond_timedwait_epilogue(cur, cnd, mx);
+               err = cobalt_cond_timedwait_epilogue(cur, cond, mx);
                break;
 
        case -EINTR:
@@ -376,10 +377,8 @@ COBALT_SYSCALL(cond_wait_prologue, nonrestartable,
                d.err = EINVAL;
        }
 
-       if (!cnd->mutex) {
-               datp = (struct mutex_dat *)~0UL;
-               __xn_put_user(datp, &u_cnd->mutex_datp);
-       }
+       if (cond->mutex == NULL)
+               cond->state->mutex_datp = (struct mutex_dat *)~0UL;
 
        if (err == -EINTR)
                __xn_put_user(d.err, u_err);
@@ -392,37 +391,36 @@ COBALT_SYSCALL(cond_wait_epilogue, primary,
                     struct cobalt_mutex_shadow __user *u_mx))
 {
        struct xnthread *cur = xnthread_current();
-       struct cobalt_cond *cnd;
+       struct cobalt_cond *cond;
        struct cobalt_mutex *mx;
        xnhandle_t handle;
        int err;
 
        handle = cobalt_get_handle_from_user(&u_cnd->handle);
-       cnd = xnregistry_lookup(handle, NULL);
+       cond = xnregistry_lookup(handle, NULL);
 
        handle = cobalt_get_handle_from_user(&u_mx->handle);
        mx = xnregistry_lookup(handle, NULL);
+       err = cobalt_cond_timedwait_epilogue(cur, cond, mx);
 
-       err = cobalt_cond_timedwait_epilogue(cur, cnd, mx);
-
-       if (!cnd->mutex) {
-               struct mutex_dat *datp = (struct mutex_dat *)~0UL;
-               __xn_put_user(datp, &u_cnd->mutex_datp);
-       }
+       if (cond->mutex == NULL)
+               cond->state->mutex_datp = (struct mutex_dat *)~0UL;
 
        return err;
 }
 
 int cobalt_cond_deferred_signals(struct cobalt_cond *cond)
 {
+       struct cobalt_cond_state *state;
        __u32 pending_signals;
        int need_resched;
 
-       pending_signals = *cond->pending_signals;
+       state = cond->state;
+       pending_signals = state->pending_signals;
 
        switch(pending_signals) {
        default:
-               *cond->pending_signals = 0;
+               state->pending_signals = 0;
                need_resched = xnsynch_wakeup_many_sleepers(&cond->synchbase,
                                                            pending_signals);
                break;
@@ -430,7 +428,7 @@ int cobalt_cond_deferred_signals(struct cobalt_cond *cond)
        case ~0U:
                need_resched =
                        xnsynch_flush(&cond->synchbase, 0) == XNSYNCH_RESCHED;
-               *cond->pending_signals = 0;
+               state->pending_signals = 0;
                break;
 
        case 0:
diff --git a/kernel/cobalt/posix/cond.h b/kernel/cobalt/posix/cond.h
index c98edf8..3850652 100644
--- a/kernel/cobalt/posix/cond.h
+++ b/kernel/cobalt/posix/cond.h
@@ -35,7 +35,7 @@ struct cobalt_cond {
        /** cobalt_condq */
        struct list_head link;
        struct list_head mutex_link;
-       __u32 *pending_signals;
+       struct cobalt_cond_state *state;
        struct cobalt_condattr attr;
        struct cobalt_mutex *mutex;
        struct cobalt_kqueues *owningq;
diff --git a/lib/cobalt/cond.c b/lib/cobalt/cond.c
index 6be832c..c177e4a 100644
--- a/lib/cobalt/cond.c
+++ b/lib/cobalt/cond.c
@@ -55,26 +55,28 @@
 
 static pthread_condattr_t cobalt_default_condattr;
 
-static inline __u32 *cond_get_signalsp(struct cobalt_cond_shadow *shadow)
+static inline struct cobalt_cond_state *
+get_cond_state(struct cobalt_cond_shadow *shadow)
 {
-       if (shadow->attr.pshared)
-               return (__u32 *)(cobalt_umm_shared
-                                + shadow->pending_signals_offset);
-
-       return shadow->pending_signals;
+       if (xnsynch_is_shared(shadow->handle))
+               return (struct cobalt_cond_state *)(cobalt_umm_shared
+                                + shadow->state_offset);
+       return shadow->state;
 }
 
 static inline struct mutex_dat *
-cond_get_mutex_datp(struct cobalt_cond_shadow *shadow)
+get_mutex_state(struct cobalt_cond_shadow *shadow)
 {
-       if (shadow->mutex_datp == (struct mutex_dat *)~0UL)
+       struct cobalt_cond_state *cond_state = get_cond_state(shadow);
+
+       if (cond_state->mutex_datp == (struct mutex_dat *)~0UL)
                return NULL;
 
-       if (shadow->attr.pshared)
+       if (xnsynch_is_shared(shadow->handle))
                return (struct mutex_dat *)(cobalt_umm_shared
-                                           + shadow->mutex_datp_offset);
+                                           + cond_state->mutex_datp_offset);
 
-       return shadow->mutex_datp;
+       return cond_state->mutex_datp;
 }
 
 void cobalt_default_condattr_init(void)
@@ -82,7 +84,6 @@ void cobalt_default_condattr_init(void)
        pthread_condattr_init(&cobalt_default_condattr);
 }
 
-
 /**
  * @fn int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t 
*attr)
  * @brief Initialize a condition variable
@@ -112,8 +113,8 @@ COBALT_IMPL(int, pthread_cond_init, (pthread_cond_t *cond,
                                     const pthread_condattr_t * attr))
 {
        struct cobalt_cond_shadow *_cnd = &((union cobalt_cond_union 
*)cond)->shadow_cond;
+       struct cobalt_cond_state *cond_state;
        struct cobalt_condattr kcattr;
-       __u32 *pending_signalsp;
        int err, tmp;
 
        if (attr == NULL)
@@ -133,14 +134,19 @@ COBALT_IMPL(int, pthread_cond_init, (pthread_cond_t *cond,
        if (err)
                return err;
 
-       if (!_cnd->attr.pshared) {
-               pending_signalsp = (__u32 *)
-                       (cobalt_umm_private + _cnd->pending_signals_offset);
-               _cnd->pending_signals = pending_signalsp;
-       } else
-               pending_signalsp = cond_get_signalsp(_cnd);
+       if (kcattr.pshared)
+               cond_state = get_cond_state(_cnd);
+       else {
+               /*
+                * This is condvar is local to the current process,
+                * build a direct pointer for fast access.
+                */
+               cond_state = (struct cobalt_cond_state *)
+                       (cobalt_umm_private + _cnd->state_offset);
+               _cnd->state = cond_state;
+       }
 
-       cobalt_commit_memory(pending_signalsp);
+       cobalt_commit_memory(cond_state);
 
        return 0;
 }
@@ -399,32 +405,34 @@ COBALT_IMPL(int, pthread_cond_timedwait, (pthread_cond_t 
*cond,
 COBALT_IMPL(int, pthread_cond_signal, (pthread_cond_t *cond))
 {
        struct cobalt_cond_shadow *_cnd = &((union cobalt_cond_union 
*)cond)->shadow_cond;
-       __u32 pending_signals, *pending_signalsp;
-       struct mutex_dat *mutex_datp;
+       struct cobalt_cond_state *cond_state;
+       struct mutex_dat *mutex_state;
+       __u32 pending_signals;
        xnhandle_t cur;
        __u32 flags;
 
        if (_cnd->magic != COBALT_COND_MAGIC)
                return EINVAL;
 
-       mutex_datp = cond_get_mutex_datp(_cnd);
-       if (mutex_datp) {
-               flags = mutex_datp->flags;
-               if (flags & COBALT_MUTEX_ERRORCHECK) {
-                       cur = cobalt_get_current();
-                       if (cur == XN_NO_HANDLE)
-                               return EPERM;
-
-                       if (xnsynch_fast_owner_check(&mutex_datp->owner, cur) < 
0)
-                               return EPERM;
-               }
-               mutex_datp->flags = flags | COBALT_MUTEX_COND_SIGNAL;
-               pending_signalsp = cond_get_signalsp(_cnd);
-               pending_signals = *pending_signalsp;
-               if (pending_signals != ~0U)
-                       *pending_signalsp = pending_signals + 1;
+       mutex_state = get_mutex_state(_cnd);
+       if (mutex_state == NULL)
+               return 0;       /* Fast path, no waiter. */
+
+       flags = mutex_state->flags;
+       if (flags & COBALT_MUTEX_ERRORCHECK) {
+               cur = cobalt_get_current();
+               if (cur == XN_NO_HANDLE)
+                       return EPERM;
+               if (xnsynch_fast_owner_check(&mutex_state->owner, cur) < 0)
+                       return EPERM;
        }
 
+       mutex_state->flags = flags | COBALT_MUTEX_COND_SIGNAL;
+       cond_state = get_cond_state(_cnd);
+       pending_signals = cond_state->pending_signals;
+       if (pending_signals != ~0U)
+               cond_state->pending_signals = pending_signals + 1;
+
        return 0;
 }
 
@@ -449,28 +457,31 @@ COBALT_IMPL(int, pthread_cond_signal, (pthread_cond_t 
*cond))
 COBALT_IMPL(int, pthread_cond_broadcast, (pthread_cond_t *cond))
 {
        struct cobalt_cond_shadow *_cnd = &((union cobalt_cond_union 
*)cond)->shadow_cond;
-       struct mutex_dat *mutex_datp;
+       struct cobalt_cond_state *cond_state;
+       struct mutex_dat *mutex_state;
        xnhandle_t cur;
        __u32 flags;
 
        if (_cnd->magic != COBALT_COND_MAGIC)
                return EINVAL;
 
-       mutex_datp = cond_get_mutex_datp(_cnd);
-       if (mutex_datp) {
-               flags = mutex_datp->flags ;
-               if (flags & COBALT_MUTEX_ERRORCHECK) {
-                       cur = cobalt_get_current();
-                       if (cur == XN_NO_HANDLE)
-                               return EPERM;
-
-                       if (xnsynch_fast_owner_check(&mutex_datp->owner, cur) < 
0)
-                               return EPERM;
-               }
-               mutex_datp->flags = flags | COBALT_MUTEX_COND_SIGNAL;
-               *cond_get_signalsp(_cnd) = ~0U;
+       mutex_state = get_mutex_state(_cnd);
+       if (mutex_state == NULL)
+               return 0;
+
+       flags = mutex_state->flags;
+       if (flags & COBALT_MUTEX_ERRORCHECK) {
+               cur = cobalt_get_current();
+               if (cur == XN_NO_HANDLE)
+                       return EPERM;
+               if (xnsynch_fast_owner_check(&mutex_state->owner, cur) < 0)
+                       return EPERM;
        }
 
+       mutex_state->flags = flags | COBALT_MUTEX_COND_SIGNAL;
+       cond_state = get_cond_state(_cnd);
+       cond_state->pending_signals = ~0U;
+
        return 0;
 }
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to