mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 18:19:42 +00:00
Make hazard pointers max_threads configurable at runtime.
hp implementation requires an object for each thread accessing a hazard pointer. previous implementation had a hardcoded HP_MAX_THREAD value of 128, which failed on machines with lots of CPU cores (named uses 3n threads). We make isc__hp_max_threads configurable at startup, with the value set to 4*named_g_cpus. It's also important for this value not to be too big as we do linear searches on a list.
This commit is contained in:
parent
1639dc8dca
commit
493b6a9f33
@ -23,6 +23,7 @@
|
|||||||
#include <isc/dir.h>
|
#include <isc/dir.h>
|
||||||
#include <isc/file.h>
|
#include <isc/file.h>
|
||||||
#include <isc/hash.h>
|
#include <isc/hash.h>
|
||||||
|
#include <isc/hp.h>
|
||||||
#include <isc/httpd.h>
|
#include <isc/httpd.h>
|
||||||
#include <isc/netmgr.h>
|
#include <isc/netmgr.h>
|
||||||
#include <isc/os.h>
|
#include <isc/os.h>
|
||||||
@ -907,6 +908,12 @@ create_managers(void) {
|
|||||||
"using %u UDP listener%s per interface",
|
"using %u UDP listener%s per interface",
|
||||||
named_g_udpdisp, named_g_udpdisp == 1 ? "" : "s");
|
named_g_udpdisp, named_g_udpdisp == 1 ? "" : "s");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have ncpus network threads, ncpus worker threads, ncpus
|
||||||
|
* old network threads - make it 4x just to be safe. The memory
|
||||||
|
* impact is neglible.
|
||||||
|
*/
|
||||||
|
isc_hp_init(4*named_g_cpus);
|
||||||
named_g_nm = isc_nm_start(named_g_mctx, named_g_cpus);
|
named_g_nm = isc_nm_start(named_g_mctx, named_g_cpus);
|
||||||
if (named_g_nm == NULL) {
|
if (named_g_nm == NULL) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
|
33
lib/isc/hp.c
33
lib/isc/hp.c
@ -54,12 +54,13 @@
|
|||||||
#include <isc/thread.h>
|
#include <isc/thread.h>
|
||||||
|
|
||||||
#define HP_MAX_THREADS 128
|
#define HP_MAX_THREADS 128
|
||||||
|
static int isc__hp_max_threads = HP_MAX_THREADS;
|
||||||
#define HP_MAX_HPS 4 /* This is named 'K' in the HP paper */
|
#define HP_MAX_HPS 4 /* This is named 'K' in the HP paper */
|
||||||
#define CLPAD (128 / sizeof(uintptr_t))
|
#define CLPAD (128 / sizeof(uintptr_t))
|
||||||
#define HP_THRESHOLD_R 0 /* This is named 'R' in the HP paper */
|
#define HP_THRESHOLD_R 0 /* This is named 'R' in the HP paper */
|
||||||
|
|
||||||
/* Maximum number of retired objects per thread */
|
/* Maximum number of retired objects per thread */
|
||||||
#define MAX_RETIRED (HP_MAX_THREADS * HP_MAX_HPS)
|
static int isc__hp_max_retired = HP_MAX_THREADS * HP_MAX_HPS;
|
||||||
|
|
||||||
#define TID_UNKNOWN -1
|
#define TID_UNKNOWN -1
|
||||||
|
|
||||||
@ -69,14 +70,14 @@ ISC_THREAD_LOCAL int tid_v = TID_UNKNOWN;
|
|||||||
|
|
||||||
typedef struct retirelist {
|
typedef struct retirelist {
|
||||||
int size;
|
int size;
|
||||||
uintptr_t list[MAX_RETIRED];
|
uintptr_t *list;
|
||||||
} retirelist_t;
|
} retirelist_t;
|
||||||
|
|
||||||
struct isc_hp {
|
struct isc_hp {
|
||||||
int max_hps;
|
int max_hps;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
atomic_uintptr_t *hp[HP_MAX_THREADS];
|
atomic_uintptr_t **hp;
|
||||||
retirelist_t *rl[HP_MAX_THREADS];
|
retirelist_t **rl;
|
||||||
isc_hp_deletefunc_t *deletefunc;
|
isc_hp_deletefunc_t *deletefunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,12 +85,18 @@ static inline int
|
|||||||
tid() {
|
tid() {
|
||||||
if (tid_v == TID_UNKNOWN) {
|
if (tid_v == TID_UNKNOWN) {
|
||||||
tid_v = atomic_fetch_add(&tid_v_base, 1);
|
tid_v = atomic_fetch_add(&tid_v_base, 1);
|
||||||
REQUIRE(tid_v < HP_MAX_THREADS);
|
REQUIRE(tid_v < isc__hp_max_threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tid_v);
|
return (tid_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc_hp_init(int max_threads) {
|
||||||
|
isc__hp_max_threads = max_threads;
|
||||||
|
isc__hp_max_retired = max_threads * HP_MAX_HPS;
|
||||||
|
}
|
||||||
|
|
||||||
isc_hp_t *
|
isc_hp_t *
|
||||||
isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
|
isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
|
||||||
isc_hp_t *hp = isc_mem_get(mctx, sizeof(*hp));
|
isc_hp_t *hp = isc_mem_get(mctx, sizeof(*hp));
|
||||||
@ -105,7 +112,10 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
|
|||||||
|
|
||||||
isc_mem_attach(mctx, &hp->mctx);
|
isc_mem_attach(mctx, &hp->mctx);
|
||||||
|
|
||||||
for (int i = 0; i < HP_MAX_THREADS; i++) {
|
hp->hp = isc_mem_get(mctx, isc__hp_max_threads * sizeof(hp->hp[0]));
|
||||||
|
hp->rl = isc_mem_get(mctx, isc__hp_max_threads * sizeof(hp->rl[0]));
|
||||||
|
|
||||||
|
for (int i = 0; i < isc__hp_max_threads; i++) {
|
||||||
hp->hp[i] = isc_mem_get(mctx, CLPAD * 2 * sizeof(hp->hp[i][0]));
|
hp->hp[i] = isc_mem_get(mctx, CLPAD * 2 * sizeof(hp->hp[i][0]));
|
||||||
hp->rl[i] = isc_mem_get(mctx, sizeof(*hp->rl[0]));
|
hp->rl[i] = isc_mem_get(mctx, sizeof(*hp->rl[0]));
|
||||||
*hp->rl[i] = (retirelist_t) { .size = 0 };
|
*hp->rl[i] = (retirelist_t) { .size = 0 };
|
||||||
@ -113,6 +123,7 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
|
|||||||
for (int j = 0; j < hp->max_hps; j++) {
|
for (int j = 0; j < hp->max_hps; j++) {
|
||||||
atomic_init(&hp->hp[i][j], 0);
|
atomic_init(&hp->hp[i][j], 0);
|
||||||
}
|
}
|
||||||
|
hp->rl[i]->list = isc_mem_get(hp->mctx, isc__hp_max_retired * sizeof(uintptr_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (hp);
|
return (hp);
|
||||||
@ -120,7 +131,7 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
isc_hp_destroy(isc_hp_t *hp) {
|
isc_hp_destroy(isc_hp_t *hp) {
|
||||||
for (int i = 0; i < HP_MAX_THREADS; i++) {
|
for (int i = 0; i < isc__hp_max_threads; i++) {
|
||||||
isc_mem_put(hp->mctx, hp->hp[i],
|
isc_mem_put(hp->mctx, hp->hp[i],
|
||||||
CLPAD * 2 * sizeof(uintptr_t));
|
CLPAD * 2 * sizeof(uintptr_t));
|
||||||
|
|
||||||
@ -128,9 +139,11 @@ isc_hp_destroy(isc_hp_t *hp) {
|
|||||||
void *data = (void *)hp->rl[i]->list[j];
|
void *data = (void *)hp->rl[i]->list[j];
|
||||||
hp->deletefunc(data);
|
hp->deletefunc(data);
|
||||||
}
|
}
|
||||||
|
isc_mem_put(hp->mctx, hp->rl[i]->list, isc__hp_max_retired * sizeof(uintptr_t));
|
||||||
isc_mem_put(hp->mctx, hp->rl[i], sizeof(*hp->rl[0]));
|
isc_mem_put(hp->mctx, hp->rl[i], sizeof(*hp->rl[0]));
|
||||||
}
|
}
|
||||||
|
isc_mem_put(hp->mctx, hp->hp, isc__hp_max_threads * sizeof(hp->hp[0]));
|
||||||
|
isc_mem_put(hp->mctx, hp->rl, isc__hp_max_threads * sizeof(hp->rl[0]));
|
||||||
|
|
||||||
isc_mem_putanddetach(&hp->mctx, hp, sizeof(*hp));
|
isc_mem_putanddetach(&hp->mctx, hp, sizeof(*hp));
|
||||||
}
|
}
|
||||||
@ -172,7 +185,7 @@ isc_hp_protect_release(isc_hp_t *hp, int ihp, atomic_uintptr_t ptr) {
|
|||||||
void
|
void
|
||||||
isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
|
isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
|
||||||
hp->rl[tid()]->list[hp->rl[tid()]->size++] = ptr;
|
hp->rl[tid()]->list[hp->rl[tid()]->size++] = ptr;
|
||||||
INSIST(hp->rl[tid()]->size < MAX_RETIRED);
|
INSIST(hp->rl[tid()]->size < isc__hp_max_retired);
|
||||||
|
|
||||||
if (hp->rl[tid()]->size < HP_THRESHOLD_R) {
|
if (hp->rl[tid()]->size < HP_THRESHOLD_R) {
|
||||||
return;
|
return;
|
||||||
@ -182,7 +195,7 @@ isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
|
|||||||
uintptr_t obj = hp->rl[tid()]->list[iret];
|
uintptr_t obj = hp->rl[tid()]->list[iret];
|
||||||
bool can_delete = true;
|
bool can_delete = true;
|
||||||
for (int itid = 0;
|
for (int itid = 0;
|
||||||
itid < HP_MAX_THREADS && can_delete;
|
itid < isc__hp_max_threads && can_delete;
|
||||||
itid++)
|
itid++)
|
||||||
{
|
{
|
||||||
for (int ihp = hp->max_hps-1; ihp >= 0; ihp--) {
|
for (int ihp = hp->max_hps-1; ihp >= 0; ihp--) {
|
||||||
|
@ -64,6 +64,13 @@
|
|||||||
typedef void
|
typedef void
|
||||||
(isc_hp_deletefunc_t)(void *);
|
(isc_hp_deletefunc_t)(void *);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc_hp_init(int max_threads);
|
||||||
|
/*%<
|
||||||
|
* Initialize hazard pointer constants - isc__hp_max_threads. If more threads
|
||||||
|
* will try to access hp it will assert.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_hp_t *
|
isc_hp_t *
|
||||||
isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc);
|
isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc);
|
||||||
/*%<
|
/*%<
|
||||||
|
@ -248,6 +248,7 @@ isc_hex_tobuffer
|
|||||||
isc_hex_totext
|
isc_hex_totext
|
||||||
isc_hp_clear
|
isc_hp_clear
|
||||||
isc_hp_destroy
|
isc_hp_destroy
|
||||||
|
isc_hp_init
|
||||||
isc_hp_protect
|
isc_hp_protect
|
||||||
isc_hp_protect_ptr
|
isc_hp_protect_ptr
|
||||||
isc_hp_protect_release
|
isc_hp_protect_release
|
||||||
|
Loading…
x
Reference in New Issue
Block a user