2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

finetune isc_thread_key implementation [RT #15408]

This commit is contained in:
Mark Andrews
2005-09-18 07:16:24 +00:00
parent 79d2e0b253
commit ed6ca94ad7
13 changed files with 169 additions and 71 deletions

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named-checkconf.c,v 1.38 2005/08/24 23:53:54 marka Exp $ */
/* $Id: named-checkconf.c,v 1.39 2005/09/18 07:16:17 marka Exp $ */
/*! \file */
@@ -438,6 +438,8 @@ main(int argc, char **argv) {
cfg_parser_destroy(&parser);
dns_name_destroy();
isc_log_destroy(&logc);
isc_hash_destroy();

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named-checkzone.c,v 1.40 2005/09/01 02:24:45 marka Exp $ */
/* $Id: named-checkzone.c,v 1.41 2005/09/18 07:16:17 marka Exp $ */
/*! \file */
@@ -86,6 +86,7 @@ static void
destroy(void) {
if (zone != NULL)
dns_zone_detach(&zone);
dns_name_destroy();
}
/*% main processing routine */

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dighost.c,v 1.286 2005/09/09 06:13:59 marka Exp $ */
/* $Id: dighost.c,v 1.287 2005/09/18 07:16:18 marka Exp $ */
/*! \file
* \note
@@ -3223,6 +3223,9 @@ destroy_libs(void) {
void * ptr;
dig_message_t *chase_msg;
#endif
#ifdef WITH_IDN
isc_result_t result;
#endif
debug("destroy_libs()");
if (global_task != NULL) {
@@ -3254,6 +3257,13 @@ destroy_libs(void) {
flush_server_list();
clear_searchlist();
#ifdef WITH_IDN
result = dns_name_settotextfilter(NULL);
check_result(result, "dns_name_settotextfilter");
#endif
dns_name_destroy();
if (commctx != NULL) {
debug("freeing commctx");
isc_mempool_destroy(&commctx);

View File

@@ -16,7 +16,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnssec-keygen.c,v 1.69 2005/04/29 00:22:24 marka Exp $ */
/* $Id: dnssec-keygen.c,v 1.70 2005/09/18 07:16:19 marka Exp $ */
/*! \file */
@@ -409,6 +409,7 @@ main(int argc, char **argv) {
cleanup_logging(&log);
cleanup_entropy(&ectx);
dst_lib_destroy();
dns_name_destroy();
if (verbose > 10)
isc_mem_stats(mctx, stdout);
isc_mem_destroy(&mctx);

View File

@@ -16,7 +16,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnssec-signzone.c,v 1.190 2005/07/18 05:58:55 marka Exp $ */
/* $Id: dnssec-signzone.c,v 1.191 2005/09/18 07:16:19 marka Exp $ */
/*! \file */
@@ -2150,6 +2150,7 @@ main(int argc, char *argv[]) {
dst_lib_destroy();
isc_hash_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();
if (verbose > 10)
isc_mem_stats(mctx, stdout);
isc_mem_destroy(&mctx);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: main.c,v 1.148 2005/09/05 00:10:52 marka Exp $ */
/* $Id: main.c,v 1.149 2005/09/18 07:16:19 marka Exp $ */
/*! \file */
@@ -715,6 +715,8 @@ cleanup(void) {
dlz_drivers_clear();
#endif
dns_name_destroy();
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
ISC_LOG_NOTICE, "exiting");
ns_log_shutdown();

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: nsupdate.c,v 1.138 2005/04/27 04:56:03 sra Exp $ */
/* $Id: nsupdate.c,v 1.139 2005/09/18 07:16:20 marka Exp $ */
/*! \file */
@@ -1927,6 +1927,9 @@ cleanup(void) {
ddebug("Destroying hash context");
isc_hash_destroy();
ddebug("Destroying name state");
dns_name_destroy();
ddebug("Destroying memory context");
if (memdebugging)
isc_mem_stats(mctx, stderr);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rndc.c,v 1.105 2005/04/27 04:56:04 sra Exp $ */
/* $Id: rndc.c,v 1.106 2005/09/18 07:16:21 marka Exp $ */
/*! \file */
@@ -824,6 +824,8 @@ main(int argc, char **argv) {
isc_mem_put(mctx, args, argslen);
isccc_ccmsg_invalidate(&ccmsg);
dns_name_destroy();
if (show_final_mem)
isc_mem_stats(mctx, stderr);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: name.h,v 1.118 2005/09/09 06:14:00 marka Exp $ */
/* $Id: name.h,v 1.119 2005/09/18 07:16:22 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

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: name.c,v 1.154 2005/09/10 01:02:08 marka Exp $ */
/* $Id: name.c,v 1.155 2005/09/18 07:16:21 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
}

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: thread.h,v 1.23 2005/09/09 06:14:00 marka Exp $ */
/* $Id: thread.h,v 1.24 2005/09/18 07:16:22 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

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: thread.h,v 1.18 2005/09/09 14:11:38 marka Exp $ */
/* $Id: thread.h,v 1.19 2005/09/18 07:16:24 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 */

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: thread.c,v 1.20 2005/09/09 14:11:38 marka Exp $ */
/* $Id: thread.c,v 1.21 2005/09/18 07:16:23 marka Exp $ */
#include <config.h>
@@ -66,26 +66,25 @@ isc_thread_setconcurrency(unsigned int level) {
* call exists
*/
}
void *
isc_key_getspecific(isc_thread_key_t key) {
return(TlsGetValue(key));
}
int
isc_key_setspecific(isc_thread_key_t key, void *value) {
return (TlsSetValue(key, value) ? 0 : GetLastError());
}
int
isc_key_create(isc_thread_key_t *key, void (*func)(void *)) {
*key = TlsAlloc();
return ((*key == -1) ? 0 : GetLastError());
}
int
isc_key_destroy(isc_thread_key_t key) {
return (TlsFree(key) ? 0 : GetLastError());
}
void *
isc_thread_key_getspecific(isc_thread_key_t key) {
return(TlsGetValue(key));
}
int
isc_thread_key_setspecific(isc_thread_key_t key, void *value) {
return (TlsSetValue(key, value) ? 0 : GetLastError());
}
int
isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)) {
*key = TlsAlloc();
return ((*key != -1) ? 0 : GetLastError());
}
int
isc_thread_key_destroy(isc_thread_key_t key) {
return (TlsFree(key) ? 0 : GetLastError());
}