mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 21:23:06 +00:00
Add batcher module.
This can be used to batch up simple operation commands for later use by another thread.
This commit is contained in:
committed by
David Goldblatt
parent
86f4851f5d
commit
70c94d7474
86
src/batcher.c
Normal file
86
src/batcher.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||
|
||||
#include "jemalloc/internal/batcher.h"
|
||||
|
||||
#include "jemalloc/internal/assert.h"
|
||||
#include "jemalloc/internal/atomic.h"
|
||||
|
||||
void
|
||||
batcher_init(batcher_t *batcher, size_t nelems_max) {
|
||||
atomic_store_zu(&batcher->nelems, 0, ATOMIC_RELAXED);
|
||||
batcher->nelems_max = nelems_max;
|
||||
malloc_mutex_init(&batcher->mtx, "batcher", WITNESS_RANK_BATCHER,
|
||||
malloc_mutex_rank_exclusive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an index (into some user-owned array) to use for pushing, or
|
||||
* BATCHER_NO_IDX if no index is free.
|
||||
*/
|
||||
size_t batcher_push_begin(tsdn_t *tsdn, batcher_t *batcher,
|
||||
size_t elems_to_push) {
|
||||
assert(elems_to_push > 0);
|
||||
size_t nelems_guess = atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED);
|
||||
if (nelems_guess + elems_to_push > batcher->nelems_max) {
|
||||
return BATCHER_NO_IDX;
|
||||
}
|
||||
malloc_mutex_lock(tsdn, &batcher->mtx);
|
||||
size_t nelems = atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED);
|
||||
if (nelems + elems_to_push > batcher->nelems_max) {
|
||||
malloc_mutex_unlock(tsdn, &batcher->mtx);
|
||||
return BATCHER_NO_IDX;
|
||||
}
|
||||
assert(elems_to_push <= batcher->nelems_max - nelems);
|
||||
/*
|
||||
* We update nelems at push time (instead of during pop) so that other
|
||||
* racing accesses of the batcher can fail fast instead of trying to
|
||||
* acquire a mutex only to discover that there's no space for them.
|
||||
*/
|
||||
atomic_store_zu(&batcher->nelems, nelems + elems_to_push, ATOMIC_RELAXED);
|
||||
return nelems;
|
||||
}
|
||||
|
||||
void
|
||||
batcher_push_end(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
malloc_mutex_assert_owner(tsdn, &batcher->mtx);
|
||||
assert(atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED) > 0);
|
||||
malloc_mutex_unlock(tsdn, &batcher->mtx);
|
||||
}
|
||||
|
||||
size_t
|
||||
batcher_pop_begin(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
size_t nelems_guess = atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED);
|
||||
assert(nelems_guess <= batcher->nelems_max);
|
||||
if (nelems_guess == 0) {
|
||||
return BATCHER_NO_IDX;
|
||||
}
|
||||
malloc_mutex_lock(tsdn, &batcher->mtx);
|
||||
size_t nelems = atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED);
|
||||
assert(nelems <= batcher->nelems_max);
|
||||
if (nelems == 0) {
|
||||
malloc_mutex_unlock(tsdn, &batcher->mtx);
|
||||
return BATCHER_NO_IDX;
|
||||
}
|
||||
atomic_store_zu(&batcher->nelems, 0, ATOMIC_RELAXED);
|
||||
return nelems;
|
||||
}
|
||||
|
||||
void batcher_pop_end(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
assert(atomic_load_zu(&batcher->nelems, ATOMIC_RELAXED) == 0);
|
||||
malloc_mutex_unlock(tsdn, &batcher->mtx);
|
||||
}
|
||||
|
||||
void
|
||||
batcher_prefork(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
malloc_mutex_prefork(tsdn, &batcher->mtx);
|
||||
}
|
||||
|
||||
void
|
||||
batcher_postfork_parent(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
malloc_mutex_postfork_parent(tsdn, &batcher->mtx);
|
||||
}
|
||||
|
||||
void
|
||||
batcher_postfork_child(tsdn_t *tsdn, batcher_t *batcher) {
|
||||
malloc_mutex_postfork_child(tsdn, &batcher->mtx);
|
||||
}
|
||||
Reference in New Issue
Block a user