From 0109bcad8c61a19cf19a43f39cdfff7bedfa78e1 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Nihei Date: Tue, 30 Mar 2021 14:04:27 -0300 Subject: [PATCH] libs/libc: Update pthread_once according to the specification OpenGroup specification was updated regarding the return value for pthread_once, which after Issue 7 states that "the [EINVAL] error for an uninitialized pthread_once_t object is removed; this condition results in undefined behavior". --- libs/libc/pthread/pthread_once.c | 45 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/libs/libc/pthread/pthread_once.c b/libs/libc/pthread/pthread_once.c index c662f15de8..0e6060a008 100644 --- a/libs/libc/pthread/pthread_once.c +++ b/libs/libc/pthread/pthread_once.c @@ -24,10 +24,10 @@ #include +#include #include #include #include -#include #include /**************************************************************************** @@ -38,14 +38,14 @@ * Name: pthread_once * * Description: - * The first call to pthread_once() by any thread with a given + * The first call to pthread_once() by any thread with a given * once_control, will call the init_routine with no arguments. Subsequent * calls to pthread_once() with the same once_control will have no effect. * On return from pthread_once(), init_routine will have completed. * * Input Parameters: * once_control - Determines if init_routine should be called. - * once_control should be declared and initializeed as follows: + * once_control should be declared and initialized as follows: * * pthread_once_t once_control = PTHREAD_ONCE_INIT; * @@ -53,8 +53,8 @@ * init_routine - The initialization routine that will be called once. * * Returned Value: - * 0 (OK) on success or EINVAL if either once_control or init_routine are - * invalid + * 0 (OK) on success or an error number shall be returned to + * indicate the error. * * Assumptions: * @@ -65,31 +65,28 @@ int pthread_once(FAR pthread_once_t *once_control, { /* Sanity checks */ - if (once_control && init_routine) + DEBUGASSERT(once_control != NULL); + DEBUGASSERT(init_routine != NULL); + + /* Prohibit pre-emption while we test and set the once_control. */ + + sched_lock(); + + if (!*once_control) { - /* Prohibit pre-emption while we test and set the once_control */ + *once_control = true; - sched_lock(); - if (!*once_control) - { - *once_control = true; - - /* Call the init_routine with pre-emption enabled. */ - - sched_unlock(); - init_routine(); - return OK; - } - - /* The init_routine has already been called. - * Restore pre-emption and return - */ + /* Call the init_routine with pre-emption enabled. */ sched_unlock(); + init_routine(); return OK; } - /* One of the two arguments is NULL */ + /* The init_routine has already been called. + * Restore pre-emption and return. + */ - return EINVAL; + sched_unlock(); + return OK; }