finetune isc_thread_key implementation [RT #15408]
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: name.h,v 1.107.18.11 2005/09/09 06:22:08 marka Exp $ */
|
||||
/* $Id: name.h,v 1.107.18.12 2005/09/18 07:58:07 marka Exp $ */
|
||||
|
||||
#ifndef DNS_NAME_H
|
||||
#define DNS_NAME_H 1
|
||||
@@ -1132,6 +1132,11 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc);
|
||||
* Set / clear a thread specific function 'proc' to be called at the
|
||||
* end of dns_name_totext().
|
||||
*
|
||||
* Note: Under Windows you need to call "dns_name_settotextfilter(NULL);"
|
||||
* prior to exiting the thread otherwise memory will be leaked.
|
||||
* For other platforms, which are pthreads based, this is still a good
|
||||
* idea but not required.
|
||||
*
|
||||
* Returns
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_UNEXPECTED
|
||||
@@ -1169,7 +1174,7 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target);
|
||||
|
||||
isc_boolean_t
|
||||
dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard);
|
||||
/*
|
||||
/*%<
|
||||
* Return if 'name' is a valid hostname. RFC 952 / RFC 1123.
|
||||
* If 'wildcard' is ISC_TRUE then allow the first label of name to
|
||||
* be a wildcard.
|
||||
@@ -1182,20 +1187,32 @@ dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard);
|
||||
|
||||
isc_boolean_t
|
||||
dns_name_ismailbox(const dns_name_t *name);
|
||||
/*
|
||||
/*%<
|
||||
* Return if 'name' is a valid mailbox. RFC 821.
|
||||
*
|
||||
* Requires:
|
||||
* 'name' to be valid.
|
||||
* \li 'name' to be valid.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_name_internalwildcard(const dns_name_t *name);
|
||||
/*
|
||||
/*%<
|
||||
* Return if 'name' contains a internal wildcard name.
|
||||
*
|
||||
* Requires:
|
||||
* 'name' to be valid.
|
||||
* \li 'name' to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_name_destroy(void);
|
||||
/*%<
|
||||
* Cleanup dns_name_settotextfilter() / dns_name_totext() state.
|
||||
*
|
||||
* This should be called as part of the final cleanup process.
|
||||
*
|
||||
* Note: dns_name_settotextfilter(NULL); should be called for all
|
||||
* threads which have called dns_name_settotextfilter() with a
|
||||
* non-NULL arguement prior to calling dns_name_destroy();
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: name.c,v 1.144.18.10 2005/09/10 01:09:29 marka Exp $ */
|
||||
/* $Id: name.c,v 1.144.18.11 2005/09/18 07:58:07 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -191,6 +191,9 @@ dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
|
||||
* dns_name_t to text post-conversion procedure.
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
static int thread_key_initialized = 0;
|
||||
static isc_mutex_t thread_key_mutex;
|
||||
static isc_mem_t *thread_key_mctx = NULL;
|
||||
static isc_thread_key_t totext_filter_proc_key;
|
||||
static isc_once_t once = ISC_ONCE_INIT;
|
||||
#else
|
||||
@@ -1277,8 +1280,49 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
static void
|
||||
free_specific(void *arg) {
|
||||
dns_name_totextfilter_t *mem = arg;
|
||||
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
|
||||
/* Stop use being called again. */
|
||||
(void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
thread_key_mutex_init(void) {
|
||||
RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
totext_filter_proc_key_init(void) {
|
||||
RUNTIME_CHECK(isc_key_create(&totext_filter_proc_key, free) == 0);
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
* We need the call to isc_once_do() to support profiled mutex
|
||||
* otherwise thread_key_mutex could be initialized at compile time.
|
||||
*/
|
||||
result = isc_once_do(&once, thread_key_mutex_init);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
if (!thread_key_initialized) {
|
||||
LOCK(&thread_key_mutex);
|
||||
if (thread_key_mctx == NULL)
|
||||
result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto unlock;
|
||||
isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
|
||||
|
||||
if (!thread_key_initialized &&
|
||||
isc_thread_key_create(&totext_filter_proc_key,
|
||||
free_specific) != 0) {
|
||||
result = ISC_R_FAILURE;
|
||||
isc_mem_detach(&thread_key_mctx);
|
||||
} else
|
||||
thread_key_initialized = 1;
|
||||
unlock:
|
||||
UNLOCK(&thread_key_mutex);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1308,7 +1352,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
REQUIRE(ISC_BUFFER_VALID(target));
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
result = isc_once_do(&once, totext_filter_proc_key_init);
|
||||
result = totext_filter_proc_key_init();
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
#endif
|
||||
@@ -1445,7 +1489,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
|
||||
mem = isc_key_getspecific(totext_filter_proc_key);
|
||||
mem = isc_thread_key_getspecific(totext_filter_proc_key);
|
||||
if (mem)
|
||||
totext_filter_proc = *mem;
|
||||
#endif
|
||||
@@ -2238,8 +2282,9 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
isc_result_t result;
|
||||
dns_name_totextfilter_t *mem;
|
||||
int res;
|
||||
|
||||
result = isc_once_do(&once, totext_filter_proc_key_init);
|
||||
result = totext_filter_proc_key_init();
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
@@ -2247,28 +2292,27 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
|
||||
* If we already have been here set / clear as appropriate.
|
||||
* Otherwise allocate memory.
|
||||
*/
|
||||
mem = isc_key_getspecific(totext_filter_proc_key);
|
||||
mem = isc_thread_key_getspecific(totext_filter_proc_key);
|
||||
if (mem != NULL && proc != NULL) {
|
||||
*mem = proc;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
if (proc == NULL) {
|
||||
free(mem);
|
||||
if (isc_key_setspecific(totext_filter_proc_key, NULL) != 0)
|
||||
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
|
||||
res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
|
||||
if (res != 0)
|
||||
result = ISC_R_UNEXPECTED;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use malloc because Windows can't automatically free the
|
||||
* memory and we don't want to trigger a INSIST at exit.
|
||||
*/
|
||||
mem = malloc(sizeof(dns_name_totextfilter_t));
|
||||
mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
|
||||
if (mem == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
*mem = proc;
|
||||
if (isc_key_setspecific(totext_filter_proc_key, mem) != 0)
|
||||
if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
|
||||
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
|
||||
result = ISC_R_UNEXPECTED;
|
||||
}
|
||||
return (result);
|
||||
#else
|
||||
totext_filter_proc = proc;
|
||||
@@ -2350,3 +2394,19 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
dns_name_destroy(void) {
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
|
||||
== ISC_R_SUCCESS);
|
||||
|
||||
LOCK(&thread_key_mutex);
|
||||
if (thread_key_initialized) {
|
||||
isc_mem_detach(&thread_key_mctx);
|
||||
isc_thread_key_delete(totext_filter_proc_key);
|
||||
thread_key_initialized = 0;
|
||||
}
|
||||
UNLOCK(&thread_key_mutex);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: thread.h,v 1.20.18.3 2005/09/09 06:22:09 marka Exp $ */
|
||||
/* $Id: thread.h,v 1.20.18.4 2005/09/18 07:58:08 marka Exp $ */
|
||||
|
||||
#ifndef ISC_THREAD_H
|
||||
#define ISC_THREAD_H 1
|
||||
@@ -50,10 +50,10 @@ isc_thread_setconcurrency(unsigned int level);
|
||||
#define isc_thread_self \
|
||||
(unsigned long)pthread_self
|
||||
|
||||
#define isc_key_create pthread_key_create
|
||||
#define isc_key_getspecific pthread_getspecific
|
||||
#define isc_key_setspecific pthread_setspecific
|
||||
#define isc_key_delete pthread_key_delete
|
||||
#define isc_thread_key_create pthread_key_create
|
||||
#define isc_thread_key_getspecific pthread_getspecific
|
||||
#define isc_thread_key_setspecific pthread_setspecific
|
||||
#define isc_thread_key_delete pthread_key_delete
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: thread.h,v 1.16.18.2 2005/09/09 14:11:05 marka Exp $ */
|
||||
/* $Id: thread.h,v 1.16.18.3 2005/09/18 07:58:09 marka Exp $ */
|
||||
|
||||
#ifndef ISC_THREAD_H
|
||||
#define ISC_THREAD_H 1
|
||||
@@ -68,7 +68,7 @@ typedef HANDLE isc_thread_t;
|
||||
typedef unsigned int isc_threadresult_t;
|
||||
typedef void * isc_threadarg_t;
|
||||
typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t);
|
||||
typedef DWORD isc_thread_key_t;
|
||||
typedef DWORD isc_thread_key_t;
|
||||
|
||||
#define isc_thread_self (unsigned long)GetCurrentThreadId
|
||||
|
||||
@@ -83,18 +83,18 @@ isc_thread_join(isc_thread_t, isc_threadresult_t *);
|
||||
void
|
||||
isc_thread_setconcurrency(unsigned int level);
|
||||
|
||||
int
|
||||
isc_key_create(isc_thread_key_t *key, void (*func)(void *));
|
||||
|
||||
int
|
||||
isc_key_destroy(isc_thread_key_t key);
|
||||
|
||||
void *
|
||||
isc_key_getspecific(isc_thread_key);
|
||||
|
||||
int
|
||||
isc_key_setspecific(isc_thread_key_t key, void *value);
|
||||
|
||||
int
|
||||
isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *));
|
||||
|
||||
int
|
||||
isc_thread_key_destroy(isc_thread_key_t key);
|
||||
|
||||
void *
|
||||
isc_thread_key_getspecific(isc_thread_key);
|
||||
|
||||
int
|
||||
isc_thread_key_setspecific(isc_thread_key_t key, void *value);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_THREAD_H */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: thread.c,v 1.18.18.3 2005/09/12 07:10:41 marka Exp $ */
|
||||
/* $Id: thread.c,v 1.18.18.4 2005/09/18 07:58:08 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -88,4 +88,3 @@ int
|
||||
isc_key_destroy(isc_thread_key_t key) {
|
||||
return (TlsFree(key) ? 0 : GetLastError());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user