Module: xenomai-jki
Branch: queues/assorted
Commit: 0a1ca2dd9c5f9439eccfcb8b678abe8db143b9a0
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=0a1ca2dd9c5f9439eccfcb8b678abe8db143b9a0

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Sat Mar  6 09:30:20 2010 +0100

POSIX: Add and use fixed syscalls for pthread_cond_[timed]wait

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 include/posix/pthread.h    |    5 +++
 include/posix/syscall.h    |    2 +
 ksrc/skins/posix/syscall.c |   82 ++++++++++++++++++++++++++++++++++--------
 src/skins/posix/cond.c     |   87 ++++++++++++++++++++++++++++++++++++++------
 src/skins/posix/init.c     |    3 ++
 5 files changed, 153 insertions(+), 26 deletions(-)

diff --git a/include/posix/pthread.h b/include/posix/pthread.h
index 685b356..b4f9531 100644
--- a/include/posix/pthread.h
+++ b/include/posix/pthread.h
@@ -184,6 +184,11 @@ union __xeno_cond {
        } shadow_cond;
 };
 
+struct pse51_cond_wait_state {
+       unsigned count;
+       int prologue_err;
+};
+
 struct pse51_interrupt;
 
 typedef struct pse51_interrupt *pthread_intr_t;
diff --git a/include/posix/syscall.h b/include/posix/syscall.h
index 04a528d..8bb64bd 100644
--- a/include/posix/syscall.h
+++ b/include/posix/syscall.h
@@ -104,6 +104,8 @@
 #define __pse51_select                77
 #define __pse51_thread_setschedparam_ex        78
 #define __pse51_thread_getschedparam_ex        79
+#define __pse51_cond_wait_prologue2    80
+#define __pse51_cond_wait_epilogue2    81
 
 #ifdef __KERNEL__
 
diff --git a/ksrc/skins/posix/syscall.c b/ksrc/skins/posix/syscall.c
index 0032f4d..584708e 100644
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1512,13 +1512,14 @@ static int __pthread_cond_destroy(struct pt_regs *regs)
                                      &cnd.shadow_cond, 
sizeof(ucnd->shadow_cond));
 }
 
-/* pthread_cond_wait_prologue(cond, mutex, count_ptr, timed, timeout) */
-static int __pthread_cond_wait_prologue(struct pt_regs *regs)
+static int
+__pthread_cond_wait_prologue_inner(struct pt_regs *regs,
+                                  struct pse51_cond_wait_state *state)
 {
        xnthread_t *cur = xnshadow_thread(current);
        union __xeno_cond cnd, *ucnd;
        union __xeno_mutex mx, *umx;
-       unsigned timed, count;
+       unsigned timed;
        struct timespec ts;
        int err, epilogue_err;
 
@@ -1551,22 +1552,23 @@ static int __pthread_cond_wait_prologue(struct pt_regs 
*regs)
                err = pse51_cond_timedwait_prologue(cur,
                                                    &cnd.shadow_cond,
                                                    &mx.shadow_mutex,
-                                                   &count,
+                                                   &state->count,
                                                    timed,
                                                    ts2ticks_ceil(&ts) + 1);
        } else
                err = pse51_cond_timedwait_prologue(cur,
                                                    &cnd.shadow_cond,
                                                    &mx.shadow_mutex,
-                                                   &count, timed, XN_INFINITE);
+                                                   &state->count,
+                                                   timed, XN_INFINITE);
 
-       cur->errcode = err != EINTR ? err : 0;
+       state->prologue_err = err != EINTR ? err : 0;
 
        if (err == 0 || err == ETIMEDOUT) {
                epilogue_err =
                        -pse51_cond_timedwait_epilogue(cur, &cnd.shadow_cond,
                                                       &mx.shadow_mutex,
-                                                      count);
+                                                      state->count);
                if (epilogue_err != 0)
                        err = epilogue_err;
                else if (__xn_safe_copy_to_user((void __user *)
@@ -1575,17 +1577,45 @@ static int __pthread_cond_wait_prologue(struct pt_regs 
*regs)
                                                
sizeof(umx->shadow_mutex.lockcnt)))
                        return -EFAULT;
        }
-
-       if (err == EINTR
-           && __xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
-                                     &count, sizeof(count)))
-                       return -EFAULT;
        
        return -err;
 }
 
