Module: xenomai-gch Branch: for-forge Commit: 956d38b6d27dcfccecaa49fcdc86093743719f17 URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=956d38b6d27dcfccecaa49fcdc86093743719f17
Author: Gilles Chanteperdrix <[email protected]> Date: Sun Nov 13 17:15:37 2011 +0100 cobalt: fix pthread_mutex_trylock and pthread_mutex_unlock pthread_mutex_trylock was broken since the introduction of XNOTHER. pthread_mutex_unlock was broken with XNOTHER for recursive mutexes. --- include/cobalt/syscall.h | 49 +++++++++++------------ kernel/cobalt/syscall.c | 66 +++++++++++++++++++++++++++++-- kernel/drivers/can/sja1000/Makefile | 3 +- lib/cobalt/mutex.c | 73 ++++++++++++++++------------------ 4 files changed, 121 insertions(+), 70 deletions(-) diff --git a/include/cobalt/syscall.h b/include/cobalt/syscall.h index 56c4700..ab1d16e 100644 --- a/include/cobalt/syscall.h +++ b/include/cobalt/syscall.h @@ -42,31 +42,30 @@ #define __cobalt_clock_settime 16 #define __cobalt_clock_nanosleep 17 #define __cobalt_mutex_init 18 -#define __cobalt_mutex_destroy 19 -#define __cobalt_mutex_lock 20 -#define __cobalt_mutex_timedlock 21 -#define __cobalt_mutex_trylock 22 -#define __cobalt_check_init __cobalt_mutex_trylock -#define __cobalt_mutex_unlock 23 -#define __cobalt_cond_init 24 -#define __cobalt_cond_destroy 25 -#define __cobalt_cond_wait_prologue 26 -#define __cobalt_cond_wait_epilogue 27 -#define __cobalt_cond_signal 28 -#define __cobalt_cond_broadcast 29 -#define __cobalt_mq_open 30 -#define __cobalt_mq_close 31 -#define __cobalt_mq_unlink 32 -#define __cobalt_mq_getattr 33 -#define __cobalt_mq_setattr 34 -#define __cobalt_mq_send 35 -#define __cobalt_mq_timedsend 36 -#define __cobalt_mq_receive 37 -#define __cobalt_mq_timedreceive 38 -#define __cobalt_thread_probe 39 -#define __cobalt_sched_minprio 40 -#define __cobalt_sched_maxprio 41 -#define __cobalt_unimp_42 42 +#define __cobalt_check_init 19 +#define __cobalt_mutex_destroy 20 +#define __cobalt_mutex_lock 21 +#define __cobalt_mutex_timedlock 22 +#define __cobalt_mutex_trylock 23 +#define __cobalt_mutex_unlock 24 +#define __cobalt_cond_init 25 +#define __cobalt_cond_destroy 26 +#define __cobalt_cond_wait_prologue 27 +#define __cobalt_cond_wait_epilogue 28 +#define __cobalt_cond_signal 29 +#define __cobalt_cond_broadcast 30 +#define __cobalt_mq_open 31 +#define __cobalt_mq_close 32 +#define __cobalt_mq_unlink 33 +#define __cobalt_mq_getattr 34 +#define __cobalt_mq_setattr 35 +#define __cobalt_mq_send 36 +#define __cobalt_mq_timedsend 37 +#define __cobalt_mq_receive 38 +#define __cobalt_mq_timedreceive 39 +#define __cobalt_thread_probe 40 +#define __cobalt_sched_minprio 41 +#define __cobalt_sched_maxprio 42 #define __cobalt_timer_create 43 #define __cobalt_timer_delete 44 #define __cobalt_timer_settime 45 diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c index dfb2520..140a12d 100644 --- a/kernel/cobalt/syscall.c +++ b/kernel/cobalt/syscall.c @@ -1078,6 +1078,8 @@ static int __pthread_mutex_init(union __xeno_mutex __user *u_mx, &mx.shadow_mutex, sizeof(u_mx->shadow_mutex)); } +#define __pthread_mutex_check_init __cobalt_call_not_available + static int __pthread_mutex_destroy(union __xeno_mutex __user *u_mx) { union __xeno_mutex mx; @@ -1331,6 +1333,65 @@ static int __pthread_mutex_destroy(union __xeno_mutex __user *u_mx) shadow, sizeof(u_mx->shadow_mutex)); } +static int __pthread_mutex_trylock(union __xeno_mutex __user *u_mx) +{ + xnthread_t *cur = xnpod_current_thread(); + struct __shadow_mutex *shadow; + cobalt_mutex_t *mutex; + union __xeno_mutex mx; + int err; + + if (__xn_safe_copy_from_user(&mx.shadow_mutex, + &u_mx->shadow_mutex, + offsetof(struct __shadow_mutex, lock))) + return -EFAULT; + + shadow = &mx.shadow_mutex; + mutex = shadow->mutex; + + if (!cobalt_obj_active(shadow, COBALT_MUTEX_MAGIC, + struct __shadow_mutex) + || !cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC, + struct cobalt_mutex)) { + return -EINVAL; + } + + err = xnsynch_fast_acquire(mutex->synchbase.fastlock, + xnthread_handle(cur)); + switch(err) { + case 0: + if (xnthread_test_state(cur, XNOTHER)) + xnthread_inc_rescnt(cur); + shadow->lockcnt = 1; + break; + + case -EBUSY: +/* This should not happen, as recursive mutexes are handled in + user-space */ + if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) { + if (shadow->lockcnt == UINT_MAX) + err = -EAGAIN; + else { + ++shadow->lockcnt; + err = 0; + } + } + break; + + case -EAGAIN: + err = -EBUSY; + break; + } + + if (err == 0 && + __xn_safe_copy_to_user(&u_mx->shadow_mutex.lockcnt, + &shadow->lockcnt, + sizeof(u_mx->shadow_mutex.lockcnt))) + return -EFAULT; + + return err; +} + static int __pthread_mutex_lock(union __xeno_mutex __user *u_mx) { struct __shadow_mutex *shadow; @@ -2586,14 +2647,11 @@ static struct xnsysent __systab[] = { SKINCALL_DEF(__cobalt_clock_settime, __clock_settime, any), SKINCALL_DEF(__cobalt_clock_nanosleep, __clock_nanosleep, nonrestartable), SKINCALL_DEF(__cobalt_mutex_init, __pthread_mutex_init, any), + SKINCALL_DEF(__cobalt_check_init, __pthread_mutex_check_init, any), SKINCALL_DEF(__cobalt_mutex_destroy, __pthread_mutex_destroy, any), SKINCALL_DEF(__cobalt_mutex_lock, __pthread_mutex_lock, primary), SKINCALL_DEF(__cobalt_mutex_timedlock, __pthread_mutex_timedlock, primary), -#ifndef CONFIG_XENO_FASTSYNCH SKINCALL_DEF(__cobalt_mutex_trylock, __pthread_mutex_trylock, primary), -#else - SKINCALL_DEF(__cobalt_check_init, __pthread_mutex_check_init, any), -#endif SKINCALL_DEF(__cobalt_mutex_unlock, __pthread_mutex_unlock, nonrestartable), SKINCALL_DEF(__cobalt_cond_init, __pthread_cond_init, any), SKINCALL_DEF(__cobalt_cond_destroy, __pthread_cond_destroy, any), diff --git a/kernel/drivers/can/sja1000/Makefile b/kernel/drivers/can/sja1000/Makefile index 23dc1f5..73e047f 100644 --- a/kernel/drivers/can/sja1000/Makefile +++ b/kernel/drivers/can/sja1000/Makefile @@ -1,5 +1,4 @@ - -ccflags-y := -D__IN_XENOMAI__ -Iinclude/xenomai -Idrivers/xenomai/can -Idrivers/xenomai/can/sja1000 +ccflags-y := -D__IN_XENOMAI__ -Iinclude/xenomai -Iinclude/xenomai/cobalt -Idrivers/xenomai/can -Idrivers/xenomai/can/sja1000 obj-$(CONFIG_XENO_DRIVERS_CAN_SJA1000) += xeno_can_sja1000.o obj-$(CONFIG_XENO_DRIVERS_CAN_SJA1000_PEAK_PCI) += xeno_can_peak_pci.o diff --git a/lib/cobalt/mutex.c b/lib/cobalt/mutex.c index d63e177..94bd488 100644 --- a/lib/cobalt/mutex.c +++ b/lib/cobalt/mutex.c @@ -290,36 +290,40 @@ int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex) int err; #ifdef CONFIG_XENO_FASTSYNCH - unsigned long status; + xnarch_atomic_t *ownerp; xnhandle_t cur; cur = xeno_get_current(); if (cur == XN_NO_HANDLE) return EPERM; - status = xeno_get_current_mode(); - if (unlikely(status & XNOTHER)) - goto do_syscall; - if (unlikely(cb_try_read_lock(&shadow->lock, s))) return EINVAL; if (unlikely(shadow->magic != COBALT_MUTEX_MAGIC)) { - err = -EINVAL; + err = EINVAL; goto out; } - if (unlikely(status & XNRELAX)) { - do { - err = XENOMAI_SYSCALL1(__xn_sys_migrate, - XENOMAI_XENO_DOMAIN); - } while (err == -EINTR); - - if (err < 0) - goto out; + ownerp = get_ownerp(shadow); + err = xnsynch_fast_owner_check(ownerp, cur); + if (err == 0) { + if (shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) { + if (shadow->lockcnt == UINT_MAX) + err = EAGAIN; + else { + ++shadow->lockcnt; + err = 0; + } + } else + err = EBUSY; + goto out; } - err = xnsynch_fast_acquire(get_ownerp(shadow), cur); + if (unlikely(xeno_get_current_mode() & (XNOTHER | XNRELAX))) + goto do_syscall; + + err = xnsynch_fast_acquire(ownerp, cur); if (likely(!err)) { shadow->lockcnt = 1; @@ -327,29 +331,23 @@ int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex) return 0; } - if (err == -EBUSY && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) { - if (shadow->lockcnt == UINT_MAX) - err = -EAGAIN; - else { - ++shadow->lockcnt; - err = 0; - } - } else - err = -EBUSY; - - out: - cb_read_unlock(&shadow->lock, s); - return -err; + err = EBUSY; + goto out; do_syscall: -#endif /* !CONFIG_XENO_FASTSYNCH */ +#endif /* CONFIG_XENO_FASTSYNCH */ do { - err = XENOMAI_SKINCALL1(__cobalt_muxid, - __cobalt_mutex_trylock, shadow); - } while (err == -EINTR); + err = -XENOMAI_SKINCALL1(__cobalt_muxid, + __cobalt_mutex_trylock, shadow); + } while (err == EINTR); - return -err; +#ifdef CONFIG_XENO_FASTSYNCH + out: + cb_read_unlock(&shadow->lock, s); +#endif /* CONFIG_XENO_FASTSYNCH */ + + return err; } int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) @@ -360,15 +358,12 @@ int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) #ifdef CONFIG_XENO_FASTSYNCH xnarch_atomic_t *ownerp; - unsigned long status; xnhandle_t cur; cur = xeno_get_current(); if (cur == XN_NO_HANDLE) return EPERM; - status = xeno_get_current_mode(); - if (unlikely(cb_try_read_lock(&shadow->lock, s))) return EINVAL; @@ -377,9 +372,6 @@ int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) goto out_err; } - if (unlikely(status & XNOTHER)) - goto do_syscall; - ownerp = get_ownerp(shadow); err = xnsynch_fast_owner_check(ownerp, cur); @@ -391,6 +383,9 @@ int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) goto out; } + if (unlikely(xeno_get_current_mode() & XNOTHER)) + goto do_syscall; + if (likely(xnsynch_fast_release(ownerp, cur))) { out: cb_read_unlock(&shadow->lock, s); _______________________________________________ Xenomai-git mailing list [email protected] https://mail.gna.org/listinfo/xenomai-git
