#include <isc/refcount.h>
#include <isc/strerr.h>
#include <isc/string.h>
+#include <isc/thread.h>
#include <isc/types.h>
#include <isc/util.h>
#include "mem_p.h"
+#define MEM_MAX_THREADS 128
+
#define MCTXLOCK(m) LOCK(&m->lock)
#define MCTXUNLOCK(m) UNLOCK(&m->lock)
#define MPCTXLOCK(mp) \
/*%< locked via the memory context's lock */
ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */
/*%< optionally locked from here down */
- element *items; /*%< low water item list */
size_t size; /*%< size of each item on this pool */
atomic_size_t allocated; /*%< # of items currently given out */
- atomic_size_t freecount; /*%< # of items on reserved list */
+ atomic_size_t *freecount; /*%< # of items on reserved list */
/*%< Stats only. */
atomic_size_t gets; /*%< # of requests to this pool */
/*%< Debugging only. */
char name[16]; /*%< printed name in stats reports */
+ size_t max_threads;
+ element **items; /*%< low water item list */
};
/*
while (pool != NULL) {
fprintf(out, "%15s %10zu %10zu %10zu %10zu %s\n",
pool->name, pool->size,
- atomic_load_relaxed(&pool->allocated),
- atomic_load_relaxed(&pool->freecount),
+ isc_mempool_getallocated(pool),
+ isc_mempool_getfreecount(pool),
atomic_load_relaxed(&pool->gets),
(pool->lock == NULL ? "N" : "Y"));
pool = ISC_LIST_NEXT(pool, link);
.magic = MEMPOOL_MAGIC,
.mctx = mctx,
.size = size,
+ .max_threads = MEM_MAX_THREADS,
};
atomic_init(&mpctx->allocated, 0);
- atomic_init(&mpctx->freecount, 0);
+
+ mpctx->freecount = isc_mem_get(mctx, mpctx->max_threads * sizeof(mpctx->freecount[0]));
+ mpctx->items = isc_mem_get(mctx, mpctx->max_threads * sizeof(mpctx->items[0]));
+
+ for (size_t i = 0; i < mpctx->max_threads; i++) {
+ atomic_init(&mpctx->freecount[i], 0);
+ mpctx->items[i] = NULL;
+ }
*mpctxp = (isc_mempool_t *)mpctx;
isc_mempool_t *mpctx;
isc_mem_t *mctx;
- isc_mutex_t *lock;
element *item;
mpctx = *mpctxp;
*mpctxp = NULL;
+ mpctx->magic = 0;
+
if (atomic_load_acquire(&mpctx->allocated) > 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_mempool_destroy(): mempool %s "
mctx = mpctx->mctx;
- lock = mpctx->lock;
-
- if (lock != NULL) {
- LOCK(lock);
- }
-
/*
* Return any items on the free list
*/
- while (mpctx->items != NULL) {
- INSIST(atomic_fetch_sub_release(&mpctx->freecount, 1) > 0);
-
- item = mpctx->items;
- mpctx->items = item->next;
-
- mem_putstats(mctx, item, mpctx->size);
- mem_put(mctx, item, mpctx->size);
+ for (size_t i = 0; i < mpctx->max_threads; i++) {
+ while (mpctx->items[i] != NULL) {
+ INSIST(atomic_fetch_sub_release(&mpctx->freecount[i], 1) > 0);
+ item = mpctx->items[i];
+ mpctx->items[i] = item->next;
+
+ mem_putstats(mctx, item, mpctx->size);
+ mem_put(mctx, item, mpctx->size);
+ }
}
+ isc_mem_put(mctx, mpctx->freecount, mpctx->max_threads * sizeof(mpctx->freecount[0]));
+ isc_mem_put(mctx, mpctx->items, mpctx->max_threads * sizeof(mpctx->items[0]));
+
/*
* Remove our linked list entry from the memory context.
*/
mctx->poolcnt--;
MCTXUNLOCK(mctx);
- mpctx->magic = 0;
-
isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
-
- if (lock != NULL) {
- UNLOCK(lock);
- }
}
void
element *item;
- MPCTXLOCK(mpctx);
- if (ISC_UNLIKELY(mpctx->items == NULL)) {
+ if (ISC_UNLIKELY(mpctx->items[isc_tid_v] == NULL)) {
isc_mem_t *mctx = mpctx->mctx;
item = mem_get(mctx, mpctx->size);
mem_getstats(mctx, mpctx->size);
} else {
- item = mpctx->items;
- mpctx->items = item->next;
+ item = mpctx->items[isc_tid_v];
+ mpctx->items[isc_tid_v] = item->next;
+ INSIST(atomic_fetch_sub_relaxed(&mpctx->freecount[isc_tid_v], 1) > 0);
}
- MPCTXUNLOCK(mpctx);
REQUIRE(item != NULL);
item->next = NULL;
- INSIST(atomic_fetch_sub_release(&mpctx->freecount, 1) > 0);
atomic_fetch_add_relaxed(&mpctx->gets, 1);
- atomic_fetch_add_release(&mpctx->allocated, 1);
+ atomic_fetch_add_relaxed(&mpctx->allocated, 1);
ADD_TRACE(mpctx->mctx, item, mpctx->size, file, line);
REQUIRE(mem != NULL);
isc_mem_t *mctx = mpctx->mctx;
- size_t freecount = atomic_load_acquire(&mpctx->freecount);
- size_t allocated = atomic_fetch_sub_release(&mpctx->allocated, 1);
+ element *item;
+ size_t freecount = atomic_load_relaxed(&mpctx->freecount[isc_tid_v]);
+ size_t allocated = atomic_fetch_sub_relaxed(&mpctx->allocated, 1);
INSIST(allocated > 0);
/*
* Otherwise, attach it to our free list and bump the counter.
*/
- MPCTXLOCK(mpctx);
-
item = (element *)mem;
- item->next = mpctx->items;
- mpctx->items = item;
- atomic_fetch_add_relaxed(&mpctx->freecount, 1);
-
- MPCTXUNLOCK(mpctx);
+ item->next = mpctx->items[isc_tid_v];
+ mpctx->items[isc_tid_v] = item;
+ atomic_fetch_add_relaxed(&mpctx->freecount[isc_tid_v], 1);
}
#endif /* __SANITIZE_ADDRESS__ */
* Quotas
*/
-unsigned int
+size_t
isc_mempool_getfreecount(isc_mempool_t *mpctx) {
REQUIRE(VALID_MEMPOOL(mpctx));
+ size_t freecount = 0;
- return (atomic_load_relaxed(&mpctx->freecount));
+ for (size_t i = 0; i < mpctx->max_threads; i++) {
+ freecount += atomic_load_relaxed(&mpctx->freecount[i]);
+ }
+
+ return (freecount);
}
-unsigned int
+size_t
isc_mempool_getallocated(isc_mempool_t *mpctx) {
REQUIRE(VALID_MEMPOOL(mpctx));