-/* pthread_cond_wait_epilogue(cond, mutex, count) */
-static int __pthread_cond_wait_epilogue(struct pt_regs *regs)
+/* pthread_cond_wait_prologue(cond, mutex, count_ptr, timed, timeout) */
+static int __pthread_cond_wait_prologue(struct pt_regs *regs)
+{
+       struct pse51_cond_wait_state state;
+       int err;
+
+       err = __pthread_cond_wait_prologue_inner(regs, &state);
+
+       xnshadow_thread(current)->errcode = state.prologue_err;
+
+       if (err == -EINTR
+           && __xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
+                                     &state.count, sizeof(state.count)))
+               return -EFAULT;
+
+       return err;
+}
+
+/* pthread_cond_wait_prologue2(cond, mutex, state_ptr, timed, timeout) */
+static int __pthread_cond_wait_prologue2(struct pt_regs *regs)
+{
+       struct pse51_cond_wait_state state;
+       int err;
+
+       err = __pthread_cond_wait_prologue_inner(regs, &state);
+
+       if (err == -EINTR
+           && __xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
+                                     &state, sizeof(state)))
+               return -EFAULT;
+
+       return err;
+}
+
+static int __pthread_cond_wait_epilogue_inner(struct pt_regs *regs)
 {
        xnthread_t *cur = xnshadow_thread(current);
        union __xeno_cond cnd, *ucnd;
@@ -1623,7 +1653,25 @@ static int __pthread_cond_wait_epilogue(struct pt_regs 
*regs)
                                      sizeof(umx->shadow_mutex.lockcnt)))
                return -EFAULT;
 
-       return err ? err : -cur->errcode;
+       return err;
+}
+
+/* pthread_cond_wait_epilogue(cond, mutex, count)
+   Used with pthread_cond_wait_prologue. */
+static int __pthread_cond_wait_epilogue(struct pt_regs *regs)
+{
+       int err;
+
+       err = __pthread_cond_wait_epilogue_inner(regs);
+
+       return err ? err : -xnshadow_thread(current)->errcode;
+}
+
+/* pthread_cond_wait_epilogue2(cond, mutex, count)
+   Used with pthread_cond_wait_prologue2. */
+static int __pthread_cond_wait_epilogue2(struct pt_regs *regs)
+{
+       return __pthread_cond_wait_epilogue_inner(regs);
 }
 
 static int __pthread_cond_signal(struct pt_regs *regs)
@@ -2793,6 +2841,10 @@ static xnsysent_t __systab[] = {
            {&__pthread_cond_wait_prologue, __xn_exec_primary | 
__xn_exec_norestart},
        [__pse51_cond_wait_epilogue] =
            {&__pthread_cond_wait_epilogue, __xn_exec_primary},
+       [__pse51_cond_wait_prologue2] =
+           {&__pthread_cond_wait_prologue2, __xn_exec_primary | 
__xn_exec_norestart},
+       [__pse51_cond_wait_epilogue2] =
+           {&__pthread_cond_wait_epilogue2, __xn_exec_primary},
        [__pse51_cond_signal] = {&__pthread_cond_signal, __xn_exec_any},
        [__pse51_cond_broadcast] = {&__pthread_cond_broadcast, __xn_exec_any},
        [__pse51_mq_open] = {&__mq_open, __xn_exec_lostage},
diff --git a/src/skins/posix/cond.c b/src/skins/posix/cond.c
index 1fd01b3..8431ffe 100644
--- a/src/skins/posix/cond.c
+++ b/src/skins/posix/cond.c
@@ -24,6 +24,8 @@
 
 extern int __pse51_muxid;
 
+static int have_new_cond_syscalls;
+
 int __wrap_pthread_condattr_init(pthread_condattr_t *attr)
 {
        return -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_condattr_init, attr);
@@ -83,7 +85,7 @@ int __wrap_pthread_cond_destroy(pthread_cond_t * cond)
 struct pse51_cond_cleanup_t {
        union __xeno_cond *cond;
        union __xeno_mutex *mutex;
-       unsigned count;
+       struct pse51_cond_wait_state state;
 };
 
 static void __pthread_cond_cleanup(void *data)
@@ -93,15 +95,16 @@ static void __pthread_cond_cleanup(void *data)
 
        do {
                err = -XENOMAI_SKINCALL3(__pse51_muxid,
-                                       __pse51_cond_wait_epilogue,
-                                       &c->cond->shadow_cond,
-                                       &c->mutex->shadow_mutex,
-                                       c->count);
+                                        __pse51_cond_wait_epilogue,
+                                        &c->cond->shadow_cond,
+                                        &c->mutex->shadow_mutex,
+                                        c->state.count);
        } while (err == EINTR);
 }
 
