From 3808c842f799ee522d408d9eb34c1dbd45a07fa2 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Tue, 4 May 2004 22:40:07 +0000 Subject: [PATCH] * New directory. * Makefile.in: New file. * threads.c: New file. Thread-specific data support. * fake-addrinfo.c: New file. Placeholder. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16299 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/support/ChangeLog | 7 + src/util/support/Makefile.in | 63 ++++++++ src/util/support/fake-addrinfo.c | 8 ++ src/util/support/threads.c | 237 +++++++++++++++++++++++++++++++ 4 files changed, 315 insertions(+) create mode 100644 src/util/support/ChangeLog create mode 100644 src/util/support/Makefile.in create mode 100644 src/util/support/fake-addrinfo.c create mode 100644 src/util/support/threads.c diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog new file mode 100644 index 000000000..b36d8454c --- /dev/null +++ b/src/util/support/ChangeLog @@ -0,0 +1,7 @@ +2004-05-04 Ken Raeburn + + * New directory. + * Makefile.in: New file. + * threads.c: New file. Thread-specific data support. + * fake-addrinfo.c: New file. Placeholder. + diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in new file mode 100644 index 000000000..7170eaae2 --- /dev/null +++ b/src/util/support/Makefile.in @@ -0,0 +1,63 @@ +thisconfigdir=../.. +myfulldir=util/support +mydir=util/support +BUILDTOP=$(REL)..$(S).. +RELDIR=../util/support + +SED = sed + +KRB5_RUN_ENV= @KRB5_RUN_ENV@ +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +LIB=$(SUPPORT_LIBNAME) +LIBMAJOR=0 +LIBMINOR=0 + +LIBINITFUNC=krb5int_thread_support_init +#LIBFINIFUNC= + +STLIBOBJS= \ + threads.o \ + fake-addrinfo.o + +STOBJLISTS=OBJS.ST + +INSTALLFILE = cp + +LOCALINCLUDES=-I. -I$(srcdir) + +SRCS=\ + $(srcdir)/threads.c \ + $(srcdir)/fake-addrinfo.c +SHLIB_EXPDEPS = +SHLIB_EXPLIBS= +SHLIB_DIRS= +SHLIB_RDIRS= + +DEPLIBS= + +# +all-unix:: all-liblinks + +install-unix:: install-libs + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +$(BUILDTOP)/include/krb5/autoconf.h: $(SRCTOP)/include/krb5/autoconf.h.in + (cd $(BUILDTOP)/include; $(MAKE) krb5/autoconf.h) + + +# @lib_frag@ +# @libobj_frag@ + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + + + + +# foo diff --git a/src/util/support/fake-addrinfo.c b/src/util/support/fake-addrinfo.c new file mode 100644 index 000000000..c8be554f9 --- /dev/null +++ b/src/util/support/fake-addrinfo.c @@ -0,0 +1,8 @@ +/* Placeholder. + + Move most of the code from fake-addrinfo.h into here, someday. + Enhance the caching. */ + +#include "fake-addrinfo.h" + +static int krb5int__fake_addrinfo_c__dummy = 0; diff --git a/src/util/support/threads.c b/src/util/support/threads.c new file mode 100644 index 000000000..2aede85e5 --- /dev/null +++ b/src/util/support/threads.c @@ -0,0 +1,237 @@ +/* + * util/support/threads.c + * + * Copyright 2004 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Preliminary thread support. + */ + +#include +#include +#include +#include "k5-thread.h" +#include "k5-platform.h" + +MAKE_INIT_FUNCTION(krb5int_thread_support_init); +MAKE_FINI_FUNCTION(krb5int_thread_support_fini); + +#ifdef ENABLE_THREADS + +#ifdef _WIN32 + +#error "need WIN32 thread support code written" + +#else + +/* POSIX */ + +/* Must support register/delete/register sequence, e.g., if krb5 is + loaded so this support code stays in the process, and gssapi is + loaded, unloaded, and loaded again. */ + +static pthread_mutex_t key_lock = PTHREAD_MUTEX_INITIALIZER; +static void (*destructors[K5_KEY_MAX])(void *); +static unsigned char destructors_set[K5_KEY_MAX]; + +/* This is not safe yet! + + Thread termination concurrent with key deletion can cause two + threads to interfere. It's a bit tricky, since one of the threads + will want to remove this structure from the list being walked by + the other. + + Other cases, like looking up data while the library owning the key + is in the process of being unloaded, we don't worry about. */ + +struct tsd_block { + struct tsd_block *next; + void *values[K5_KEY_MAX]; +}; + +static pthread_key_t key; +static void thread_termination(void *); + +int krb5int_thread_support_init(void) +{ + return pthread_key_create(&key, thread_termination); +} + +void krb5int_thread_support_fini(void) +{ + if (INITIALIZER_RAN(krb5int_thread_support_init)) + pthread_key_delete(key); +} + +static void thread_termination (void *tptr) +{ + int i, pass, none_found; + struct tsd_block *t = tptr; + + /* Make multiple passes in case, for example, a libkrb5 cleanup + function wants to print out an error message, which causes + com_err to allocate a thread-specific buffer, after we just + freed up the old one. + + Shouldn't actually happen, if we're careful, but check just in + case. */ + + pass = 0; + none_found = 0; + while (pass < 4 && !none_found) { + none_found = 1; + 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; + (*destructors[i])(v); + none_found = 0; + } + } + } + /* remove thread from global linked list */ +} + +int k5_key_register (k5_key_t keynum, void (*destructor)(void *)) +{ + int err; + + err = pthread_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 = pthread_mutex_unlock(&key_lock); + if (err) + return err; + return 0; +} + +void *k5_getspecific (k5_key_t keynum) +{ + struct tsd_block *t; + int err; + + err = CALL_INIT_FUNCTION(krb5int_thread_support_init); + if (err) + return NULL; + + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] != 0); + + t = pthread_getspecific(key); + if (t == NULL) + return NULL; + + return t->values[keynum]; +} + +int k5_setspecific (k5_key_t keynum, void *value) +{ + struct tsd_block *t; + int err; + + err = CALL_INIT_FUNCTION(krb5int_thread_support_init); + if (err) + return err; + + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] != 0); + + t = pthread_getspecific(key); + 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 = pthread_setspecific(key, t); + if (err) { + free(t); + return err; + } + } + + t->values[keynum] = value; + return 0; +} + +int k5_key_delete (k5_key_t keynum) +{ + abort(); +} + +#endif /* Win32 vs POSIX */ + +#else + +static void (*destructors[K5_KEY_MAX])(void); +static void *tsd_values[K5_KEY_MAX]; +static unsigned char destructors_set[K5_KEY_MAX]; + +int krb5int_thread_support_init(void) +{ + return 0; +} + +int k5_key_register (k5_key_t keynum, void (*d)(void)) +{ + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] == 0); + destructors[keynum] = d; + destructors_set[keynum] = 1; +} + +void *k5_getspecific (k5_key_t keynum) +{ + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] == 1); + return tsd_values[keynum]; +} + +int k5_setspecific (k5_key_t keynum, const void *value) +{ + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] == 1); + tsd_values[keynum] = value; + return 0; +} + +int k5_key_delete (k5_key_t keynum) +{ + assert(keynum >= 0 && keynum < K5_KEY_MAX); + assert(destructors_set[keynum] == 1); + if (destructors[keynum] && tsd_values[keynum]) + (*destructors[keynum])(tsd_values[keynum]); + destructors[keynum] = 0; + tsd_values[keynum] = 0; + destructors_set[keynum] = 0; + return 0; +} + +#endif -- 2.26.2