1b7eaed25SJason Evans #ifndef JEMALLOC_INTERNAL_ARENA_INLINES_B_H
2b7eaed25SJason Evans #define JEMALLOC_INTERNAL_ARENA_INLINES_B_H
3b7eaed25SJason Evans
4b7eaed25SJason Evans #include "jemalloc/internal/jemalloc_internal_types.h"
5b7eaed25SJason Evans #include "jemalloc/internal/mutex.h"
6b7eaed25SJason Evans #include "jemalloc/internal/rtree.h"
7c5ad8142SEric van Gyzen #include "jemalloc/internal/sc.h"
8b7eaed25SJason Evans #include "jemalloc/internal/sz.h"
9b7eaed25SJason Evans #include "jemalloc/internal/ticker.h"
10b7eaed25SJason Evans
11c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE bool
arena_has_default_hooks(arena_t * arena)12c5ad8142SEric van Gyzen arena_has_default_hooks(arena_t *arena) {
13c5ad8142SEric van Gyzen return (extent_hooks_get(arena) == &extent_hooks_default);
14c5ad8142SEric van Gyzen }
15c5ad8142SEric van Gyzen
16c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE arena_t *
arena_choose_maybe_huge(tsd_t * tsd,arena_t * arena,size_t size)17c5ad8142SEric van Gyzen arena_choose_maybe_huge(tsd_t *tsd, arena_t *arena, size_t size) {
18c5ad8142SEric van Gyzen if (arena != NULL) {
19c5ad8142SEric van Gyzen return arena;
20c5ad8142SEric van Gyzen }
21c5ad8142SEric van Gyzen
22c5ad8142SEric van Gyzen /*
23c5ad8142SEric van Gyzen * For huge allocations, use the dedicated huge arena if both are true:
24c5ad8142SEric van Gyzen * 1) is using auto arena selection (i.e. arena == NULL), and 2) the
25c5ad8142SEric van Gyzen * thread is not assigned to a manual arena.
26c5ad8142SEric van Gyzen */
27c5ad8142SEric van Gyzen if (unlikely(size >= oversize_threshold)) {
28c5ad8142SEric van Gyzen arena_t *tsd_arena = tsd_arena_get(tsd);
29c5ad8142SEric van Gyzen if (tsd_arena == NULL || arena_is_auto(tsd_arena)) {
30c5ad8142SEric van Gyzen return arena_choose_huge(tsd);
31c5ad8142SEric van Gyzen }
32c5ad8142SEric van Gyzen }
33c5ad8142SEric van Gyzen
34c5ad8142SEric van Gyzen return arena_choose(tsd, NULL);
35c5ad8142SEric van Gyzen }
36c5ad8142SEric van Gyzen
37b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE prof_tctx_t *
arena_prof_tctx_get(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx)38b7eaed25SJason Evans arena_prof_tctx_get(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx) {
39b7eaed25SJason Evans cassert(config_prof);
40b7eaed25SJason Evans assert(ptr != NULL);
41b7eaed25SJason Evans
42b7eaed25SJason Evans /* Static check. */
43b7eaed25SJason Evans if (alloc_ctx == NULL) {
44b7eaed25SJason Evans const extent_t *extent = iealloc(tsdn, ptr);
45b7eaed25SJason Evans if (unlikely(!extent_slab_get(extent))) {
46b7eaed25SJason Evans return large_prof_tctx_get(tsdn, extent);
47b7eaed25SJason Evans }
48b7eaed25SJason Evans } else {
49b7eaed25SJason Evans if (unlikely(!alloc_ctx->slab)) {
50b7eaed25SJason Evans return large_prof_tctx_get(tsdn, iealloc(tsdn, ptr));
51b7eaed25SJason Evans }
52b7eaed25SJason Evans }
53b7eaed25SJason Evans return (prof_tctx_t *)(uintptr_t)1U;
54b7eaed25SJason Evans }
55b7eaed25SJason Evans
56b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_prof_tctx_set(tsdn_t * tsdn,const void * ptr,size_t usize,alloc_ctx_t * alloc_ctx,prof_tctx_t * tctx)57c5ad8142SEric van Gyzen arena_prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize,
58b7eaed25SJason Evans alloc_ctx_t *alloc_ctx, prof_tctx_t *tctx) {
59b7eaed25SJason Evans cassert(config_prof);
60b7eaed25SJason Evans assert(ptr != NULL);
61b7eaed25SJason Evans
62b7eaed25SJason Evans /* Static check. */
63b7eaed25SJason Evans if (alloc_ctx == NULL) {
64b7eaed25SJason Evans extent_t *extent = iealloc(tsdn, ptr);
65b7eaed25SJason Evans if (unlikely(!extent_slab_get(extent))) {
66b7eaed25SJason Evans large_prof_tctx_set(tsdn, extent, tctx);
67b7eaed25SJason Evans }
68b7eaed25SJason Evans } else {
69b7eaed25SJason Evans if (unlikely(!alloc_ctx->slab)) {
70b7eaed25SJason Evans large_prof_tctx_set(tsdn, iealloc(tsdn, ptr), tctx);
71b7eaed25SJason Evans }
72b7eaed25SJason Evans }
73b7eaed25SJason Evans }
74b7eaed25SJason Evans
75b7eaed25SJason Evans static inline void
arena_prof_tctx_reset(tsdn_t * tsdn,const void * ptr,prof_tctx_t * tctx)76c5ad8142SEric van Gyzen arena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) {
77b7eaed25SJason Evans cassert(config_prof);
78b7eaed25SJason Evans assert(ptr != NULL);
79b7eaed25SJason Evans
80b7eaed25SJason Evans extent_t *extent = iealloc(tsdn, ptr);
81b7eaed25SJason Evans assert(!extent_slab_get(extent));
82b7eaed25SJason Evans
83b7eaed25SJason Evans large_prof_tctx_reset(tsdn, extent);
84b7eaed25SJason Evans }
85b7eaed25SJason Evans
86c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE nstime_t
arena_prof_alloc_time_get(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx)87c5ad8142SEric van Gyzen arena_prof_alloc_time_get(tsdn_t *tsdn, const void *ptr,
88c5ad8142SEric van Gyzen alloc_ctx_t *alloc_ctx) {
89c5ad8142SEric van Gyzen cassert(config_prof);
90c5ad8142SEric van Gyzen assert(ptr != NULL);
91c5ad8142SEric van Gyzen
92c5ad8142SEric van Gyzen extent_t *extent = iealloc(tsdn, ptr);
93c5ad8142SEric van Gyzen /*
94c5ad8142SEric van Gyzen * Unlike arena_prof_prof_tctx_{get, set}, we only call this once we're
95c5ad8142SEric van Gyzen * sure we have a sampled allocation.
96c5ad8142SEric van Gyzen */
97c5ad8142SEric van Gyzen assert(!extent_slab_get(extent));
98c5ad8142SEric van Gyzen return large_prof_alloc_time_get(extent);
99c5ad8142SEric van Gyzen }
100c5ad8142SEric van Gyzen
101c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_prof_alloc_time_set(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx,nstime_t t)102c5ad8142SEric van Gyzen arena_prof_alloc_time_set(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx,
103c5ad8142SEric van Gyzen nstime_t t) {
104c5ad8142SEric van Gyzen cassert(config_prof);
105c5ad8142SEric van Gyzen assert(ptr != NULL);
106c5ad8142SEric van Gyzen
107c5ad8142SEric van Gyzen extent_t *extent = iealloc(tsdn, ptr);
108c5ad8142SEric van Gyzen assert(!extent_slab_get(extent));
109c5ad8142SEric van Gyzen large_prof_alloc_time_set(extent, t);
110c5ad8142SEric van Gyzen }
111c5ad8142SEric van Gyzen
112b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_decay_ticks(tsdn_t * tsdn,arena_t * arena,unsigned nticks)113b7eaed25SJason Evans arena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks) {
114b7eaed25SJason Evans tsd_t *tsd;
115b7eaed25SJason Evans ticker_t *decay_ticker;
116b7eaed25SJason Evans
117b7eaed25SJason Evans if (unlikely(tsdn_null(tsdn))) {
118b7eaed25SJason Evans return;
119b7eaed25SJason Evans }
120b7eaed25SJason Evans tsd = tsdn_tsd(tsdn);
121b7eaed25SJason Evans decay_ticker = decay_ticker_get(tsd, arena_ind_get(arena));
122b7eaed25SJason Evans if (unlikely(decay_ticker == NULL)) {
123b7eaed25SJason Evans return;
124b7eaed25SJason Evans }
125b7eaed25SJason Evans if (unlikely(ticker_ticks(decay_ticker, nticks))) {
126b7eaed25SJason Evans arena_decay(tsdn, arena, false, false);
127b7eaed25SJason Evans }
128b7eaed25SJason Evans }
129b7eaed25SJason Evans
130b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_decay_tick(tsdn_t * tsdn,arena_t * arena)131b7eaed25SJason Evans arena_decay_tick(tsdn_t *tsdn, arena_t *arena) {
132b7eaed25SJason Evans malloc_mutex_assert_not_owner(tsdn, &arena->decay_dirty.mtx);
133b7eaed25SJason Evans malloc_mutex_assert_not_owner(tsdn, &arena->decay_muzzy.mtx);
134b7eaed25SJason Evans
135b7eaed25SJason Evans arena_decay_ticks(tsdn, arena, 1);
136b7eaed25SJason Evans }
137b7eaed25SJason Evans
138c5ad8142SEric van Gyzen /* Purge a single extent to retained / unmapped directly. */
139c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_decay_extent(tsdn_t * tsdn,arena_t * arena,extent_hooks_t ** r_extent_hooks,extent_t * extent)140c5ad8142SEric van Gyzen arena_decay_extent(tsdn_t *tsdn,arena_t *arena, extent_hooks_t **r_extent_hooks,
141c5ad8142SEric van Gyzen extent_t *extent) {
142c5ad8142SEric van Gyzen size_t extent_size = extent_size_get(extent);
143c5ad8142SEric van Gyzen extent_dalloc_wrapper(tsdn, arena,
144c5ad8142SEric van Gyzen r_extent_hooks, extent);
145c5ad8142SEric van Gyzen if (config_stats) {
146c5ad8142SEric van Gyzen /* Update stats accordingly. */
147c5ad8142SEric van Gyzen arena_stats_lock(tsdn, &arena->stats);
148c5ad8142SEric van Gyzen arena_stats_add_u64(tsdn, &arena->stats,
149c5ad8142SEric van Gyzen &arena->decay_dirty.stats->nmadvise, 1);
150c5ad8142SEric van Gyzen arena_stats_add_u64(tsdn, &arena->stats,
151c5ad8142SEric van Gyzen &arena->decay_dirty.stats->purged, extent_size >> LG_PAGE);
152c5ad8142SEric van Gyzen arena_stats_sub_zu(tsdn, &arena->stats, &arena->stats.mapped,
153c5ad8142SEric van Gyzen extent_size);
154c5ad8142SEric van Gyzen arena_stats_unlock(tsdn, &arena->stats);
155c5ad8142SEric van Gyzen }
156c5ad8142SEric van Gyzen }
157c5ad8142SEric van Gyzen
158b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void *
arena_malloc(tsdn_t * tsdn,arena_t * arena,size_t size,szind_t ind,bool zero,tcache_t * tcache,bool slow_path)159b7eaed25SJason Evans arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero,
160b7eaed25SJason Evans tcache_t *tcache, bool slow_path) {
161b7eaed25SJason Evans assert(!tsdn_null(tsdn) || tcache == NULL);
162b7eaed25SJason Evans
163b7eaed25SJason Evans if (likely(tcache != NULL)) {
164c5ad8142SEric van Gyzen if (likely(size <= SC_SMALL_MAXCLASS)) {
165b7eaed25SJason Evans return tcache_alloc_small(tsdn_tsd(tsdn), arena,
166b7eaed25SJason Evans tcache, size, ind, zero, slow_path);
167b7eaed25SJason Evans }
168b7eaed25SJason Evans if (likely(size <= tcache_maxclass)) {
169b7eaed25SJason Evans return tcache_alloc_large(tsdn_tsd(tsdn), arena,
170b7eaed25SJason Evans tcache, size, ind, zero, slow_path);
171b7eaed25SJason Evans }
172b7eaed25SJason Evans /* (size > tcache_maxclass) case falls through. */
173b7eaed25SJason Evans assert(size > tcache_maxclass);
174b7eaed25SJason Evans }
175b7eaed25SJason Evans
176b7eaed25SJason Evans return arena_malloc_hard(tsdn, arena, size, ind, zero);
177b7eaed25SJason Evans }
178b7eaed25SJason Evans
179b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE arena_t *
arena_aalloc(tsdn_t * tsdn,const void * ptr)180b7eaed25SJason Evans arena_aalloc(tsdn_t *tsdn, const void *ptr) {
181b7eaed25SJason Evans return extent_arena_get(iealloc(tsdn, ptr));
182b7eaed25SJason Evans }
183b7eaed25SJason Evans
184b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE size_t
arena_salloc(tsdn_t * tsdn,const void * ptr)185b7eaed25SJason Evans arena_salloc(tsdn_t *tsdn, const void *ptr) {
186b7eaed25SJason Evans assert(ptr != NULL);
187b7eaed25SJason Evans
188b7eaed25SJason Evans rtree_ctx_t rtree_ctx_fallback;
189b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
190b7eaed25SJason Evans
191b7eaed25SJason Evans szind_t szind = rtree_szind_read(tsdn, &extents_rtree, rtree_ctx,
192b7eaed25SJason Evans (uintptr_t)ptr, true);
193c5ad8142SEric van Gyzen assert(szind != SC_NSIZES);
194b7eaed25SJason Evans
195b7eaed25SJason Evans return sz_index2size(szind);
196b7eaed25SJason Evans }
197b7eaed25SJason Evans
198b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE size_t
arena_vsalloc(tsdn_t * tsdn,const void * ptr)199b7eaed25SJason Evans arena_vsalloc(tsdn_t *tsdn, const void *ptr) {
200b7eaed25SJason Evans /*
201b7eaed25SJason Evans * Return 0 if ptr is not within an extent managed by jemalloc. This
202b7eaed25SJason Evans * function has two extra costs relative to isalloc():
203b7eaed25SJason Evans * - The rtree calls cannot claim to be dependent lookups, which induces
204b7eaed25SJason Evans * rtree lookup load dependencies.
205b7eaed25SJason Evans * - The lookup may fail, so there is an extra branch to check for
206b7eaed25SJason Evans * failure.
207b7eaed25SJason Evans */
208b7eaed25SJason Evans
209b7eaed25SJason Evans rtree_ctx_t rtree_ctx_fallback;
210b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
211b7eaed25SJason Evans
212b7eaed25SJason Evans extent_t *extent;
213b7eaed25SJason Evans szind_t szind;
214b7eaed25SJason Evans if (rtree_extent_szind_read(tsdn, &extents_rtree, rtree_ctx,
215b7eaed25SJason Evans (uintptr_t)ptr, false, &extent, &szind)) {
216b7eaed25SJason Evans return 0;
217b7eaed25SJason Evans }
218b7eaed25SJason Evans
219b7eaed25SJason Evans if (extent == NULL) {
220b7eaed25SJason Evans return 0;
221b7eaed25SJason Evans }
222b7eaed25SJason Evans assert(extent_state_get(extent) == extent_state_active);
223b7eaed25SJason Evans /* Only slab members should be looked up via interior pointers. */
224b7eaed25SJason Evans assert(extent_addr_get(extent) == ptr || extent_slab_get(extent));
225b7eaed25SJason Evans
226c5ad8142SEric van Gyzen assert(szind != SC_NSIZES);
227b7eaed25SJason Evans
228b7eaed25SJason Evans return sz_index2size(szind);
229b7eaed25SJason Evans }
230b7eaed25SJason Evans
231b7eaed25SJason Evans static inline void
arena_dalloc_large_no_tcache(tsdn_t * tsdn,void * ptr,szind_t szind)232c5ad8142SEric van Gyzen arena_dalloc_large_no_tcache(tsdn_t *tsdn, void *ptr, szind_t szind) {
233c5ad8142SEric van Gyzen if (config_prof && unlikely(szind < SC_NBINS)) {
234c5ad8142SEric van Gyzen arena_dalloc_promoted(tsdn, ptr, NULL, true);
235c5ad8142SEric van Gyzen } else {
236c5ad8142SEric van Gyzen extent_t *extent = iealloc(tsdn, ptr);
237c5ad8142SEric van Gyzen large_dalloc(tsdn, extent);
238c5ad8142SEric van Gyzen }
239c5ad8142SEric van Gyzen }
240c5ad8142SEric van Gyzen
241c5ad8142SEric van Gyzen static inline void
arena_dalloc_no_tcache(tsdn_t * tsdn,void * ptr)242b7eaed25SJason Evans arena_dalloc_no_tcache(tsdn_t *tsdn, void *ptr) {
243b7eaed25SJason Evans assert(ptr != NULL);
244b7eaed25SJason Evans
245b7eaed25SJason Evans rtree_ctx_t rtree_ctx_fallback;
246b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
247b7eaed25SJason Evans
248b7eaed25SJason Evans szind_t szind;
249b7eaed25SJason Evans bool slab;
250b7eaed25SJason Evans rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr,
251b7eaed25SJason Evans true, &szind, &slab);
252b7eaed25SJason Evans
253b7eaed25SJason Evans if (config_debug) {
254b7eaed25SJason Evans extent_t *extent = rtree_extent_read(tsdn, &extents_rtree,
255b7eaed25SJason Evans rtree_ctx, (uintptr_t)ptr, true);
256b7eaed25SJason Evans assert(szind == extent_szind_get(extent));
257c5ad8142SEric van Gyzen assert(szind < SC_NSIZES);
258b7eaed25SJason Evans assert(slab == extent_slab_get(extent));
259b7eaed25SJason Evans }
260b7eaed25SJason Evans
261b7eaed25SJason Evans if (likely(slab)) {
262b7eaed25SJason Evans /* Small allocation. */
263b7eaed25SJason Evans arena_dalloc_small(tsdn, ptr);
264b7eaed25SJason Evans } else {
265c5ad8142SEric van Gyzen arena_dalloc_large_no_tcache(tsdn, ptr, szind);
266c5ad8142SEric van Gyzen }
267c5ad8142SEric van Gyzen }
268c5ad8142SEric van Gyzen
269c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_dalloc_large(tsdn_t * tsdn,void * ptr,tcache_t * tcache,szind_t szind,bool slow_path)270c5ad8142SEric van Gyzen arena_dalloc_large(tsdn_t *tsdn, void *ptr, tcache_t *tcache, szind_t szind,
271c5ad8142SEric van Gyzen bool slow_path) {
272c5ad8142SEric van Gyzen if (szind < nhbins) {
273c5ad8142SEric van Gyzen if (config_prof && unlikely(szind < SC_NBINS)) {
274c5ad8142SEric van Gyzen arena_dalloc_promoted(tsdn, ptr, tcache, slow_path);
275c5ad8142SEric van Gyzen } else {
276c5ad8142SEric van Gyzen tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, szind,
277c5ad8142SEric van Gyzen slow_path);
278c5ad8142SEric van Gyzen }
279c5ad8142SEric van Gyzen } else {
280b7eaed25SJason Evans extent_t *extent = iealloc(tsdn, ptr);
281b7eaed25SJason Evans large_dalloc(tsdn, extent);
282b7eaed25SJason Evans }
283b7eaed25SJason Evans }
284b7eaed25SJason Evans
285b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_dalloc(tsdn_t * tsdn,void * ptr,tcache_t * tcache,alloc_ctx_t * alloc_ctx,bool slow_path)286b7eaed25SJason Evans arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache,
287b7eaed25SJason Evans alloc_ctx_t *alloc_ctx, bool slow_path) {
288b7eaed25SJason Evans assert(!tsdn_null(tsdn) || tcache == NULL);
289b7eaed25SJason Evans assert(ptr != NULL);
290b7eaed25SJason Evans
291b7eaed25SJason Evans if (unlikely(tcache == NULL)) {
292b7eaed25SJason Evans arena_dalloc_no_tcache(tsdn, ptr);
293b7eaed25SJason Evans return;
294b7eaed25SJason Evans }
295b7eaed25SJason Evans
296b7eaed25SJason Evans szind_t szind;
297b7eaed25SJason Evans bool slab;
298b7eaed25SJason Evans rtree_ctx_t *rtree_ctx;
299b7eaed25SJason Evans if (alloc_ctx != NULL) {
300b7eaed25SJason Evans szind = alloc_ctx->szind;
301b7eaed25SJason Evans slab = alloc_ctx->slab;
302c5ad8142SEric van Gyzen assert(szind != SC_NSIZES);
303b7eaed25SJason Evans } else {
304b7eaed25SJason Evans rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
305b7eaed25SJason Evans rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
306b7eaed25SJason Evans (uintptr_t)ptr, true, &szind, &slab);
307b7eaed25SJason Evans }
308b7eaed25SJason Evans
309b7eaed25SJason Evans if (config_debug) {
310b7eaed25SJason Evans rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
311b7eaed25SJason Evans extent_t *extent = rtree_extent_read(tsdn, &extents_rtree,
312b7eaed25SJason Evans rtree_ctx, (uintptr_t)ptr, true);
313b7eaed25SJason Evans assert(szind == extent_szind_get(extent));
314c5ad8142SEric van Gyzen assert(szind < SC_NSIZES);
315b7eaed25SJason Evans assert(slab == extent_slab_get(extent));
316b7eaed25SJason Evans }
317b7eaed25SJason Evans
318b7eaed25SJason Evans if (likely(slab)) {
319b7eaed25SJason Evans /* Small allocation. */
320b7eaed25SJason Evans tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind,
321b7eaed25SJason Evans slow_path);
322b7eaed25SJason Evans } else {
323c5ad8142SEric van Gyzen arena_dalloc_large(tsdn, ptr, tcache, szind, slow_path);
324b7eaed25SJason Evans }
325b7eaed25SJason Evans }
326b7eaed25SJason Evans
327b7eaed25SJason Evans static inline void
arena_sdalloc_no_tcache(tsdn_t * tsdn,void * ptr,size_t size)328b7eaed25SJason Evans arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) {
329b7eaed25SJason Evans assert(ptr != NULL);
330c5ad8142SEric van Gyzen assert(size <= SC_LARGE_MAXCLASS);
331b7eaed25SJason Evans
332b7eaed25SJason Evans szind_t szind;
333b7eaed25SJason Evans bool slab;
334b7eaed25SJason Evans if (!config_prof || !opt_prof) {
335b7eaed25SJason Evans /*
336b7eaed25SJason Evans * There is no risk of being confused by a promoted sampled
337b7eaed25SJason Evans * object, so base szind and slab on the given size.
338b7eaed25SJason Evans */
339b7eaed25SJason Evans szind = sz_size2index(size);
340c5ad8142SEric van Gyzen slab = (szind < SC_NBINS);
341b7eaed25SJason Evans }
342b7eaed25SJason Evans
343b7eaed25SJason Evans if ((config_prof && opt_prof) || config_debug) {
344b7eaed25SJason Evans rtree_ctx_t rtree_ctx_fallback;
345b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn,
346b7eaed25SJason Evans &rtree_ctx_fallback);
347b7eaed25SJason Evans
348b7eaed25SJason Evans rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
349b7eaed25SJason Evans (uintptr_t)ptr, true, &szind, &slab);
350b7eaed25SJason Evans
351b7eaed25SJason Evans assert(szind == sz_size2index(size));
352c5ad8142SEric van Gyzen assert((config_prof && opt_prof) || slab == (szind < SC_NBINS));
353b7eaed25SJason Evans
354b7eaed25SJason Evans if (config_debug) {
355b7eaed25SJason Evans extent_t *extent = rtree_extent_read(tsdn,
356b7eaed25SJason Evans &extents_rtree, rtree_ctx, (uintptr_t)ptr, true);
357b7eaed25SJason Evans assert(szind == extent_szind_get(extent));
358b7eaed25SJason Evans assert(slab == extent_slab_get(extent));
359b7eaed25SJason Evans }
360b7eaed25SJason Evans }
361b7eaed25SJason Evans
362b7eaed25SJason Evans if (likely(slab)) {
363b7eaed25SJason Evans /* Small allocation. */
364b7eaed25SJason Evans arena_dalloc_small(tsdn, ptr);
365b7eaed25SJason Evans } else {
366c5ad8142SEric van Gyzen arena_dalloc_large_no_tcache(tsdn, ptr, szind);
367b7eaed25SJason Evans }
368b7eaed25SJason Evans }
369b7eaed25SJason Evans
370b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_sdalloc(tsdn_t * tsdn,void * ptr,size_t size,tcache_t * tcache,alloc_ctx_t * alloc_ctx,bool slow_path)371b7eaed25SJason Evans arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,
372b7eaed25SJason Evans alloc_ctx_t *alloc_ctx, bool slow_path) {
373b7eaed25SJason Evans assert(!tsdn_null(tsdn) || tcache == NULL);
374b7eaed25SJason Evans assert(ptr != NULL);
375c5ad8142SEric van Gyzen assert(size <= SC_LARGE_MAXCLASS);
376b7eaed25SJason Evans
377b7eaed25SJason Evans if (unlikely(tcache == NULL)) {
378b7eaed25SJason Evans arena_sdalloc_no_tcache(tsdn, ptr, size);
379b7eaed25SJason Evans return;
380b7eaed25SJason Evans }
381b7eaed25SJason Evans
382b7eaed25SJason Evans szind_t szind;
383b7eaed25SJason Evans bool slab;
384c5ad8142SEric van Gyzen alloc_ctx_t local_ctx;
385b7eaed25SJason Evans if (config_prof && opt_prof) {
386b7eaed25SJason Evans if (alloc_ctx == NULL) {
387b7eaed25SJason Evans /* Uncommon case and should be a static check. */
388b7eaed25SJason Evans rtree_ctx_t rtree_ctx_fallback;
389b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn,
390b7eaed25SJason Evans &rtree_ctx_fallback);
391b7eaed25SJason Evans rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
392b7eaed25SJason Evans (uintptr_t)ptr, true, &local_ctx.szind,
393b7eaed25SJason Evans &local_ctx.slab);
394b7eaed25SJason Evans assert(local_ctx.szind == sz_size2index(size));
395b7eaed25SJason Evans alloc_ctx = &local_ctx;
396b7eaed25SJason Evans }
397b7eaed25SJason Evans slab = alloc_ctx->slab;
398b7eaed25SJason Evans szind = alloc_ctx->szind;
399b7eaed25SJason Evans } else {
400b7eaed25SJason Evans /*
401b7eaed25SJason Evans * There is no risk of being confused by a promoted sampled
402b7eaed25SJason Evans * object, so base szind and slab on the given size.
403b7eaed25SJason Evans */
404b7eaed25SJason Evans szind = sz_size2index(size);
405c5ad8142SEric van Gyzen slab = (szind < SC_NBINS);
406b7eaed25SJason Evans }
407b7eaed25SJason Evans
408b7eaed25SJason Evans if (config_debug) {
409b7eaed25SJason Evans rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
410b7eaed25SJason Evans rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
411b7eaed25SJason Evans (uintptr_t)ptr, true, &szind, &slab);
412b7eaed25SJason Evans extent_t *extent = rtree_extent_read(tsdn,
413b7eaed25SJason Evans &extents_rtree, rtree_ctx, (uintptr_t)ptr, true);
414b7eaed25SJason Evans assert(szind == extent_szind_get(extent));
415b7eaed25SJason Evans assert(slab == extent_slab_get(extent));
416b7eaed25SJason Evans }
417b7eaed25SJason Evans
418b7eaed25SJason Evans if (likely(slab)) {
419b7eaed25SJason Evans /* Small allocation. */
420b7eaed25SJason Evans tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind,
421b7eaed25SJason Evans slow_path);
422b7eaed25SJason Evans } else {
423c5ad8142SEric van Gyzen arena_dalloc_large(tsdn, ptr, tcache, szind, slow_path);
424b7eaed25SJason Evans }
425b7eaed25SJason Evans }
426b7eaed25SJason Evans
427b7eaed25SJason Evans #endif /* JEMALLOC_INTERNAL_ARENA_INLINES_B_H */
428