diff options
author | Andrea Canciani <ranma42@gmail.com> | 2013-06-28 19:35:08 +0200 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2013-06-28 19:37:43 +0200 |
commit | 262d6c86a3802c2120a11620b348038966a6dc1e (patch) | |
tree | c681247e9bce2923c269ff04285ec31dff6dbf24 | |
parent | f5c51d4eb781f118bc7bf3250dcbc76d9c956ad4 (diff) |
tss: Fix win32 implementationc11
The win32 implementation was broken in multiple ways: it did not
compile, it contained bugs, it was missing proper initialization and
termination functions.
-rw-r--r-- | initfini/impl/_common.h | 2 | ||||
-rw-r--r-- | initfini/impl/msvc.h | 2 | ||||
-rw-r--r-- | tss/impl/win32.h | 48 | ||||
-rw-r--r-- | tss/internal/_dispatch.h | 10 | ||||
-rw-r--r-- | tss/internal/win32.h | 35 |
5 files changed, 69 insertions, 28 deletions
diff --git a/initfini/impl/_common.h b/initfini/impl/_common.h index f98937a..1b818b9 100644 --- a/initfini/impl/_common.h +++ b/initfini/impl/_common.h @@ -39,11 +39,13 @@ static void _simpleops_init_internals (void) { _simpleops_atomic_init (); + _simpleops_tss_init (); } static void _simpleops_fini_internals (void) { + _simpleops_tss_fini (); _simpleops_atomic_fini (); } diff --git a/initfini/impl/msvc.h b/initfini/impl/msvc.h index b040576..1505ebe 100644 --- a/initfini/impl/msvc.h +++ b/initfini/impl/msvc.h @@ -52,7 +52,7 @@ _simpleops_msvc_tss (HINSTANCE h, PVOID pv) { if (dwReason == DLL_THREAD_DETACH) - _simpleops_tss_destoy (); + _simpleops_tss_destroy (); } static int diff --git a/tss/impl/win32.h b/tss/impl/win32.h index f73588a..6adc02c 100644 --- a/tss/impl/win32.h +++ b/tss/impl/win32.h @@ -40,9 +40,12 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <stdlib.h> + +#include "simpleops/mtx.h" typedef struct _simpleops_tss { - struct _simpleops_tss *prev; + struct _simpleops_tss **prev; struct _simpleops_tss *next; DWORD idx; simpleops_tss_dtor_t dtor; @@ -52,46 +55,53 @@ typedef struct _simpleops_tss { #define _SIMPLEOPS_TSS_HEAD SIMPLEOPS_ADD_PREFIX (_simpleops_tss_head) extern simpleops_mtx_t _SIMPLEOPS_TSS_MTX; -extern simpleops_tss_t *_SIMPLEOPS_TSS_HEAD; +extern simpleops_tss_t _SIMPLEOPS_TSS_HEAD; static simpleops_always_inline int simpleops_tss_create (simpleops_tss_t *key, simpleops_tss_dtor_t dtor) { - *key = malloc (sizeof (*key)); - if (SIMPLEOPS_UNLIKELY (key == NULL)) + simpleops_tss_t tss; + + *key = NULL; + tss = malloc (sizeof (*tss)); + if (SIMPLEOPS_UNLIKELY (tss == NULL)) return simpleops_thrd_error; - simpleops_mtx_lock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_lock (&_SIMPLEOPS_TSS_MTX); - key->link = &SIMPLEOPS_TSS_HEAD; - key->next = SIMPLEOPS_TSS_HEAD; - key->idx = TlsAlloc (); - key->dtor = dtor; + tss->prev = &_SIMPLEOPS_TSS_HEAD; + tss->next = _SIMPLEOPS_TSS_HEAD; + tss->idx = TlsAlloc (); + tss->dtor = dtor; - if (SIMPLEOPS_UNLIKELY (key->idx == TLS_OUT_OF_INDEXES)) { - simpleops_mtx_unlock (&SIMPLEOPS_TSS_MTX); - free (key); - *key = NULL; + if (SIMPLEOPS_UNLIKELY (tss->idx == TLS_OUT_OF_INDEXES)) { + simpleops_mtx_unlock (&_SIMPLEOPS_TSS_MTX); + free (tss); return simpleops_thrd_error; } - SIMPLEOPS_TSS_HEAD->link = &key->next; - SIMPLEOPS_TSS_HEAD = key; + if (tss->next != NULL) + tss->next->prev = &tss->next; + *tss->prev = tss; - simpleops_mtx_unlock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_unlock (&_SIMPLEOPS_TSS_MTX); + *key = tss; return simpleops_thrd_success; } static simpleops_always_inline void simpleops_tss_delete (simpleops_tss_t key) { - simpleops_mtx_lock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_lock (&_SIMPLEOPS_TSS_MTX); + + if (key->next != NULL) + key->next->prev = key->prev; + *key->prev = key->next; - *key->link = key->next; TlsFree (key->idx); - simpleops_mtx_unlock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_unlock (&_SIMPLEOPS_TSS_MTX); free (key); } diff --git a/tss/internal/_dispatch.h b/tss/internal/_dispatch.h index 22e3919..12fc5a9 100644 --- a/tss/internal/_dispatch.h +++ b/tss/internal/_dispatch.h @@ -41,7 +41,15 @@ #if ! SIMPLEOPS_HAVE_TSS_INTERNAL -/* Just for consistency */ +static simpleops_always_inline void +_simpleops_tss_init (void) +{ +} + +static simpleops_always_inline void +_simpleops_tss_fini (void) +{ +} #endif diff --git a/tss/internal/win32.h b/tss/internal/win32.h index 89e5a04..20de99c 100644 --- a/tss/internal/win32.h +++ b/tss/internal/win32.h @@ -25,8 +25,8 @@ * Author(s): Andrea Canciani <ranma42@gmail.com> */ -#ifndef SIMPLEOPS_TSS_INTERNAL_H -#define SIMPLEOPS_TSS_INTERNAL_H +#ifndef SIMPLEOPS_TSS_INTERNAL_WIN32_H +#define SIMPLEOPS_TSS_INTERNAL_WIN32_H #ifndef SIMPLEOPS_TSS_INTERNAL_H #error Private header used directly @@ -37,26 +37,37 @@ #define SIMPLEOPS_HAVE_TSS_INTERNAL 1 -#if ! SIMPLEOPS_HAVE_TSS_DESTRUCTOR +#if ! SIMPLEOPS_HAVE_TSS_DESTROY #error "The TSS implementation requires a destruction callback" #endif +#ifndef SIMPLEOPS_TSS_DTOR_ITERATIONS +#define SIMPLEOPS_TSS_DTOR_ITERATIONS 16 +#endif + +simpleops_private simpleops_mtx_t _SIMPLEOPS_TSS_MTX; +simpleops_private simpleops_tss_t _SIMPLEOPS_TSS_HEAD; + static simpleops_always_inline void _simpleops_tss_destroy (void) { simpleops_tss_t key; void *val; + int i; + simpleops_bool_t ran_dtor; - simpleops_mtx_lock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_lock (&_SIMPLEOPS_TSS_MTX); for (i = 0; i < SIMPLEOPS_TSS_DTOR_ITERATIONS; i++) { - for (key = SIMPLEOPS_TSS_HEAD; key != NULL; key = key->next) { + ran_dtor = FALSE; + + for (key = _SIMPLEOPS_TSS_HEAD; key != NULL; key = key->next) { val = simpleops_tss_get (key); if (val != NULL) { simpleops_tss_set (key, NULL); if (key->dtor != NULL) { key->dtor (val); - ran_dtor = SIMPLEOPS_TRUE; + ran_dtor = TRUE; } } } @@ -65,10 +76,20 @@ _simpleops_tss_destroy (void) break; } - simpleops_mtx_unlock (&SIMPLEOPS_TSS_MTX); + simpleops_mtx_unlock (&_SIMPLEOPS_TSS_MTX); } +static simpleops_always_inline void +_simpleops_tss_init (void) +{ + simpleops_mtx_init (&_SIMPLEOPS_TSS_MTX, simpleops_mtx_plain); +} +static simpleops_always_inline void +_simpleops_tss_fini (void) +{ + simpleops_mtx_destroy (&_SIMPLEOPS_TSS_MTX); +} #endif |