summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/libc/posix/pthreads/pthread.c57
-rw-r--r--components/libc/posix/tls/SConscript9
-rw-r--r--components/libc/posix/tls/emutls.c (renamed from components/libc/cplusplus/cpp11/emutls.c)15
3 files changed, 71 insertions, 10 deletions
diff --git a/components/libc/posix/pthreads/pthread.c b/components/libc/posix/pthreads/pthread.c
index d035515be4..5cc3bbd7a7 100644
--- a/components/libc/posix/pthreads/pthread.c
+++ b/components/libc/posix/pthreads/pthread.c
@@ -9,6 +9,8 @@
* thread.
* 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
* 2022-05-10 xiangxistu Modify the recycle logic about resource of pthread.
+ * 2024-04-15 atwww Modify the recycle logic of TLS in function _pthread_data_destroy,
+ * make it safe for C++11's thread_local destructors.
*/
#include <rthw.h>
@@ -85,9 +87,27 @@ pthread_t _pthread_data_create(void)
return index;
}
-void _pthread_data_destroy(_pthread_data_t *ptd)
+static inline void _destroy_item(int index, _pthread_data_t *ptd)
{
extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
+ void *data;
+
+ if (_thread_keys[index].is_used)
+ {
+ data = ptd->tls[index];
+ if (data && _thread_keys[index].destructor)
+ {
+ _thread_keys[index].destructor(data);
+ }
+ }
+}
+
+#ifdef RT_USING_CPLUSPLUS11
+ #define NOT_USE_CXX_TLS -1
+#endif
+
+void _pthread_data_destroy(_pthread_data_t *ptd)
+{
pthread_t pth;
if (ptd)
@@ -97,18 +117,37 @@ void _pthread_data_destroy(_pthread_data_t *ptd)
*/
if (ptd->tls != RT_NULL)
{
- void *data;
- rt_uint32_t index;
- for (index = 0; index < PTHREAD_KEY_MAX; index ++)
+ int index;
+#ifdef RT_USING_CPLUSPLUS11
+ /* If C++11 is enabled and emutls is used,
+ * destructors of C++ object must be called safely.
+ */
+ extern pthread_key_t emutls_get_pthread_key(void);
+ pthread_key_t emutls_pthread_key = emutls_get_pthread_key();
+
+ if (emutls_pthread_key != NOT_USE_CXX_TLS)
{
- if (_thread_keys[index].is_used)
+ /* If execution reaches here, C++ 'thread_local' may be used.
+ * Destructors of c++ class object must be called before emutls_key_destructor.
+ */
+ int start = ((emutls_pthread_key - 1 + PTHREAD_KEY_MAX) % PTHREAD_KEY_MAX);
+ int i = 0;
+ for (index = start; i < PTHREAD_KEY_MAX; index = (index - 1 + PTHREAD_KEY_MAX) % PTHREAD_KEY_MAX, i ++)
{
- data = ptd->tls[index];
- if (data && _thread_keys[index].destructor)
- _thread_keys[index].destructor(data);
+ _destroy_item(index, ptd);
+ }
+ }
+ else
+#endif
+ {
+ /* If only C TLS is used, that is, POSIX TLS or __Thread_local,
+ * just iterate the _thread_keys from index 0.
+ */
+ for (index = 0; index < PTHREAD_KEY_MAX; index ++)
+ {
+ _destroy_item(index, ptd);
}
}
-
/* release tls area */
rt_free(ptd->tls);
ptd->tls = RT_NULL;
diff --git a/components/libc/posix/tls/SConscript b/components/libc/posix/tls/SConscript
new file mode 100644
index 0000000000..adcd07ee49
--- /dev/null
+++ b/components/libc/posix/tls/SConscript
@@ -0,0 +1,9 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('POSIX', src, depend = ['RT_USING_PTHREADS'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/libc/cplusplus/cpp11/emutls.c b/components/libc/posix/tls/emutls.c
index 52d1244c92..0bec347cf9 100644
--- a/components/libc/cplusplus/cpp11/emutls.c
+++ b/components/libc/posix/tls/emutls.c
@@ -6,6 +6,10 @@
* Change Logs:
* Date Author Notes
* 2021-04-27 peterfan Add copyright header.
+ * 2024-04-15 atwww Add emutls_get_pthread_key to make c++11's thread_local destructe safely.
+ * Use emutls_pthread_key to determine whether C++11 thread_local is used.
+ * Move this file from components\libc\cplusplus\cpp11 to components\libc\posix\tls,
+ * because _Thread_local in C will also use emutls.
*/
/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
@@ -109,7 +113,16 @@ typedef struct emutls_address_array
void *data[];
} emutls_address_array;
-static pthread_key_t emutls_pthread_key;
+static pthread_key_t emutls_pthread_key = -1; /* -1 means that TLS in C or C++ is not used. */
+
+pthread_key_t emutls_get_pthread_key(void)
+{
+ /* If program uses C or C++ TLS keyword, _Thread_local、__thread or thread_local,
+ * the function emutls_get_index will ensure that emutls_pthread_key is initialized once
+ * when it is first used. Therefore, there is no need to use synchronization measures here.
+ */
+ return emutls_pthread_key;
+}
static void emutls_key_destructor(void *ptr)
{