Blame src/include/k5-thread.h

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* include/k5-thread.h - Preliminary portable thread support */
Packit fd8b60
/*
Packit fd8b60
 * Copyright 2004,2005,2006,2007,2008 by the Massachusetts Institute of Technology.
Packit fd8b60
 * All Rights Reserved.
Packit fd8b60
 *
Packit fd8b60
 * Export of this software from the United States of America may
Packit fd8b60
 *   require a specific license from the United States Government.
Packit fd8b60
 *   It is the responsibility of any person or organization contemplating
Packit fd8b60
 *   export to obtain such a license before exporting.
Packit fd8b60
 *
Packit fd8b60
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
Packit fd8b60
 * distribute this software and its documentation for any purpose and
Packit fd8b60
 * without fee is hereby granted, provided that the above copyright
Packit fd8b60
 * notice appear in all copies and that both that copyright notice and
Packit fd8b60
 * this permission notice appear in supporting documentation, and that
Packit fd8b60
 * the name of M.I.T. not be used in advertising or publicity pertaining
Packit fd8b60
 * to distribution of the software without specific, written prior
Packit fd8b60
 * permission.  Furthermore if you modify this software you must label
Packit fd8b60
 * your software as modified software and not distribute it in such a
Packit fd8b60
 * fashion that it might be confused with the original M.I.T. software.
Packit fd8b60
 * M.I.T. makes no representations about the suitability of
Packit fd8b60
 * this software for any purpose.  It is provided "as is" without express
Packit fd8b60
 * or implied warranty.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#ifndef K5_THREAD_H
Packit fd8b60
#define K5_THREAD_H
Packit fd8b60
Packit fd8b60
#include "autoconf.h"
Packit fd8b60
#ifndef KRB5_CALLCONV
Packit fd8b60
# define KRB5_CALLCONV
Packit fd8b60
#endif
Packit fd8b60
#ifndef KRB5_CALLCONV_C
Packit fd8b60
# define KRB5_CALLCONV_C
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
/* Interface (tentative):
Packit fd8b60
Packit fd8b60
     Mutex support:
Packit fd8b60
Packit fd8b60
     // Between these two, we should be able to do pure compile-time
Packit fd8b60
     // and pure run-time initialization.
Packit fd8b60
     //   POSIX:   partial initializer is PTHREAD_MUTEX_INITIALIZER,
Packit fd8b60
     //            finish does nothing
Packit fd8b60
     //   Windows: partial initializer is an invalid handle,
Packit fd8b60
     //            finish does the real initialization work
Packit fd8b60
     k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
Packit fd8b60
     int k5_mutex_finish_init(k5_mutex_t *);
Packit fd8b60
     // for dynamic allocation
Packit fd8b60
     int k5_mutex_init(k5_mutex_t *);
Packit fd8b60
     // Must work for both kinds of alloc, even if it means adding flags.
Packit fd8b60
     int k5_mutex_destroy(k5_mutex_t *);
Packit fd8b60
Packit fd8b60
     // As before.
Packit fd8b60
     int k5_mutex_lock(k5_mutex_t *);
Packit fd8b60
     int k5_mutex_unlock(k5_mutex_t *);
Packit fd8b60
Packit fd8b60
     In each library, one new function to finish the static mutex init,
Packit fd8b60
     and any other library-wide initialization that might be desired.
Packit fd8b60
     On POSIX, this function would be called via the second support
Packit fd8b60
     function (see below).  On Windows, it would be called at library
Packit fd8b60
     load time.  These functions, or functions they calls, should be the
Packit fd8b60
     only places that k5_mutex_finish_init gets called.
Packit fd8b60
Packit fd8b60
     A second function or macro called at various possible "first" entry
Packit fd8b60
     points which either calls pthread_once on the first function
Packit fd8b60
     (POSIX), or checks some flag set by the first function (Windows),
Packit fd8b60
     and possibly returns an error.  (In the non-threaded case, a simple
Packit fd8b60
     flag can be used to avoid multiple invocations, and the mutexes
Packit fd8b60
     don't need run-time initialization anyways.)
Packit fd8b60
Packit fd8b60
     A third function for library termination calls mutex_destroy on
Packit fd8b60
     each mutex for the library.  This function would be called
Packit fd8b60
     automatically at library unload time.  If it turns out to be needed
Packit fd8b60
     at exit time for libraries that don't get unloaded, perhaps we
Packit fd8b60
     should also use atexit().  Any static mutexes should be cleaned up
Packit fd8b60
     with k5_mutex_destroy here.
Packit fd8b60
Packit fd8b60
     How does that second support function invoke the first support
Packit fd8b60
     function only once?  Through something modelled on pthread_once
Packit fd8b60
     that I haven't written up yet.  Probably:
Packit fd8b60
Packit fd8b60
     k5_once_t foo_once = K5_ONCE_INIT;
Packit fd8b60
     k5_once(k5_once_t *, void (*)(void));
Packit fd8b60
Packit fd8b60
     For POSIX: Map onto pthread_once facility.
Packit fd8b60
     For non-threaded case: A simple flag.
Packit fd8b60
     For Windows: Not needed; library init code takes care of it.
Packit fd8b60
Packit fd8b60
     XXX: A general k5_once mechanism isn't possible for Windows,
Packit fd8b60
     without faking it through named mutexes or mutexes initialized at
Packit fd8b60
     startup.  I was only using it in one place outside these headers,
Packit fd8b60
     so I'm dropping the general scheme.  Eventually the existing uses
Packit fd8b60
     in k5-thread.h and k5-platform.h will be converted to pthread_once
Packit fd8b60
     or static variables.
Packit fd8b60
Packit fd8b60
Packit fd8b60
     Thread-specific data:
Packit fd8b60
Packit fd8b60
     // TSD keys are limited in number in gssapi/krb5/com_err; enumerate
Packit fd8b60
     // them all.  This allows support code init to allocate the
Packit fd8b60
     // necessary storage for pointers all at once, and avoids any
Packit fd8b60
     // possible error in key creation.
Packit fd8b60
     enum { ... } k5_key_t;
Packit fd8b60
     // Register destructor function.  Called in library init code.
Packit fd8b60
     int k5_key_register(k5_key_t, void (*destructor)(void *));
Packit fd8b60
     // Returns NULL or data.
Packit fd8b60
     void *k5_getspecific(k5_key_t);
Packit fd8b60
     // Returns error if key out of bounds, or the pointer table can't
Packit fd8b60
     // be allocated.  A call to k5_key_register must have happened first.
Packit fd8b60
     // This may trigger the calling of pthread_setspecific on POSIX.
Packit fd8b60
     int k5_setspecific(k5_key_t, void *);
Packit fd8b60
     // Called in library termination code.
Packit fd8b60
     // Trashes data in all threads, calling the registered destructor
Packit fd8b60
     // (but calling it from the current thread).
Packit fd8b60
     int k5_key_delete(k5_key_t);
Packit fd8b60
Packit fd8b60
     For the non-threaded version, the support code will have a static
Packit fd8b60
     array indexed by k5_key_t values, and get/setspecific simply access
Packit fd8b60
     the array elements.
Packit fd8b60
Packit fd8b60
     The TSD destructor table is global state, protected by a mutex if
Packit fd8b60
     threads are enabled.
Packit fd8b60
Packit fd8b60
Packit fd8b60
     Any actual external symbols will use the krb5int_ prefix.  The k5_
Packit fd8b60
     names will be simple macros or inline functions to rename the
Packit fd8b60
     external symbols, or slightly more complex ones to expand the
Packit fd8b60
     implementation inline (e.g., map to POSIX versions and/or debug
Packit fd8b60
     code using __FILE__ and the like).
Packit fd8b60
Packit fd8b60
Packit fd8b60
     More to be added, perhaps.  */
