Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thread: add thread-local storage functions #355

Merged
merged 3 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/re_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ typedef INIT_ONCE once_flag;
typedef HANDLE thrd_t;
typedef CONDITION_VARIABLE cnd_t;
typedef CRITICAL_SECTION mtx_t;
typedef DWORD tss_t;

#else

Expand All @@ -36,6 +37,7 @@ typedef pthread_once_t once_flag;
typedef pthread_t thrd_t;
typedef pthread_cond_t cnd_t;
typedef pthread_mutex_t mtx_t;
typedef pthread_key_t tss_t;

#endif

Expand All @@ -50,6 +52,7 @@ enum {
thrd_timedout = 4
};

typedef void (*tss_dtor_t)(void *);
typedef int (*thrd_start_t)(void *);


Expand Down Expand Up @@ -224,6 +227,14 @@ int mtx_trylock(mtx_t *mtx);
int mtx_unlock(mtx_t *mtx);


/******************************************************************************
* Thread-local storage functions
*****************************************************************************/
int tss_create(tss_t *key, tss_dtor_t destructor);
void *tss_get(tss_t key);
int tss_set(tss_t key, void *val);
void tss_delete(tss_t key);

#endif /* C11 threads fallback */


Expand Down
29 changes: 29 additions & 0 deletions src/thread/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,32 @@ int mtx_unlock(mtx_t *mtx)

return (pthread_mutex_unlock(mtx) == 0) ? thrd_success : thrd_error;
}


int tss_create(tss_t *key, tss_dtor_t destructor)
{
if (!key)
return thrd_error;

return (pthread_key_create(key, destructor) == 0) ? thrd_success
: thrd_error;
}


void *tss_get(tss_t key)
{
return pthread_getspecific(key);
}


int tss_set(tss_t key, void *val)
{
return (pthread_setspecific(key, val) == 0) ? thrd_success
: thrd_error;
}


void tss_delete(tss_t key)
{
pthread_key_delete(key);
}
96 changes: 95 additions & 1 deletion src/thread/win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,71 @@
#include <re_thread.h>


#define DEBUG_MODULE "thread"
#define DEBUG_LEVEL 5
#include <re_dbg.h>

#define TSS_DESTRUCTOR_MAX 64

static struct tss_dtor_entry {
tss_t key;
tss_dtor_t dtor;
} tss_dtor_tbl[TSS_DESTRUCTOR_MAX];


struct thread {
thrd_start_t func;
void *arg;
};

static int tss_dtor_register(tss_t key, tss_dtor_t dtor)
{
int i;

for (i = 0; i < TSS_DESTRUCTOR_MAX; i++) {
if (!tss_dtor_tbl[i].dtor)
break;
}

if (i >= TSS_DESTRUCTOR_MAX) {
DEBUG_WARNING("thread: max tss destructors reached\n");
return ENOMEM;
}

tss_dtor_tbl[i].key = key;
tss_dtor_tbl[i].dtor = dtor;

return 0;
}


static void tss_dtor_destruct(void)
{
void *val;

for (int i = 0; i < TSS_DESTRUCTOR_MAX; i++) {
if (!tss_dtor_tbl[i].dtor)
continue;
val = tss_get(tss_dtor_tbl[i].key);
if (val) {
tss_dtor_tbl[i].dtor(val);
tss_dtor_tbl[i].dtor = NULL;
}
}
}


static unsigned __stdcall thrd_handler(void *p)
{
struct thread th = *(struct thread *)p;
int err;

mem_deref(p);
err = th.func(th.arg);

tss_dtor_destruct();

return th.func(th.arg);
return err;
}


Expand Down Expand Up @@ -207,3 +259,45 @@ int mtx_unlock(mtx_t *mtx)

return thrd_success;
}


int tss_create(tss_t *key, tss_dtor_t destructor)
{
int err;

if (!key)
return thrd_error;

*key = TlsAlloc();
if (*key == TLS_OUT_OF_INDEXES)
return thrd_error;

if (!destructor)
return thrd_success;

err = tss_dtor_register(*key, destructor);
if (err) {
TlsFree(*key);
return thrd_error;
}

return thrd_success;
}


void *tss_get(tss_t key)
{
return TlsGetValue(key);
}


int tss_set(tss_t key, void *val)
{
return TlsSetValue(key, val) ? thrd_success : thrd_error;
}


void tss_delete(tss_t key)
{
TlsFree(key);
}