From bd76e69f8df302b07cf5feee6bdbef0bf1b0091e Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Fri, 27 May 2022 04:55:42 +0800 Subject: [PATCH] tls: Merge tls_xxx into pthread_keyxxx it's always better to provide the standard api directly Signed-off-by: Xiang Xiao --- include/nuttx/tls.h | 82 -------------- libs/libc/pthread/pthread_getspecific.c | 24 +++- libs/libc/pthread/pthread_keycreate.c | 43 ++++++-- libs/libc/pthread/pthread_keydelete.c | 36 +++++- libs/libc/pthread/pthread_setspecific.c | 22 +++- libs/libc/tls/Make.defs | 8 +- libs/libc/tls/{tls_setvalue.c => task_tls.c} | 45 +++----- libs/libc/tls/tls_alloc.c | 100 ----------------- libs/libc/tls/tls_free.c | 90 --------------- libs/libc/tls/tls_getvalue.c | 110 ------------------- 10 files changed, 128 insertions(+), 432 deletions(-) rename libs/libc/tls/{tls_setvalue.c => task_tls.c} (73%) delete mode 100644 libs/libc/tls/tls_alloc.c delete mode 100644 libs/libc/tls/tls_free.c delete mode 100644 libs/libc/tls/tls_getvalue.c diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index 27e031e3e1..846e7010e3 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -209,88 +209,6 @@ struct tls_info_s * Public Function Prototypes ****************************************************************************/ -/**************************************************************************** - * Name: tls_alloc - * - * Description: - * Allocate a group-unique TLS data index - * - * Input Parameters: - * dtor - The destructor of TLS data element - * - * Returned Value: - * A TLS index that is unique for use within this task group. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_alloc(CODE void (*dtor)(FAR void *)); -#endif - -/**************************************************************************** - * Name: tls_free - * - * Description: - * Release a group-unique TLS data index previous obtained by tls_alloc() - * - * Input Parameters: - * tlsindex - The previously allocated TLS index to be freed - * - * Returned Value: - * OK is returned on success; a negated errno value will be returned on - * failure: - * - * -EINVAL - the index to be freed is out of range. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_free(int tlsindex); -#endif - -/**************************************************************************** - * Name: tls_get_value - * - * Description: - * Return an the TLS data value associated with the 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of TLS data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero is returned in the event of an error, but zero may also - * be valid value and returned when there is no error. The only possible - * error would be if tlsindex < 0 or tlsindex >=CONFIG_TLS_NELEM. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -uintptr_t tls_get_value(int tlsindex); -#endif - -/**************************************************************************** - * Name: tls_set_value - * - * Description: - * Set the TLS element associated with the 'tlsindex' to 'tlsvalue' - * - * Input Parameters: - * tlsindex - Index of TLS data element to set - * tlsvalue - The new value of the TLS data element - * - * Returned Value: - * Zero is returned on success, a negated errno value is return on - * failure: - * - * EINVAL - tlsindex is not in range. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_set_value(int tlsindex, uintptr_t tlsvalue); -#endif - #if CONFIG_TLS_TASK_NELEM > 0 /**************************************************************************** diff --git a/libs/libc/pthread/pthread_getspecific.c b/libs/libc/pthread/pthread_getspecific.c index def22b9129..15bec11e68 100644 --- a/libs/libc/pthread/pthread_getspecific.c +++ b/libs/libc/pthread/pthread_getspecific.c @@ -25,9 +25,13 @@ #include #include +#include +#include #include +#if CONFIG_TLS_NELEM > 0 + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -59,5 +63,23 @@ FAR void *pthread_getspecific(pthread_key_t key) { - return (FAR void *)tls_get_value((int)key); + FAR struct tls_info_s *info; + FAR void *ret = NULL; + + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* Get the TLS info structure from the current threads stack */ + + info = up_tls_info(); + DEBUGASSERT(info != NULL); + + /* Get the element value from the TLS info. */ + + ret = (FAR void *)info->tl_elem[key]; + } + + return ret; } + +#endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_keycreate.c b/libs/libc/pthread/pthread_keycreate.c index fb9e458b8d..478dedec1f 100644 --- a/libs/libc/pthread/pthread_keycreate.c +++ b/libs/libc/pthread/pthread_keycreate.c @@ -26,7 +26,9 @@ #include #include +#include +#include #include #if CONFIG_TLS_NELEM > 0 @@ -70,23 +72,46 @@ int pthread_key_create(FAR pthread_key_t *key, CODE void (*destructor)(FAR void *)) { - int tlsindex; + FAR struct task_info_s *info = task_get_info(); + int candidate; + int ret; DEBUGASSERT(key != NULL); + DEBUGASSERT(info != NULL); - /* Allocate a TLS index */ + /* Search for an unused index. This is done in a critical section here to + * avoid concurrent modification of the group TLS index set. + */ - tlsindex = tls_alloc(destructor); + ret = _SEM_WAIT(&info->ta_sem); - /* Check if found a TLS index. */ - - if (tlsindex >= 0) + if (ret < 0) { - *key = tlsindex; - return OK; + ret = _SEM_ERRNO(ret); + return ret; } - return -tlsindex; + ret = EAGAIN; + + for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) + { + /* Is this candidate index available? */ + + tls_ndxset_t mask = (tls_ndxset_t)1 << candidate; + if ((info->ta_tlsset & mask) == 0) + { + /* Yes.. allocate the index and break out of the loop */ + + info->ta_tlsset |= mask; + info->ta_tlsdtor[candidate] = destructor; + *key = candidate; + ret = OK; + break; + } + } + + _SEM_POST(&info->ta_sem); + return ret; } #endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_keydelete.c b/libs/libc/pthread/pthread_keydelete.c index ad5ab06af4..51693a4337 100644 --- a/libs/libc/pthread/pthread_keydelete.c +++ b/libs/libc/pthread/pthread_keydelete.c @@ -25,9 +25,14 @@ #include #include +#include +#include +#include #include +#if CONFIG_TLS_NELEM > 0 + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -52,8 +57,33 @@ int pthread_key_delete(pthread_key_t key) { - /* Free the TLS index */ + FAR struct task_info_s *info = task_get_info(); + tls_ndxset_t mask; + int ret = EINVAL; - int ret = tls_free((int)key); - return ret < 0 ? -ret : 0; + DEBUGASSERT(info != NULL); + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* This is done while holding a semaphore here to avoid concurrent + * modification of the group TLS index set. + */ + + mask = (tls_ndxset_t)1 << key; + ret = _SEM_WAIT(&info->ta_sem); + if (ret == OK) + { + DEBUGASSERT((info->ta_tlsset & mask) != 0); + info->ta_tlsset &= ~mask; + _SEM_POST(&info->ta_sem); + } + else + { + ret = _SEM_ERRNO(ret); + } + } + + return ret; } + +#endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_setspecific.c b/libs/libc/pthread/pthread_setspecific.c index 40ed44270f..c40d36a915 100644 --- a/libs/libc/pthread/pthread_setspecific.c +++ b/libs/libc/pthread/pthread_setspecific.c @@ -25,7 +25,9 @@ #include #include +#include +#include #include #if CONFIG_TLS_NELEM > 0 @@ -72,9 +74,23 @@ int pthread_setspecific(pthread_key_t key, FAR const void *value) { - int ret = tls_set_value((int)key, (uintptr_t)value); - return ret < 0 ? -ret : 0; + FAR struct tls_info_s *info; + + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* Get the TLS info structure from the current threads stack */ + + info = up_tls_info(); + DEBUGASSERT(info != NULL); + + /* Set the element value int the TLS info. */ + + info->tl_elem[key] = (uintptr_t)value; + return OK; + } + + return EINVAL; } #endif /* CONFIG_TLS_NELEM */ - diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 5cb0a7e54f..f1e929b8e8 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -20,13 +20,15 @@ CSRCS += task_getinfo.c tls_getinfo.c +ifneq ($(CONFIG_TLS_TASK_NELEM),0) +CSRCS += task_tls.c +endif + ifneq ($(CONFIG_TLS_NELEM),0) -CSRCS += tls_alloc.c tls_free.c -CSRCS += tls_setvalue.c tls_getvalue.c tls_destruct.c +CSRCS += tls_destruct.c endif # Include tls build support DEPPATH += --dep-path tls VPATH += :tls - diff --git a/libs/libc/tls/tls_setvalue.c b/libs/libc/tls/task_tls.c similarity index 73% rename from libs/libc/tls/tls_setvalue.c rename to libs/libc/tls/task_tls.c index 6cf775df15..9c115eef55 100644 --- a/libs/libc/tls/tls_setvalue.c +++ b/libs/libc/tls/task_tls.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/tls/tls_setvalue.c + * libs/libc/tls/task_tls.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -24,61 +24,44 @@ #include -#include #include - -#include #include -#if CONFIG_TLS_NELEM > 0 +#if CONFIG_TLS_TASK_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: tls_set_value + * Name: task_tls_get_value * * Description: - * Set the TLS element associated with the 'tlsindex' to 'tlsvalue' + * Return an the task local storage data value associated with 'tlsindx' * * Input Parameters: - * tlsindex - Index of TLS data element to set - * tlsvalue - The new value of the TLS data element + * tlsindex - Index of task local storage data element to return * * Returned Value: - * Zero is returned on success, a negated errno value is return on - * failure: - * - * EINVAL - tlsindex is not in range. + * The value of TLS element associated with 'tlsindex'. Errors are not + * reported. Zero is returned in the event of an error, but zero may also + * be valid value and returned when there is no error. The only possible + * error would be if tlsindex < 0 or tlsindex >=CONFIG_TLS_TASK_NELEM. * ****************************************************************************/ -int tls_set_value(int tlsindex, uintptr_t tlsvalue) +uintptr_t task_tls_get_value(int tlsindex) { - FAR struct tls_info_s *info; + FAR struct task_info_s *info = task_get_info(); - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM) + if (tlsindex >= 0 && tlsindex < CONFIG_TLS_TASK_NELEM) { - /* Get the TLS info structure from the current threads stack */ - - info = up_tls_info(); - DEBUGASSERT(info != NULL); - - /* Set the element value int the TLS info. */ - - info->tl_elem[tlsindex] = tlsvalue; - return OK; + return info->ta_telem[tlsindex]; } - return -EINVAL; + return 0; } -#endif /* CONFIG_TLS_NELEM > 0 */ - -#if CONFIG_TLS_TASK_NELEM > 0 - /**************************************************************************** * Name: task_tls_set_value * diff --git a/libs/libc/tls/tls_alloc.c b/libs/libc/tls/tls_alloc.c deleted file mode 100644 index 46860d0ece..0000000000 --- a/libs/libc/tls/tls_alloc.c +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** - * libs/libc/tls/tls_alloc.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_alloc - * - * Description: - * Allocate a group-unique TLS data index - * - * Input Parameters: - * None - * - * Returned Value: - * A TLS index that is unique for use within this task group. - * If unsuccessful, an errno value will be returned and set to errno. - * - ****************************************************************************/ - -int tls_alloc(CODE void (*dtor)(FAR void *)) -{ - FAR struct task_info_s *info = task_get_info(); - int candidate; - int ret; - - DEBUGASSERT(info); - - /* Search for an unused index. This is done in a critical section here to - * avoid concurrent modification of the group TLS index set. - */ - - ret = _SEM_WAIT(&info->ta_sem); - - if (ret < 0) - { - ret = _SEM_ERRVAL(ret); - return ret; - } - - ret = -EAGAIN; - - for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) - { - /* Is this candidate index available? */ - - tls_ndxset_t mask = (tls_ndxset_t)1 << candidate; - if ((info->ta_tlsset & mask) == 0) - { - /* Yes.. allocate the index and break out of the loop */ - - info->ta_tlsset |= mask; - info->ta_tlsdtor[candidate] = dtor; - ret = candidate; - break; - } - } - - _SEM_POST(&info->ta_sem); - - return ret; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/libs/libc/tls/tls_free.c b/libs/libc/tls/tls_free.c deleted file mode 100644 index e9f7eb576f..0000000000 --- a/libs/libc/tls/tls_free.c +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** - * libs/libc/tls/tls_free.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include - -#include -#include -#include - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_free - * - * Description: - * Release a group-unique TLS data index previous obtained by tls_alloc() - * - * Input Parameters: - * tlsindex - The previously allocated TLS index to be freed - * - * Returned Value: - * OK is returned on success; - * If unsuccessful an errno value will be returned and set to errno. - * -EINVAL - the index to be freed is out of range. - * -EINTR - the wait operation interrupted by signal - * -ECANCELED - the thread was canceled during waiting - * - ****************************************************************************/ - -int tls_free(int tlsindex) -{ - FAR struct task_info_s *info = task_get_info(); - tls_ndxset_t mask; - int ret = -EINVAL; - - DEBUGASSERT((unsigned)tlsindex < CONFIG_TLS_NELEM && info != NULL); - if ((unsigned)tlsindex < CONFIG_TLS_NELEM) - { - /* This is done while holding a semaphore here to avoid concurrent - * modification of the group TLS index set. - */ - - mask = (1 << tlsindex); - - ret = _SEM_WAIT(&info->ta_sem); - if (ret == OK) - { - DEBUGASSERT((info->ta_tlsset & mask) != 0); - info->ta_tlsset &= ~mask; - _SEM_POST(&info->ta_sem); - } - else - { - ret = _SEM_ERRVAL(ret); - } - } - - return ret; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/libs/libc/tls/tls_getvalue.c b/libs/libc/tls/tls_getvalue.c deleted file mode 100644 index d6204ebd89..0000000000 --- a/libs/libc/tls/tls_getvalue.c +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * libs/libc/tls/tls_getvalue.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include - -#include -#include - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_get_value - * - * Description: - * Return an the TLS data value associated with the 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of TLS data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero is returned in the event of an error, but zero may also - * be valid value and returned when there is no error. The only possible - * error would be if tlsindex < 0 or tlsindex >=CONFIG_TLS_NELEM. - * - ****************************************************************************/ - -uintptr_t tls_get_value(int tlsindex) -{ - FAR struct tls_info_s *info; - uintptr_t ret = 0; - - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM) - { - /* Get the TLS info structure from the current threads stack */ - - info = up_tls_info(); - DEBUGASSERT(info != NULL); - - /* Get the element value from the TLS info. */ - - ret = info->tl_elem[tlsindex]; - } - - return ret; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ - -#if CONFIG_TLS_TASK_NELEM > 0 - -/**************************************************************************** - * Name: task_tls_get_value - * - * Description: - * Return an the task local storage data value associated with 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of task local storage data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero is returned in the event of an error, but zero may also - * be valid value and returned when there is no error. The only possible - * error would be if tlsindex < 0 or tlsindex >=CONFIG_TLS_TASK_NELEM. - * - ****************************************************************************/ - -uintptr_t task_tls_get_value(int tlsindex) -{ - FAR struct task_info_s *info = task_get_info(); - - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_TASK_NELEM) - { - return info->ta_telem[tlsindex]; - } - - return 0; -} - -#endif