|
Packit Service |
99d1c0 |
Thread safety in the MIT Kerberos libraries
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
The return value from krb5_cc_default_name is a handle on internal
|
|
Packit Service |
99d1c0 |
storage from the krb5_context. It is valid only until
|
|
Packit Service |
99d1c0 |
krb5_cc_set_default_name or krb5_free_context is called. If
|
|
Packit Service |
99d1c0 |
krb5_cc_set_default_name may be called, the calling code must ensure
|
|
Packit Service |
99d1c0 |
that the storage returned by krb5_cc_default_name is no longer in use
|
|
Packit Service |
99d1c0 |
by that time.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
Any use of krb5_context must be confined to one thread at a time by
|
|
Packit Service |
99d1c0 |
the application code.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
Uses of credentials caches, replay caches, and keytabs may happen in
|
|
Packit Service |
99d1c0 |
multiple threads simultaneously as long as none of them destroys the
|
|
Packit Service |
99d1c0 |
object while other threads may still be using it. (Any internal data
|
|
Packit Service |
99d1c0 |
modification in those objects will be protected by mutexes or other
|
|
Packit Service |
99d1c0 |
means, within the krb5 library.)
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
The simple, exposed data structures in krb5.h like krb5_principal are
|
|
Packit Service |
99d1c0 |
not protected; they should not be used in one thread while another
|
|
Packit Service |
99d1c0 |
thread might be modifying them. (TO DO: Build a list of which calls
|
|
Packit Service |
99d1c0 |
keep references to supplied data or return references to
|
|
Packit Service |
99d1c0 |
otherwise-referenced data, as opposed to everything making copies.)
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
[ This part is a little outdated already. ]
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
// Between these two, we should be able to do pure compile-time
|
|
Packit Service |
99d1c0 |
// and pure run-time initialization.
|
|
Packit Service |
99d1c0 |
// POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER,
|
|
Packit Service |
99d1c0 |
// finish does nothing
|
|
Packit Service |
99d1c0 |
// Windows: partial initializer is zero/empty,
|
|
Packit Service |
99d1c0 |
// finish does the actual work and runs at load time
|
|
Packit Service |
99d1c0 |
// debug: partial initializer sets one magic value,
|
|
Packit Service |
99d1c0 |
// finish verifies, sets a new magic value
|
|
Packit Service |
99d1c0 |
k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
|
|
Packit Service |
99d1c0 |
int k5_mutex_finish_init(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
// for dynamic allocation
|
|
Packit Service |
99d1c0 |
int k5_mutex_init(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
// Must work for both kinds of allocation, even if it means adding
|
|
Packit Service |
99d1c0 |
// a flag.
|
|
Packit Service |
99d1c0 |
int k5_mutex_destroy(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
//
|
|
Packit Service |
99d1c0 |
// Per library, one function to finish the static mutex
|
|
Packit Service |
99d1c0 |
// initialization.
|
|
Packit Service |
99d1c0 |
//
|
|
Packit Service |
99d1c0 |
// A second function called at various possible "first" entry
|
|
Packit Service |
99d1c0 |
// points which either calls pthread_once on the first function
|
|
Packit Service |
99d1c0 |
// (POSIX), or checks some flag set by the first function (Windows,
|
|
Packit Service |
99d1c0 |
// debug support), and possibly returns an error.
|
|
Packit Service |
99d1c0 |
//
|
|
Packit Service |
99d1c0 |
// A third function for library termination calls mutex_destroy on
|
|
Packit Service |
99d1c0 |
// each mutex for the library.
|
|
Packit Service |
99d1c0 |
//
|
|
Packit Service |
99d1c0 |
//
|
|
Packit Service |
99d1c0 |
int k5_mutex_lock(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
int k5_mutex_unlock(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
// Optional (always defined, but need not do anything):
|
|
Packit Service |
99d1c0 |
void k5_mutex_assert_locked(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
void k5_mutex_assert_unlocked(k5_mutex_t *);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
k5_key_t key;
|
|
Packit Service |
99d1c0 |
int k5_key_create(k5_key_t *, void (*destructor)(void *));
|
|
Packit Service |
99d1c0 |
void *k5_getspecific(k5_key_t);
|
|
Packit Service |
99d1c0 |
int k5_setspecific(k5_key_t, const void *);
|
|
Packit Service |
99d1c0 |
... stuff to signal library termination ...
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
This is **NOT** an exported interface, and is subject to change.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
On many platforms with weak reference support, we can declare certain
|
|
Packit Service |
99d1c0 |
symbols to be weak, and test the addresses before calling them. The
|
|
Packit Service |
99d1c0 |
references generally will be non-null if the application pulls in the
|
|
Packit Service |
99d1c0 |
pthread support. Sometimes stubs are present in the C library for
|
|
Packit Service |
99d1c0 |
some of these routines, and sometimes they're not functional; if so,
|
|
Packit Service |
99d1c0 |
we need to figure out which ones, and check for the presence of some
|
|
Packit Service |
99d1c0 |
*other* routines.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
AIX 4.3.3 doesn't support weak references. However, it looks like
|
|
Packit Service |
99d1c0 |
calling dlsym(NULL) causes the pthread library to get loaded, so we're
|
|
Packit Service |
99d1c0 |
going to just go ahead and link against it anyways.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
On Tru64 we also link against the thread library always.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
For now, the basic model is:
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
If weak references are supported, use them.
|
|
Packit Service |
99d1c0 |
Else, assume support is present; if that means explicitly pulling in
|
|
Packit Service |
99d1c0 |
the thread library, so be it.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
The locking described above may not be sufficient, at least for good
|
|
Packit Service |
99d1c0 |
performance. At some point we may want to switch to read/write locks,
|
|
Packit Service |
99d1c0 |
so multiple threads can grovel over a data structure at once as long
|
|
Packit Service |
99d1c0 |
as they don't change it.
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
See also notes in src/include/k5-thread.h.
|