9
9
* thread.
10
10
* 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
11
11
* 2022-05-10 xiangxistu Modify the recycle logic about resource of pthread.
12
+ * 2024-04-15 atwww Modify the recycle logic of TLS in function _pthread_data_destroy,
13
+ * make it safe for C++11's thread_local destructors.
12
14
*/
13
15
14
16
#include <rthw.h>
@@ -85,9 +87,27 @@ pthread_t _pthread_data_create(void)
85
87
return index ;
86
88
}
87
89
88
- void _pthread_data_destroy ( _pthread_data_t * ptd )
90
+ static inline void _destroy_item ( int index , _pthread_data_t * ptd )
89
91
{
90
92
extern _pthread_key_data_t _thread_keys [PTHREAD_KEY_MAX ];
93
+ void * data ;
94
+
95
+ if (_thread_keys [index ].is_used )
96
+ {
97
+ data = ptd -> tls [index ];
98
+ if (data && _thread_keys [index ].destructor )
99
+ {
100
+ _thread_keys [index ].destructor (data );
101
+ }
102
+ }
103
+ }
104
+
105
+ #ifdef RT_USING_CPLUSPLUS11
106
+ #define NOT_USE_CXX_TLS -1
107
+ #endif
108
+
109
+ void _pthread_data_destroy (_pthread_data_t * ptd )
110
+ {
91
111
pthread_t pth ;
92
112
93
113
if (ptd )
@@ -97,18 +117,37 @@ void _pthread_data_destroy(_pthread_data_t *ptd)
97
117
*/
98
118
if (ptd -> tls != RT_NULL )
99
119
{
100
- void * data ;
101
- rt_uint32_t index ;
102
- for (index = 0 ; index < PTHREAD_KEY_MAX ; index ++ )
120
+ int index ;
121
+ #ifdef RT_USING_CPLUSPLUS11
122
+ /* If C++11 is enabled and emutls is used,
123
+ * destructors of C++ object must be called safely.
124
+ */
125
+ extern pthread_key_t emutls_get_pthread_key (void );
126
+ pthread_key_t emutls_pthread_key = emutls_get_pthread_key ();
127
+
128
+ if (emutls_pthread_key != NOT_USE_CXX_TLS )
103
129
{
104
- if (_thread_keys [index ].is_used )
130
+ /* If execution reaches here, C++ 'thread_local' may be used.
131
+ * Destructors of c++ class object must be called before emutls_key_destructor.
132
+ */
133
+ int start = ((emutls_pthread_key - 1 + PTHREAD_KEY_MAX ) % PTHREAD_KEY_MAX );
134
+ int i = 0 ;
135
+ for (index = start ; i < PTHREAD_KEY_MAX ; index = (index - 1 + PTHREAD_KEY_MAX ) % PTHREAD_KEY_MAX , i ++ )
105
136
{
106
- data = ptd -> tls [index ];
107
- if (data && _thread_keys [index ].destructor )
108
- _thread_keys [index ].destructor (data );
137
+ _destroy_item (index , ptd );
138
+ }
139
+ }
140
+ else
141
+ #endif
142
+ {
143
+ /* If only C TLS is used, that is, POSIX TLS or __Thread_local,
144
+ * just iterate the _thread_keys from index 0.
145
+ */
146
+ for (index = 0 ; index < PTHREAD_KEY_MAX ; index ++ )
147
+ {
148
+ _destroy_item (index , ptd );
109
149
}
110
150
}
111
-
112
151
/* release tls area */
113
152
rt_free (ptd -> tls );
114
153
ptd -> tls = RT_NULL ;
0 commit comments