Packit fd8b60
Packit fd8b60
#include <assert.h>
Packit fd8b60
#ifndef NDEBUG
Packit fd8b60
#include <stdio.h>
Packit fd8b60
#include <string.h>
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
/* The mutex structure we use, k5_mutex_t, is defined to some
Packit fd8b60
   OS-specific bits.  The use of multiple layers of typedefs are an
Packit fd8b60
   artifact resulting from debugging code we once used, implemented as
Packit fd8b60
   wrappers around the OS mutex scheme.
Packit fd8b60
Packit fd8b60
   The OS specific bits, in k5_os_mutex, break down into three primary
Packit fd8b60
   implementations, POSIX threads, Windows threads, and no thread
Packit fd8b60
   support.  However, the POSIX thread version is further subdivided:
Packit fd8b60
   In one case, we can determine at run time whether the thread
Packit fd8b60
   library is linked into the application, and use it only if it is
Packit fd8b60
   present; in the other case, we cannot, and the thread library must
Packit fd8b60
   be linked in always, but can be used unconditionally.  In the
Packit fd8b60
   former case, the k5_os_mutex structure needs to hold both the POSIX
Packit fd8b60
   and the non-threaded versions.
Packit fd8b60
Packit fd8b60
   The various k5_os_mutex_* operations are the OS-specific versions,
Packit fd8b60
   applied to the OS-specific data, and k5_mutex_* uses k5_os_mutex_*
Packit fd8b60
   to do the OS-specific parts of the work.  */