-static int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
-                              int timed, const struct timespec *abstime)
+static int
+__pthread_cond_wait_old(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                       int timed, const struct timespec *abstime)
 {
        struct pse51_cond_cleanup_t c = {
                .cond = (union __xeno_cond *)cond,
@@ -119,7 +122,7 @@ static int __pthread_cond_wait(pthread_cond_t *cond, 
pthread_mutex_t *mutex,
        err = -XENOMAI_SKINCALL5(__pse51_muxid,
                                 __pse51_cond_wait_prologue,
                                 &c.cond->shadow_cond,
-                                &c.mutex->shadow_mutex, &c.count,
+                                &c.mutex->shadow_mutex, &c.state.count,
                                 timed, abstime);
 
        pthread_setcanceltype(oldtype, NULL);
@@ -131,7 +134,54 @@ static int __pthread_cond_wait(pthread_cond_t *cond, 
pthread_mutex_t *mutex,
                                         __pse51_cond_wait_epilogue,
                                         &c.cond->shadow_cond,
                                         &c.mutex->shadow_mutex,
-                                        c.count);
+                                        c.state.count);
+
+       cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
+       pthread_testcancel();
+
+       return err;
+}
+
+static int
+__pthread_cond_wait_new(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                       int timeout, const struct timespec *abstime)
+{
+       struct pse51_cond_cleanup_t c = {
+               .cond = (union __xeno_cond *)cond,
+               .mutex = (union __xeno_mutex *)mutex,
+       };
+       int err, oldtype;
+
+       if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+               return EINVAL;
+
+       pthread_cleanup_push(&__pthread_cond_cleanup, &c);
+
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+
+       err = -XENOMAI_SKINCALL5(__pse51_muxid,
+                                __pse51_cond_wait_prologue2,
+                                &c.cond->shadow_cond,
+                                &c.mutex->shadow_mutex, &c.state,
+                                timeout, abstime);
+
+       pthread_setcanceltype(oldtype, NULL);
+
+       pthread_cleanup_pop(0);
+
+       if (err == EINTR) {
+               do {
+                       err = -XENOMAI_SKINCALL3(__pse51_muxid,
+                                                __pse51_cond_wait_epilogue2,
+                                                &c.cond->shadow_cond,
+                                                &c.mutex->shadow_mutex,
+                                                c.state.count);
+               } while (err == EINTR);
+
+               if (!err)
+                       err = c.state.prologue_err;
+       }
 
        cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
 
@@ -142,14 +192,20 @@ static int __pthread_cond_wait(pthread_cond_t *cond, 
pthread_mutex_t *mutex,
 
 int __wrap_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
-       return __pthread_cond_wait(cond, mutex, 0, NULL);
+       if (have_new_cond_syscalls)
+               return __pthread_cond_wait_new(cond, mutex, 0, NULL);
+       else
+               return __pthread_cond_wait_old(cond, mutex, 0, NULL);
 }
 
 int __wrap_pthread_cond_timedwait(pthread_cond_t * cond,
                                  pthread_mutex_t * mutex,
                                  const struct timespec *abstime)
 {
-       return __pthread_cond_wait(cond, mutex, 1, abstime);
+       if (have_new_cond_syscalls)
+               return __pthread_cond_wait_new(cond, mutex, 1, abstime);
+       else
+               return __pthread_cond_wait_old(cond, mutex, 1, abstime);
 }
 
 int __wrap_pthread_cond_signal(pthread_cond_t * cond)
@@ -167,3 +223,12 @@ int __wrap_pthread_cond_broadcast(pthread_cond_t * cond)
        return -XENOMAI_SKINCALL1(__pse51_muxid,
                                  __pse51_cond_broadcast, &_cond->shadow_cond);
 }
+
+void pse51_cond_init(void)
+{
+       int err = XENOMAI_SKINCALL5(__pse51_muxid,
+                                   __pse51_cond_wait_prologue2, NULL, NULL,
+                                   NULL, 0, NULL);
+
+       have_new_cond_syscalls = (err != -ENOSYS);
+}
diff --git a/src/skins/posix/init.c b/src/skins/posix/init.c
index 20ae526..48d3809 100644
--- a/src/skins/posix/init.c
+++ b/src/skins/posix/init.c
@@ -42,6 +42,7 @@ static int fork_handler_registered;
 
 int __wrap_pthread_setschedparam(pthread_t, int, const struct sched_param *);
 void pse51_clock_init(int);
+void pse51_cond_init(void);
 
 static __attribute__ ((constructor))
 void __init_posix_interface(void)
@@ -120,4 +121,6 @@ void __init_posix_interface(void)
                        (int) sizeof(struct __shadow_mutex));
                exit(EXIT_FAILURE);
        }
+
+       pse51_cond_init();
 }


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

Reply via email to