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