* New directory.
authorKen Raeburn <raeburn@mit.edu>
Tue, 4 May 2004 22:40:07 +0000 (22:40 +0000)
committerKen Raeburn <raeburn@mit.edu>
Tue, 4 May 2004 22:40:07 +0000 (22:40 +0000)
* 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 [new file with mode: 0644]
src/util/support/Makefile.in [new file with mode: 0644]
src/util/support/fake-addrinfo.c [new file with mode: 0644]
src/util/support/threads.c [new file with mode: 0644]

diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog
new file mode 100644 (file)
index 0000000..b36d845
--- /dev/null
@@ -0,0 +1,7 @@
+2004-05-04  Ken Raeburn  <raeburn@mit.edu>
+
+       * 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 (file)
index 0000000..7170eaa
--- /dev/null
@@ -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 (file)
index 0000000..c8be554
--- /dev/null
@@ -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 (file)
index 0000000..2aede85
--- /dev/null
@@ -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 <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#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