Module: xenomai-2.6 Branch: master Commit: cd1c762280126f78c9e8fa3e4118a912dd0e0563 URL: http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=cd1c762280126f78c9e8fa3e4118a912dd0e0563
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Thu Jun 16 15:11:29 2016 +0200 posix: fix pthread_once The pthread_once implementation was broken, fix it. It becomes restricted to Xenomai threads, but this functionality makes no sense for modules init functions, as a module init function is guaranteed to be executed once by definition. --- ksrc/skins/posix/module.c | 43 +++++++++++++------ ksrc/skins/posix/once.c | 104 +++++++++++++++++++++++++++++++++++++++------ ksrc/skins/posix/once.h | 8 ++++ 3 files changed, 130 insertions(+), 25 deletions(-) diff --git a/ksrc/skins/posix/module.c b/ksrc/skins/posix/module.c index eea6e13..b0c40a2 100644 --- a/ksrc/skins/posix/module.c +++ b/ksrc/skins/posix/module.c @@ -63,6 +63,7 @@ #include <posix/timer.h> #include <posix/registry.h> #include <posix/shm.h> +#include <posix/once.h> MODULE_DESCRIPTION("POSIX/PSE51 interface"); MODULE_AUTHOR("gilles.chanteperd...@xenomai.org"); @@ -86,6 +87,7 @@ static void pse51_shutdown(int xtype) #endif /* CONFIG_XENO_OPT_POSIX_SHM */ pse51_timer_pkg_cleanup(); pse51_mq_pkg_cleanup(); + pse51_once_pkg_cleanup(); pse51_cond_pkg_cleanup(); pse51_tsd_pkg_cleanup(); pse51_sem_pkg_cleanup(); @@ -129,19 +131,9 @@ int SKIN_INIT(posix) #ifdef CONFIG_XENO_OPT_PERVASIVE err = pse51_syscall_init(); + if (err != 0) + goto fail_apc_cleanup; #endif /* CONFIG_XENO_OPT_PERVASIVE */ - if (err != 0) { -#ifdef __KERNEL__ - pse51_apc_pkg_cleanup(); - fail_free_tbase: -#endif /* __KERNEL__ */ - xntbase_free(pse51_tbase); - fail_shutdown_pod: - xnpod_shutdown(err); - fail: - xnlogerr("POSIX skin init failed, code %d.\n", err); - return err; - } pse51_reg_pkg_init(CONFIG_XENO_OPT_POSIX_REGISTRY_NRSLOTS, CONFIG_XENO_OPT_POSIX_REGISTRY_NRDESCS); @@ -150,6 +142,11 @@ int SKIN_INIT(posix) pse51_sem_pkg_init(); pse51_tsd_pkg_init(); pse51_cond_pkg_init(); + + err = pse51_once_pkg_init(); + if (err) + goto fail_cond_cleanup; + pse51_mq_pkg_init(); #ifdef CONFIG_XENO_OPT_POSIX_INTR pse51_intr_pkg_init(); @@ -162,6 +159,28 @@ int SKIN_INIT(posix) pse51_thread_pkg_init(module_param_value(time_slice_arg)); return 0; + + fail_cond_cleanup: + pse51_cond_pkg_cleanup(); + pse51_tsd_pkg_cleanup(); + pse51_sem_pkg_cleanup(); + pse51_mutex_pkg_cleanup(); + pse51_signal_pkg_cleanup(); + pse51_reg_pkg_cleanup(); +#ifdef CONFIG_XENO_OPT_PERVASIVE + pse51_syscall_cleanup(); + fail_apc_cleanup: +#endif /* CONFIG_XENO_OPT_PERVASIVE */ +#ifdef __KERNEL__ + pse51_apc_pkg_cleanup(); + fail_free_tbase: +#endif /* __KERNEL__ */ + xntbase_free(pse51_tbase); + fail_shutdown_pod: + xnpod_shutdown(err); + fail: + xnlogerr("POSIX skin init failed, code %d.\n", err); + return err; } void SKIN_EXIT(posix) diff --git a/ksrc/skins/posix/once.c b/ksrc/skins/posix/once.c index 8787c1f..ca8c2dd 100644 --- a/ksrc/skins/posix/once.c +++ b/ksrc/skins/posix/once.c @@ -23,6 +23,9 @@ #include <posix/internal.h> +static pthread_mutex_t mutex; +static pthread_cond_t cond; + /** * Execute an initialization routine. * @@ -35,34 +38,109 @@ * @return 0 on success; * @return an error number if: * - EINVAL, the object pointed to by @a once is invalid (it must have been - * initialized with PTHREAD_ONCE_INIT). + * initialized with PTHREAD_ONCE_INIT); + * - EPERM, the caller context is invalid. + * + * @par Valid contexts: + * - Xenomai kernel-space thread. * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_once.html"> * Specification.</a> * */ -int pthread_once(pthread_once_t * once, void (*init_routine) (void)) + +static void once_cleanup(void *cookie) +{ + pthread_once_t *once = cookie; + + pthread_mutex_lock(&mutex); + once->routine_called = 0; + pthread_cond_broadcast(&cond); + pthread_mutex_unlock(&mutex); +} + +int pthread_once(pthread_once_t *once, void (*init_routine)(void)) { - spl_t s; + int err; - xnlock_get_irqsave(&nklock, s); + err = pthread_mutex_lock(&mutex); + if (err) + return err; if (!pse51_obj_active(once, PSE51_ONCE_MAGIC, pthread_once_t)) { - xnlock_put_irqrestore(&nklock, s); - return EINVAL; + err = EINVAL; + goto out; } - if (!once->routine_called) { - init_routine(); - /* If the calling thread is canceled while executing init_routine, - routine_called will not be set to 1. */ - once->routine_called = 1; + while (once->routine_called != 2) + switch (once->routine_called) { + case 0: + once->routine_called = 1; + pthread_mutex_unlock(&mutex); + + pthread_cleanup_push(once_cleanup, once); + init_routine(); + pthread_cleanup_pop(0); + + pthread_mutex_lock(&mutex); + once->routine_called = 2; + pthread_cond_broadcast(&cond); + break; + + case 1: + err = pthread_cond_wait(&cond, &mutex); + if (err) + goto out; + break; + + default: + err = EINVAL; + goto out; + } + + out: + pthread_mutex_unlock(&mutex); + + return err; +} + +int pse51_once_pkg_init(void) +{ + pthread_mutexattr_t tattr; + int err; + + err = pthread_mutexattr_init(&tattr); + if (err) { + printk("Posix: pthread_once/pthread_mutexattr_init: %d\n", err); + return err; + } + + err = pthread_mutexattr_setprotocol(&tattr, PTHREAD_PRIO_INHERIT); + if (err) { + printk("Posix: pthread_once/set_protocol: %d\n", err); + return err; } - xnlock_put_irqrestore(&nklock, s); + err = pthread_mutex_init(&mutex, &tattr); + if (err) { + printk("Posix: pthread_once/mutex_init: %d\n", err); + return err; + } + + err = pthread_cond_init(&cond, NULL); + if (err) { + printk("Posix: pthread_once/cond_init: %d\n", err); + pthread_mutex_destroy(&mutex); + } - return 0; + return err; +} + +void pse51_once_pkg_cleanup(void) +{ + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); } /*@}*/ diff --git a/ksrc/skins/posix/once.h b/ksrc/skins/posix/once.h new file mode 100644 index 0000000..4019b4d --- /dev/null +++ b/ksrc/skins/posix/once.h @@ -0,0 +1,8 @@ +#ifndef _POSIX_ONCE_H +#define _POSIX_ONCE_H + +int pse51_once_pkg_init(void); + +void pse51_once_pkg_cleanup(void); + +#endif /* _POSIX_ONCE_H */ _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git