posix: fix pthread thread specific data cleanup

It was never deallocationg pthread_key_data nor it was removing the node
with it from list

Signed-off-by: Jakub Michalski <jmichalski@antmicro.com>
This commit is contained in:
Jakub Michalski 2024-11-20 15:21:09 +01:00 committed by Benjamin Cabé
parent 3d3ffa2c05
commit 044b702b90
3 changed files with 31 additions and 8 deletions

View file

@ -13,14 +13,9 @@
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/sem.h>
struct pthread_key_data {
sys_snode_t node;
pthread_thread_data thread_data;
};
LOG_MODULE_REGISTER(pthread_key, CONFIG_PTHREAD_KEY_LOG_LEVEL);
static SYS_SEM_DEFINE(pthread_key_lock, 1, 1);
SYS_SEM_DEFINE(pthread_key_lock, 1, 1);
/* This is non-standard (i.e. an implementation detail) */
#define PTHREAD_KEY_INITIALIZER (-1)

View file

@ -84,6 +84,11 @@ typedef struct pthread_thread_data {
void *spec_data;
} pthread_thread_data;
struct pthread_key_data {
sys_snode_t node;
pthread_thread_data thread_data;
};
static inline bool is_pthread_obj_initialized(uint32_t obj)
{
return (obj & PTHREAD_OBJ_MASK_INIT) != 0;

View file

@ -458,19 +458,42 @@ static void posix_thread_recycle_work_handler(struct k_work *work)
}
static K_WORK_DELAYABLE_DEFINE(posix_thread_recycle_work, posix_thread_recycle_work_handler);
extern struct sys_sem pthread_key_lock;
static void posix_thread_finalize(struct posix_thread *t, void *retval)
{
sys_snode_t *node_l;
sys_snode_t *node_l, *node_s;
pthread_key_obj *key_obj;
pthread_thread_data *thread_spec_data;
sys_snode_t *node_key_data, *node_key_data_s, *node_key_data_prev = NULL;
struct pthread_key_data *key_data;
SYS_SLIST_FOR_EACH_NODE(&t->key_list, node_l) {
SYS_SLIST_FOR_EACH_NODE_SAFE(&t->key_list, node_l, node_s) {
thread_spec_data = (pthread_thread_data *)node_l;
if (thread_spec_data != NULL) {
key_obj = thread_spec_data->key;
if (key_obj->destructor != NULL) {
(key_obj->destructor)(thread_spec_data->spec_data);
}
SYS_SEM_LOCK(&pthread_key_lock) {
SYS_SLIST_FOR_EACH_NODE_SAFE(
&key_obj->key_data_l,
node_key_data,
node_key_data_s) {
key_data = (struct pthread_key_data *)node_key_data;
if (&key_data->thread_data == thread_spec_data) {
sys_slist_remove(
&key_obj->key_data_l,
node_key_data_prev,
node_key_data
);
k_free(key_data);
break;
}
node_key_data_prev = node_key_data;
}
}
}
}