From 8ef70ad5cb5083f071713b64365a5387b1f557b6 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Thu, 24 Jun 2004 22:30:16 +0000 Subject: [PATCH] * threads.c: Reorganize code: One definition of each function, with per-platform conditional tests inside, instead of per-platform definitions for each function. Combine common aspects of each function across platforms. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16511 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/support/ChangeLog | 7 + src/util/support/threads.c | 351 ++++++++++++++++++------------------- 2 files changed, 177 insertions(+), 181 deletions(-) diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog index b8ef14bcb..534868d3a 100644 --- a/src/util/support/ChangeLog +++ b/src/util/support/ChangeLog @@ -1,3 +1,10 @@ +2004-06-24 Ken Raeburn + + * threads.c: Reorganize code: One definition of each function, + with per-platform conditional tests inside, instead of + per-platform definitions for each function. Combine common + aspects of each function across platforms. + 2004-06-21 Ken Raeburn * threads.c (key_lock): Change to a k5_mutex_t. diff --git a/src/util/support/threads.c b/src/util/support/threads.c index 60c0bad8c..e3d235999 100644 --- a/src/util/support/threads.c +++ b/src/util/support/threads.c @@ -36,113 +36,44 @@ MAKE_INIT_FUNCTION(krb5int_thread_support_init); MAKE_FINI_FUNCTION(krb5int_thread_support_fini); - -#ifdef ENABLE_THREADS +#ifndef ENABLE_THREADS /* no thread support */ -#ifdef _WIN32 - -static DWORD tls_idx; -CRITICAL_SECTION key_lock; static void (*destructors[K5_KEY_MAX])(void *); +struct tsd_block { void *values[K5_KEY_MAX]; }; +static struct tsd_block tsd_no_threads; static unsigned char destructors_set[K5_KEY_MAX]; -int krb5int_thread_support_init (void) -{ - tls_idx = TlsAlloc(); - /* XXX This can raise an exception if memory is low! */ - InitializeCriticalSection(&key_lock); - return 0; -} - -void krb5int_thread_support_fini (void) -{ - if (! INITIALIZER_RAN (krb5int_thread_support_init)) - return; - /* ... free stuff ... */ - TlsFree(tls_idx); - DeleteCriticalSection(&key_lock); -} - -int k5_key_register (k5_key_t keynum, void (*destructor)(void *)) -{ - DWORD wait_result; +#elif defined(_WIN32) - assert(keynum >= 0 && keynum < K5_KEY_MAX); - /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK. */ - EnterCriticalSection(&key_lock); - assert(destructors_set[keynum] == 0); - destructors_set[keynum] = 1; - destructors[keynum] = destructor; - LeaveCriticalSection(&key_lock); - return 0; -} +static DWORD tls_idx; +static CRITICAL_SECTION key_lock; +static void (*destructors[K5_KEY_MAX])(void *); +static unsigned char destructors_set[K5_KEY_MAX]; -void *k5_getspecific (k5_key_t keynum) +void krb5int_thread_detach_hook (void) { + /* XXX Memory leak here! + Need to destroy all TLS objects we know about for this thread. */ struct tsd_block *t; + int i, err; err = CALL_INIT_FUNCTION(krb5int_thread_support_init); if (err) - return NULL; - - assert(keynum >= 0 && keynum < K5_KEY_MAX); + return; t = TlsGetValue(tls_idx); if (t == NULL) - return NULL; - return t->values[keynum]; -} - -int k5_setspecific (k5_key_t keynum, void *value) -{ - struct tsd_block *t; - - err = CALL_INIT_FUNCTION(krb5int_thread_support_init); - if (err) - return NULL; - - assert(keynum >= 0 && keynum < K5_KEY_MAX); - - t = TlsGetValue(tls_idx); - if (t == NULL) { - int i; - t = malloc(sizeof(*t)); - if (t == NULL) - return errno; - for (i = 0; i < K5_KEY_MAX; i++) + return; + for (i = 0; i < K5_KEY_MAX; i++) { + if (destructors_set[i] && destructors[i] && t->values[i]) { + void *v = t->values[i]; t->values[i] = 0; - /* add to global linked list */ - t->next = 0; - err = TlsSetValue(key, t); - if (err) { - free(t); - return err; + (*destructors[i])(v); } } - t->values[keynum] = value; - return 0; -} - -int k5_key_delete (k5_key_t keynum) -{ - assert(keynum >= 0 && keynum < K5_KEY_MAX); - /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK. */ - EnterCriticalSection(&key_lock); - abort(); - LeaveCriticalSection(&key_lock); - return 0; -} - -void krb5int_thread_detach_hook (void) -{ - /* XXX Memory leak here! - Need to destroy all TLS objects we know about for this thread. */ } - -#else - -/* POSIX */ +#else /* POSIX threads */ /* Must support register/delete/register sequence, e.g., if krb5 is loaded so this support code stays in the process, and gssapi is @@ -173,33 +104,14 @@ struct tsd_block { # pragma weak pthread_key_create # pragma weak pthread_key_delete static struct tsd_block tsd_if_single; +# define GET_NO_PTHREAD_TSD() (&tsd_if_single) +#else +# define GET_NO_PTHREAD_TSD() (abort(),0) #endif static pthread_key_t key; static void thread_termination(void *); -int krb5int_thread_support_init(void) -{ - int err; - err = k5_mutex_finish_init(&key_lock); - if (err) - return err; - if (K5_PTHREADS_LOADED) - return pthread_key_create(&key, thread_termination); - else - return 0; -} - -void krb5int_thread_support_fini(void) -{ - if (! INITIALIZER_RAN(krb5int_thread_support_init)) - return; - if (K5_PTHREADS_LOADED) - pthread_key_delete(key); - /* ... delete stuff ... */ - k5_mutex_destroy(&key_lock); -} - static void thread_termination (void *tptr) { int i, pass, none_found; @@ -229,25 +141,7 @@ static void thread_termination (void *tptr) /* remove thread from global linked list */ } -int k5_key_register (k5_key_t keynum, void (*destructor)(void *)) -{ - int err; - - err = CALL_INIT_FUNCTION(krb5int_thread_support_init); - if (err) - return err; - err = k5_mutex_lock(&key_lock); - if (err) - return err; - assert(keynum >= 0 && keynum < K5_KEY_MAX); - assert(destructors_set[keynum] == 0); - destructors_set[keynum] = 1; - destructors[keynum] = destructor; - err = k5_mutex_unlock(&key_lock); - if (err) - return err; - return 0; -} +#endif /* no threads vs Win32 vs POSIX */ void *k5_getspecific (k5_key_t keynum) { @@ -259,20 +153,28 @@ void *k5_getspecific (k5_key_t keynum) return NULL; assert(keynum >= 0 && keynum < K5_KEY_MAX); - assert(destructors_set[keynum] != 0); + assert(destructors_set[keynum] == 1); + +#ifndef ENABLE_THREADS + + t = &tsd_no_threads; + +#elif defined(_WIN32) + + t = TlsGetValue(tls_idx); + +#else /* POSIX */ if (K5_PTHREADS_LOADED) t = pthread_getspecific(key); - else { -#ifdef HAVE_PRAGMA_WEAK_REF - t = &tsd_if_single; -#else - abort(); -#endif + else + t = GET_NO_PTHREAD_TSD(); } + +#endif + if (t == NULL) return NULL; - return t->values[keynum]; } @@ -286,7 +188,32 @@ int k5_setspecific (k5_key_t keynum, void *value) return err; assert(keynum >= 0 && keynum < K5_KEY_MAX); - assert(destructors_set[keynum] != 0); + assert(destructors_set[keynum] == 1); + +#ifndef ENABLE_THREADS + + t = &tsd_no_threads; + +#elif defined(_WIN32) + + t = TlsGetValue(tls_idx); + if (t == NULL) { + int i; + t = malloc(sizeof(*t)); + if (t == NULL) + return errno; + for (i = 0; i < K5_KEY_MAX; i++) + t->values[i] = 0; + /* add to global linked list */ + t->next = 0; + err = TlsSetValue(key, t); + if (err) { + free(t); + return err; + } + } + +#else /* POSIX */ if (K5_PTHREADS_LOADED) { t = pthread_getspecific(key); @@ -306,76 +233,138 @@ int k5_setspecific (k5_key_t keynum, void *value) } } } else { -#ifdef HAVE_PRAGMA_WEAK_REF - t = &tsd_if_single; -#else - abort(); -#endif + t = GET_NO_PTHREAD_TSD(); } +#endif + t->values[keynum] = value; return 0; } -int k5_key_delete (k5_key_t keynum) +int k5_key_register (k5_key_t keynum, void (*destructor)(void *)) { - abort(); -} + int err; -#endif /* Win32 vs POSIX */ + err = CALL_INIT_FUNCTION(krb5int_thread_support_init); + if (err) + return err; - -#else -/* no thread support */ + assert(keynum >= 0 && keynum < K5_KEY_MAX); -static void (*destructors[K5_KEY_MAX])(void *); -static void *tsd_values[K5_KEY_MAX]; -static unsigned char destructors_set[K5_KEY_MAX]; +#ifndef ENABLE_THREADS -int krb5int_thread_support_init(void) -{ - return 0; -} + assert(destructors_set[keynum] == 0); + destructors[keynum] = destructor; + destructors_set[keynum] = 1; + err = 0; -void krb5int_thread_support_fini(void) -{ - /* ... */ -} +#elif defined(_WIN32) -int k5_key_register (k5_key_t keynum, void (*d)(void *)) -{ - assert(keynum >= 0 && keynum < K5_KEY_MAX); + /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK. */ + EnterCriticalSection(&key_lock); assert(destructors_set[keynum] == 0); - destructors[keynum] = d; destructors_set[keynum] = 1; - return 0; -} + destructors[keynum] = destructor; + LeaveCriticalSection(&key_lock); + err = 0; -void *k5_getspecific (k5_key_t keynum) -{ - assert(keynum >= 0 && keynum < K5_KEY_MAX); - assert(destructors_set[keynum] == 1); - return tsd_values[keynum]; -} +#else /* POSIX */ -int k5_setspecific (k5_key_t keynum, void *value) -{ - assert(keynum >= 0 && keynum < K5_KEY_MAX); - assert(destructors_set[keynum] == 1); - tsd_values[keynum] = value; + err = k5_mutex_lock(&key_lock); + if (err == 0) { + assert(destructors_set[keynum] == 0); + destructors_set[keynum] = 1; + destructors[keynum] = destructor; + err = k5_mutex_unlock(&key_lock); + } + +#endif return 0; } int k5_key_delete (k5_key_t keynum) { assert(keynum >= 0 && keynum < K5_KEY_MAX); + +#ifndef ENABLE_THREADS + assert(destructors_set[keynum] == 1); - if (destructors[keynum] && tsd_values[keynum]) - (*destructors[keynum])(tsd_values[keynum]); + if (destructors[keynum] && tsd_no_threads.values[keynum]) + (*destructors[keynum])(tsd_no_threads.values[keynum]); destructors[keynum] = 0; - tsd_values[keynum] = 0; + tsd_no_threads.values[keynum] = 0; destructors_set[keynum] = 0; + +#elif defined(_WIN32) + + /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK. */ + EnterCriticalSection(&key_lock); + /* XXX Memory leak here! + Need to destroy the associated data for all threads. + But watch for race conditions in case threads are going away too. */ + LeaveCriticalSection(&key_lock); + +#else /* POSIX */ + + /* Not written yet. */ + abort(); + +#endif + return 0; } +int krb5int_thread_support_init (void) +{ +#ifndef ENABLE_THREADS + + return 0; + +#elif defined(_WIN32) + + tls_idx = TlsAlloc(); + /* XXX This can raise an exception if memory is low! */ + InitializeCriticalSection(&key_lock); + return 0; + +#else /* POSIX */ + + int err; + err = k5_mutex_finish_init(&key_lock); + if (err) + return err; + if (K5_PTHREADS_LOADED) + return pthread_key_create(&key, thread_termination); + else + return 0; + #endif +} + +void krb5int_thread_support_fini (void) +{ +#ifndef ENABLE_THREADS + + /* Do nothing. */ + +#elif defined(_WIN32) + + if (! INITIALIZER_RAN (krb5int_thread_support_init)) + return; + /* ... free stuff ... */ + TlsFree(tls_idx); + DeleteCriticalSection(&key_lock); + +#else /* POSIX */ + + if (! INITIALIZER_RAN(krb5int_thread_support_init)) + return; + if (K5_PTHREADS_LOADED) + pthread_key_delete(key); + /* ... delete stuff ... */ + k5_mutex_destroy(&key_lock); + +#endif +} + -- 2.26.2