Blame jemalloc/include/jemalloc/internal/cache_bin.h

Packit 345191
#ifndef JEMALLOC_INTERNAL_CACHE_BIN_H
Packit 345191
#define JEMALLOC_INTERNAL_CACHE_BIN_H
Packit 345191
Packit 345191
#include "jemalloc/internal/ql.h"
Packit 345191
Packit 345191
/*
Packit 345191
 * The cache_bins are the mechanism that the tcache and the arena use to
Packit 345191
 * communicate.  The tcache fills from and flushes to the arena by passing a
Packit 345191
 * cache_bin_t to fill/flush.  When the arena needs to pull stats from the
Packit 345191
 * tcaches associated with it, it does so by iterating over its
Packit 345191
 * cache_bin_array_descriptor_t objects and reading out per-bin stats it
Packit 345191
 * contains.  This makes it so that the arena need not know about the existence
Packit 345191
 * of the tcache at all.
Packit 345191
 */
Packit 345191
Packit 345191
Packit 345191
/*
Packit 345191
 * The count of the number of cached allocations in a bin.  We make this signed
Packit 345191
 * so that negative numbers can encode "invalid" states (e.g. a low water mark
Packit 345191
 * of -1 for a cache that has been depleted).
Packit 345191
 */
Packit 345191
typedef int32_t cache_bin_sz_t;
Packit 345191
Packit 345191
typedef struct cache_bin_stats_s cache_bin_stats_t;
Packit 345191
struct cache_bin_stats_s {
Packit 345191
	/*
Packit 345191
	 * Number of allocation requests that corresponded to the size of this
Packit 345191
	 * bin.
Packit 345191
	 */
Packit 345191
	uint64_t nrequests;
Packit 345191
};
Packit 345191
Packit 345191
/*
Packit 345191
 * Read-only information associated with each element of tcache_t's tbins array
Packit 345191
 * is stored separately, mainly to reduce memory usage.
Packit 345191
 */
Packit 345191
typedef struct cache_bin_info_s cache_bin_info_t;
Packit 345191
struct cache_bin_info_s {
Packit 345191
	/* Upper limit on ncached. */
Packit 345191
	cache_bin_sz_t ncached_max;
Packit 345191
};
Packit 345191
Packit 345191
typedef struct cache_bin_s cache_bin_t;
Packit 345191
struct cache_bin_s {
Packit 345191
	/* Min # cached since last GC. */
Packit 345191
	cache_bin_sz_t low_water;
Packit 345191
	/* # of cached objects. */
Packit 345191
	cache_bin_sz_t ncached;
Packit 345191
	/*
Packit 345191
	 * ncached and stats are both modified frequently.  Let's keep them
Packit 345191
	 * close so that they have a higher chance of being on the same
Packit 345191
	 * cacheline, thus less write-backs.
Packit 345191
	 */
Packit 345191
	cache_bin_stats_t tstats;
Packit 345191
	/*
Packit 345191
	 * Stack of available objects.
Packit 345191
	 *
Packit 345191
	 * To make use of adjacent cacheline prefetch, the items in the avail
Packit 345191
	 * stack goes to higher address for newer allocations.  avail points
Packit 345191
	 * just above the available space, which means that
Packit 345191
	 * avail[-ncached, ... -1] are available items and the lowest item will
Packit 345191
	 * be allocated first.
Packit 345191
	 */
Packit 345191
	void **avail;
Packit 345191
};
Packit 345191
Packit 345191
typedef struct cache_bin_array_descriptor_s cache_bin_array_descriptor_t;
Packit 345191
struct cache_bin_array_descriptor_s {
Packit 345191
	/*
Packit 345191
	 * The arena keeps a list of the cache bins associated with it, for
Packit 345191
	 * stats collection.
Packit 345191
	 */
Packit 345191
	ql_elm(cache_bin_array_descriptor_t) link;
Packit 345191
	/* Pointers to the tcache bins. */
Packit 345191
	cache_bin_t *bins_small;
Packit 345191
	cache_bin_t *bins_large;
Packit 345191
};
Packit 345191
Packit 345191
static inline void
Packit 345191
cache_bin_array_descriptor_init(cache_bin_array_descriptor_t *descriptor,
Packit 345191
    cache_bin_t *bins_small, cache_bin_t *bins_large) {
Packit 345191
	ql_elm_new(descriptor, link);
Packit 345191
	descriptor->bins_small = bins_small;
Packit 345191
	descriptor->bins_large = bins_large;
Packit 345191
}
Packit 345191
Packit 345191
JEMALLOC_ALWAYS_INLINE void *
Packit 345191
cache_bin_alloc_easy(cache_bin_t *bin, bool *success) {
Packit 345191
	void *ret;
Packit 345191
Packit 345191
	bin->ncached--;
Packit 345191
Packit 345191
	/*
Packit 345191
	 * Check for both bin->ncached == 0 and ncached < low_water
Packit 345191
	 * in a single branch.
Packit 345191
	 */
Packit 345191
	if (unlikely(bin->ncached <= bin->low_water)) {
Packit 345191
		bin->low_water = bin->ncached;
Packit 345191
		if (bin->ncached == -1) {
Packit 345191
			bin->ncached = 0;
Packit 345191
			*success = false;
Packit 345191
			return NULL;
Packit 345191
		}
Packit 345191
	}
Packit 345191
Packit 345191
	/*
Packit 345191
	 * success (instead of ret) should be checked upon the return of this
Packit 345191
	 * function.  We avoid checking (ret == NULL) because there is never a
Packit 345191
	 * null stored on the avail stack (which is unknown to the compiler),
Packit 345191
	 * and eagerly checking ret would cause pipeline stall (waiting for the
Packit 345191
	 * cacheline).
Packit 345191
	 */
Packit 345191
	*success = true;
Packit 345191
	ret = *(bin->avail - (bin->ncached + 1));
Packit 345191
Packit 345191
	return ret;
Packit 345191
}
Packit 345191
Packit 345191
JEMALLOC_ALWAYS_INLINE bool
Packit 345191
cache_bin_dalloc_easy(cache_bin_t *bin, cache_bin_info_t *bin_info, void *ptr) {
Packit 345191
	if (unlikely(bin->ncached == bin_info->ncached_max)) {
Packit 345191
		return false;
Packit 345191
	}
Packit 345191
	assert(bin->ncached < bin_info->ncached_max);
Packit 345191
	bin->ncached++;
Packit 345191
	*(bin->avail - bin->ncached) = ptr;
Packit 345191
Packit 345191
	return true;
Packit 345191
}
Packit 345191
Packit 345191
#endif /* JEMALLOC_INTERNAL_CACHE_BIN_H */