修复C++11 thread_local对象析构函数与实际内存释放动作顺序相反问题
This commit is contained in:
parent
f55187f830
commit
b421b4e1f4
|
@ -9,6 +9,8 @@
|
||||||
* thread.
|
* thread.
|
||||||
* 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
|
* 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
|
||||||
* 2022-05-10 xiangxistu Modify the recycle logic about resource of pthread.
|
* 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>
|
#include <rthw.h>
|
||||||
|
@ -85,9 +87,27 @@ pthread_t _pthread_data_create(void)
|
||||||
return index;
|
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];
|
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;
|
pthread_t pth;
|
||||||
|
|
||||||
if (ptd)
|
if (ptd)
|
||||||
|
@ -97,18 +117,37 @@ void _pthread_data_destroy(_pthread_data_t *ptd)
|
||||||
*/
|
*/
|
||||||
if (ptd->tls != RT_NULL)
|
if (ptd->tls != RT_NULL)
|
||||||
{
|
{
|
||||||
void *data;
|
int index;
|
||||||
rt_uint32_t index;
|
#ifdef RT_USING_CPLUSPLUS11
|
||||||
for (index = 0; index < PTHREAD_KEY_MAX; index ++)
|
/* 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];
|
_destroy_item(index, ptd);
|
||||||
if (data && _thread_keys[index].destructor)
|
}
|
||||||
_thread_keys[index].destructor(data);
|
}
|
||||||
|
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 */
|
/* release tls area */
|
||||||
rt_free(ptd->tls);
|
rt_free(ptd->tls);
|
||||||
ptd->tls = RT_NULL;
|
ptd->tls = RT_NULL;
|
||||||
|
|
|
@ -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')
|
|
@ -6,6 +6,10 @@
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2021-04-27 peterfan Add copyright header.
|
* 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 ---------------===
|
/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
|
||||||
|
@ -109,7 +113,16 @@ typedef struct emutls_address_array
|
||||||
void *data[];
|
void *data[];
|
||||||
} emutls_address_array;
|
} 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)
|
static void emutls_key_destructor(void *ptr)
|
||||||
{
|
{
|
Loading…
Reference in New Issue