#include "tls.h" #include "mod_nsd.h" static Ns_TlsCleanup *(cleanups)[NS_THREAD_MAXTLS]; static Ns_Tls next_tls = 0; void *start_thread_tls[NS_THREAD_MAXTLS]; /* The implementation of these is so much simpler in the * absence of locking... */ void ns_init_tls () { int i; next_tls = 0; for (i = 0; i < NS_THREAD_MAXTLS; ++i) start_thread_tls[i] = NULL; } void Ns_TlsAlloc (Ns_Tls *tlskey, Ns_TlsCleanup *cleanup) { /* The following "can't happen" --- we've left space for 20 and need * five tops... */ if (next_tls == NS_THREAD_MAXTLS) { fprintf (stderr, "EXCEEDED MAXIMUM TLS!!!!!"); exit (100); } cleanups[next_tls] = cleanup; *tlskey = next_tls++; } /* Cleaning up tls when the pool it's attached to is deallocated... */ static void cleanup_ns_tls (void *stuff) { void **items = (void **)stuff; int i; for (i = 0; i < next_tls; ++i) if (items[i] != NULL) { if (cleanups[i] != NULL) { (*cleanups[i])(items[i]); } items[i] = NULL; } } /* Get the TLS vector for a request_rec, allocating it and * registering the cleanup if necessary */ static void **get_ns_tls (request_rec *r) { void **items; int i; if (r == NULL) return start_thread_tls; items = ap_get_module_config(r->request_config, &aolserver_module); if (items != NULL) return items; /* Allocate space --- * Not 100% portable to trust that a null pointer is a bitwise zero */ items = ap_palloc (r->pool, NS_THREAD_MAXTLS * sizeof (void *)); for (i = 0; i < NS_THREAD_MAXTLS; ++i) items[i] = NULL; /* No race condition on the cleanup here, since no tls has actually * been set yet... */ ap_set_module_config (r->request_config, &aolserver_module, items); ap_register_cleanup (r->pool, items, cleanup_ns_tls, cleanup_ns_tls); return items; } void *Ns_TlsGet (Ns_Tls *tlskey) { void **items = get_ns_tls (Tcl_request_rec); return items[*tlskey]; } void Ns_TlsSet (Ns_Tls *tlskey, void *val) { void **items = get_ns_tls (Tcl_request_rec); items[*tlskey] = val; }