* threads.c: Reorganize code: One definition of each function, with
authorKen Raeburn <raeburn@mit.edu>
Thu, 24 Jun 2004 22:30:16 +0000 (22:30 +0000)
committerKen Raeburn <raeburn@mit.edu>
Thu, 24 Jun 2004 22:30:16 +0000 (22:30 +0000)
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
src/util/support/threads.c

index b8ef14bcb1d1bf7301508222167eb2b8ae195cd0..534868d3a1450cb2c25313a61af20a5d1ebab3b1 100644 (file)
@@ -1,3 +1,10 @@
+2004-06-24  Ken Raeburn  <raeburn@mit.edu>
+
+       * 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  <raeburn@mit.edu>
 
        * threads.c (key_lock): Change to a k5_mutex_t.
index 60c0bad8cddf75d607ef32f615bc397420171a80..e3d235999c30437b6d1a9babb7638574afc1d75c 100644 (file)
 MAKE_INIT_FUNCTION(krb5int_thread_support_init);
 MAKE_FINI_FUNCTION(krb5int_thread_support_fini);
 
-\f
-#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.  */
 }
 
-\f
-#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;
 
-\f
-#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
+}
+