Packit fd8b60
Packit fd8b60
/* Define the OS mutex bit.  */
Packit fd8b60
Packit fd8b60
typedef char k5_os_nothread_mutex;
Packit fd8b60
# define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER       0
Packit fd8b60
/* Empty inline functions avoid the "statement with no effect"
Packit fd8b60
   warnings, and do better type-checking than functions that don't use
Packit fd8b60
   their arguments.  */
Packit fd8b60
static inline int k5_os_nothread_mutex_finish_init(k5_os_nothread_mutex *m) {
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
static inline int k5_os_nothread_mutex_init(k5_os_nothread_mutex *m) {
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
static inline int k5_os_nothread_mutex_destroy(k5_os_nothread_mutex *m) {
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
static inline int k5_os_nothread_mutex_lock(k5_os_nothread_mutex *m) {
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
static inline int k5_os_nothread_mutex_unlock(k5_os_nothread_mutex *m) {
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* Values:
Packit fd8b60
   2 - function has not been run
Packit fd8b60
   3 - function has been run
Packit fd8b60
   4 - function is being run -- deadlock detected */
Packit fd8b60
typedef unsigned char k5_os_nothread_once_t;
Packit fd8b60
# define K5_OS_NOTHREAD_ONCE_INIT       2
Packit fd8b60
# define k5_os_nothread_once(O,F)                               \
Packit fd8b60
    (*(O) == 3 ? 0                                              \
Packit fd8b60
     : *(O) == 2 ? (*(O) = 4, (F)(), *(O) = 3, 0)               \
Packit fd8b60
     : (assert(*(O) != 4), assert(*(O) == 2 || *(O) == 3), 0))
Packit fd8b60
Packit fd8b60
Packit fd8b60
Packit fd8b60
#ifndef ENABLE_THREADS
Packit fd8b60
Packit fd8b60
typedef k5_os_nothread_mutex k5_os_mutex;
Packit fd8b60
# define K5_OS_MUTEX_PARTIAL_INITIALIZER        \
Packit fd8b60
    K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER
Packit fd8b60
# define k5_os_mutex_finish_init        k5_os_nothread_mutex_finish_init
Packit fd8b60
# define k5_os_mutex_init               k5_os_nothread_mutex_init
Packit fd8b60
# define k5_os_mutex_destroy            k5_os_nothread_mutex_destroy
Packit fd8b60
# define k5_os_mutex_lock               k5_os_nothread_mutex_lock
Packit fd8b60
# define k5_os_mutex_unlock             k5_os_nothread_mutex_unlock
Packit fd8b60
Packit fd8b60
# define k5_once_t                      k5_os_nothread_once_t
Packit fd8b60
# define K5_ONCE_INIT                   K5_OS_NOTHREAD_ONCE_INIT
Packit fd8b60
# define k5_once                        k5_os_nothread_once
Packit fd8b60
Packit fd8b60
#elif HAVE_PTHREAD
Packit fd8b60
Packit fd8b60
# include <pthread.h>
Packit fd8b60
Packit fd8b60
/* Weak reference support, etc.
Packit fd8b60
Packit fd8b60
   Linux: Stub mutex routines exist, but pthread_once does not.
Packit fd8b60
Packit fd8b60
   Solaris <10: In libc there's a pthread_once that doesn't seem to do
Packit fd8b60
   anything.  Bleah.  But pthread_mutexattr_setrobust_np is defined
Packit fd8b60
   only in libpthread.  However, some version of GNU libc (Red Hat's
Packit fd8b60
   Fedora Core 5, reportedly) seems to have that function, but no
Packit fd8b60
   declaration, so we'd have to declare it in order to test for its
Packit fd8b60
   address.  We now have tests to see if pthread_once actually works,
Packit fd8b60
   so stick with that for now.
Packit fd8b60
Packit fd8b60
   Solaris 10: The real thread support now lives in libc, and
Packit fd8b60
   libpthread is just a filter object.  So we might as well use the
Packit fd8b60
   real functions unconditionally.  Since we haven't got a test for
Packit fd8b60
   this property yet, we use NO_WEAK_PTHREADS defined in aclocal.m4
Packit fd8b60
   depending on the OS type.
Packit fd8b60
Packit fd8b60
   IRIX 6.5 stub pthread support in libc is really annoying.  The
Packit fd8b60
   pthread_mutex_lock function returns ENOSYS for a program not linked
Packit fd8b60
   against -lpthread.  No link-time failure, no weak symbols, etc.
Packit fd8b60
   The C library doesn't provide pthread_once; we can use weak
Packit fd8b60
   reference support for that.
Packit fd8b60
Packit fd8b60
   If weak references are not available, then for now, we assume that
Packit fd8b60
   the pthread support routines will always be available -- either the
Packit fd8b60
   real thing, or functional stubs that merely prohibit creating
Packit fd8b60
   threads.
Packit fd8b60
Packit fd8b60
   If we find a platform with non-functional stubs and no weak
Packit fd8b60
   references, we may have to resort to some hack like dlsym on the
Packit fd8b60
   symbol tables of the current process.  */
Packit fd8b60
Packit fd8b60
#if defined(HAVE_PRAGMA_WEAK_REF) && !defined(NO_WEAK_PTHREADS)
Packit fd8b60
# define USE_CONDITIONAL_PTHREADS
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
#ifdef USE_CONDITIONAL_PTHREADS
Packit fd8b60
Packit fd8b60
/* Can't rely on useful stubs -- see above regarding Solaris.  */
Packit fd8b60
typedef struct {
Packit fd8b60
    pthread_once_t o;
Packit fd8b60
    k5_os_nothread_once_t n;
Packit fd8b60
} k5_once_t;
Packit fd8b60
# define K5_ONCE_INIT   { PTHREAD_ONCE_INIT, K5_OS_NOTHREAD_ONCE_INIT }
Packit fd8b60
Packit fd8b60
int k5_once(k5_once_t *once, void (*fn)(void));
Packit fd8b60
#else
Packit fd8b60
Packit fd8b60
/* no pragma weak support */
Packit fd8b60
Packit fd8b60
typedef pthread_once_t k5_once_t;
Packit fd8b60
# define K5_ONCE_INIT   PTHREAD_ONCE_INIT
Packit fd8b60
# define k5_once        pthread_once
Packit fd8b60
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
#if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__))
Packit fd8b60
# ifndef HAVE_PRAGMA_WEAK_REF
Packit fd8b60
#  if defined(__GNUC__) && __GNUC__ < 3
Packit fd8b60
#   error "Please update to a newer gcc with weak symbol support, or switch to native cc, reconfigure and recompile."
Packit fd8b60
#  else
Packit fd8b60
#   error "Weak reference support is required"
Packit fd8b60
#  endif
Packit fd8b60
# endif
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
typedef pthread_mutex_t k5_os_mutex;
Packit fd8b60
# define K5_OS_MUTEX_PARTIAL_INITIALIZER        \
Packit fd8b60
    PTHREAD_MUTEX_INITIALIZER
Packit fd8b60
Packit fd8b60
#ifdef USE_CONDITIONAL_PTHREADS
Packit fd8b60
Packit fd8b60
# define k5_os_mutex_finish_init(M)             (0)
Packit fd8b60
int k5_os_mutex_init(k5_os_mutex *m);
Packit fd8b60
int k5_os_mutex_destroy(k5_os_mutex *m);
Packit fd8b60
int k5_os_mutex_lock(k5_os_mutex *m);
Packit fd8b60
int k5_os_mutex_unlock(k5_os_mutex *m);
Packit fd8b60
Packit fd8b60
#else
Packit fd8b60
Packit fd8b60
static inline int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; }
Packit fd8b60
# define k5_os_mutex_init(M)            pthread_mutex_init((M), 0)
Packit fd8b60
# define k5_os_mutex_destroy(M)         pthread_mutex_destroy((M))
Packit fd8b60
# define k5_os_mutex_lock(M)            pthread_mutex_lock(M)
Packit fd8b60
# define k5_os_mutex_unlock(M)          pthread_mutex_unlock(M)
Packit fd8b60
Packit fd8b60
#endif /* is pthreads always available? */
Packit fd8b60
Packit fd8b60
#elif defined _WIN32
Packit fd8b60
Packit fd8b60
# define k5_once_t k5_os_nothread_once_t
Packit fd8b60
Packit fd8b60
typedef struct {
Packit fd8b60
    HANDLE h;
Packit fd8b60
    int is_locked;
Packit fd8b60
} k5_os_mutex;
Packit fd8b60
Packit fd8b60
# define K5_OS_MUTEX_PARTIAL_INITIALIZER { INVALID_HANDLE_VALUE, 0 }
Packit fd8b60
Packit fd8b60
# define k5_os_mutex_finish_init(M)                                     \
Packit fd8b60
    (assert((M)->h == INVALID_HANDLE_VALUE),                            \
Packit fd8b60
     ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
Packit fd8b60
# define k5_os_mutex_init(M)                                            \
Packit fd8b60
    ((M)->is_locked = 0,                                                \
Packit fd8b60
     ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
Packit fd8b60
# define k5_os_mutex_destroy(M)                                 \
Packit fd8b60
    (CloseHandle((M)->h) ? ((M)->h = 0, 0) : GetLastError())
Packit fd8b60
# define k5_os_mutex_lock k5_win_mutex_lock
Packit fd8b60
Packit fd8b60
static inline int k5_win_mutex_lock(k5_os_mutex *m)
Packit fd8b60
{
Packit fd8b60
    DWORD res;
Packit fd8b60
    res = WaitForSingleObject(m->h, INFINITE);
Packit fd8b60
    if (res == WAIT_FAILED)
Packit fd8b60
        return GetLastError();
Packit fd8b60
    /* Eventually these should be turned into some reasonable error
Packit fd8b60
       code.  */
Packit fd8b60
    assert(res != WAIT_TIMEOUT);
Packit fd8b60
    assert(res != WAIT_ABANDONED);
Packit fd8b60
    assert(res == WAIT_OBJECT_0);
Packit fd8b60
    /* Avoid locking twice.  */
Packit fd8b60
    assert(m->is_locked == 0);
Packit fd8b60
    m->is_locked = 1;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
# define k5_os_mutex_unlock(M)                  \
Packit fd8b60
    (assert((M)->is_locked == 1),               \
Packit fd8b60
     (M)->is_locked = 0,                        \
Packit fd8b60
     ReleaseMutex((M)->h) ? 0 : GetLastError())
Packit fd8b60
Packit fd8b60
#else
Packit fd8b60
Packit fd8b60
# error "Thread support enabled, but thread system unknown"
Packit fd8b60
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
typedef k5_os_mutex k5_mutex_t;
Packit fd8b60
#define K5_MUTEX_PARTIAL_INITIALIZER    K5_OS_MUTEX_PARTIAL_INITIALIZER
Packit fd8b60
static inline int k5_mutex_init(k5_mutex_t *m)
Packit fd8b60
{
Packit fd8b60
    return k5_os_mutex_init(m);
Packit fd8b60
}
Packit fd8b60
static inline int k5_mutex_finish_init(k5_mutex_t *m)
Packit fd8b60
{
Packit fd8b60
    return k5_os_mutex_finish_init(m);
Packit fd8b60
}
Packit fd8b60
#define k5_mutex_destroy(M)                     \
Packit fd8b60
    (k5_os_mutex_destroy(M))
Packit fd8b60
Packit fd8b60
static inline void k5_mutex_lock(k5_mutex_t *m)
Packit fd8b60
{
Packit fd8b60
    int r = k5_os_mutex_lock(m);
Packit fd8b60
#ifndef NDEBUG
Packit fd8b60
    if (r != 0) {
Packit fd8b60
        fprintf(stderr, "k5_mutex_lock: Received error %d (%s)\n",
Packit fd8b60
                r, strerror(r));
Packit fd8b60
    }
Packit fd8b60
#endif
Packit fd8b60
    assert(r == 0);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static inline void k5_mutex_unlock(k5_mutex_t *m)
Packit fd8b60
{
Packit fd8b60
    int r = k5_os_mutex_unlock(m);
Packit fd8b60
#ifndef NDEBUG
Packit fd8b60
    if (r != 0) {
Packit fd8b60
        fprintf(stderr, "k5_mutex_unlock: Received error %d (%s)\n",
Packit fd8b60
                r, strerror(r));
Packit fd8b60
    }
Packit fd8b60
#endif
Packit fd8b60
    assert(r == 0);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#define k5_mutex_assert_locked(M)       ((void)(M))
Packit fd8b60
#define k5_mutex_assert_unlocked(M)     ((void)(M))
Packit fd8b60
#define k5_assert_locked        k5_mutex_assert_locked
Packit fd8b60
#define k5_assert_unlocked      k5_mutex_assert_unlocked
Packit fd8b60
Packit fd8b60
/* Thread-specific data; implemented in a support file, because we'll
Packit fd8b60
   need to keep track of some global data for cleanup purposes.
Packit fd8b60
Packit fd8b60
   Note that the callback function type is such that the C library
Packit fd8b60
   routine free() is a valid callback.  */
Packit fd8b60
typedef enum {
Packit fd8b60
    K5_KEY_COM_ERR,
Packit fd8b60
    K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME,
Packit fd8b60
    K5_KEY_GSS_KRB5_CCACHE_NAME,
Packit fd8b60
    K5_KEY_GSS_KRB5_ERROR_MESSAGE,
Packit fd8b60
    K5_KEY_GSS_SPNEGO_STATUS,
Packit fd8b60
#if defined(__MACH__) && defined(__APPLE__)
Packit fd8b60
    K5_KEY_IPC_CONNECTION_INFO,
Packit fd8b60
#endif
Packit fd8b60
    K5_KEY_MAX
Packit fd8b60
} k5_key_t;
Packit fd8b60
/* rename shorthand symbols for export */
Packit fd8b60
#define k5_key_register krb5int_key_register
Packit fd8b60
#define k5_getspecific  krb5int_getspecific
Packit fd8b60
#define k5_setspecific  krb5int_setspecific
Packit fd8b60
#define k5_key_delete   krb5int_key_delete
Packit fd8b60
extern int k5_key_register(k5_key_t, void (*)(void *));
Packit fd8b60
extern void *k5_getspecific(k5_key_t);
Packit fd8b60
extern int k5_setspecific(k5_key_t, void *);
Packit fd8b60
extern int k5_key_delete(k5_key_t);
Packit fd8b60
Packit fd8b60
extern int  KRB5_CALLCONV krb5int_mutex_alloc  (k5_mutex_t **);
Packit fd8b60
extern void KRB5_CALLCONV krb5int_mutex_free   (k5_mutex_t *);
Packit fd8b60
extern void KRB5_CALLCONV krb5int_mutex_lock   (k5_mutex_t *);
Packit fd8b60
extern void KRB5_CALLCONV krb5int_mutex_unlock (k5_mutex_t *);
Packit fd8b60
Packit fd8b60
/* In time, many of the definitions above should move into the support
Packit fd8b60
   library, and this file should be greatly simplified.  For type
Packit fd8b60
   definitions, that'll take some work, since other data structures
Packit fd8b60
   incorporate mutexes directly, and our mutex type is dependent on
Packit fd8b60
   configuration options and system attributes.  For most functions,
Packit fd8b60
   though, it should be relatively easy.
Packit fd8b60
Packit fd8b60
   For now, plugins should use the exported functions, and not the
Packit fd8b60
   above macros, and use krb5int_mutex_alloc for allocations.  */
Packit fd8b60
#if defined(PLUGIN) || (defined(CONFIG_SMALL) && !defined(THREAD_SUPPORT_IMPL))
Packit fd8b60
#undef k5_mutex_lock
Packit fd8b60
#define k5_mutex_lock krb5int_mutex_lock
Packit fd8b60
#undef k5_mutex_unlock
Packit fd8b60
#define k5_mutex_unlock krb5int_mutex_unlock
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
#endif /* multiple inclusion? */