1 | #ifndef JEMALLOC_INTERNAL_CACHE_BIN_H |
2 | #define JEMALLOC_INTERNAL_CACHE_BIN_H |
3 | |
4 | #include "jemalloc/internal/ql.h" |
5 | |
6 | /* |
7 | * The cache_bins are the mechanism that the tcache and the arena use to |
8 | * communicate. The tcache fills from and flushes to the arena by passing a |
9 | * cache_bin_t to fill/flush. When the arena needs to pull stats from the |
10 | * tcaches associated with it, it does so by iterating over its |
11 | * cache_bin_array_descriptor_t objects and reading out per-bin stats it |
12 | * contains. This makes it so that the arena need not know about the existence |
13 | * of the tcache at all. |
14 | */ |
15 | |
16 | |
17 | /* |
18 | * The count of the number of cached allocations in a bin. We make this signed |
19 | * so that negative numbers can encode "invalid" states (e.g. a low water mark |
20 | * of -1 for a cache that has been depleted). |
21 | */ |
22 | typedef int32_t cache_bin_sz_t; |
23 | |
24 | typedef struct cache_bin_stats_s cache_bin_stats_t; |
25 | struct cache_bin_stats_s { |
26 | /* |
27 | * Number of allocation requests that corresponded to the size of this |
28 | * bin. |
29 | */ |
30 | uint64_t nrequests; |
31 | }; |
32 | |
33 | /* |
34 | * Read-only information associated with each element of tcache_t's tbins array |
35 | * is stored separately, mainly to reduce memory usage. |
36 | */ |
37 | typedef struct cache_bin_info_s cache_bin_info_t; |
38 | struct cache_bin_info_s { |
39 | /* Upper limit on ncached. */ |
40 | cache_bin_sz_t ncached_max; |
41 | }; |
42 | |
43 | typedef struct cache_bin_s cache_bin_t; |
44 | struct cache_bin_s { |
45 | /* Min # cached since last GC. */ |
46 | cache_bin_sz_t low_water; |
47 | /* # of cached objects. */ |
48 | cache_bin_sz_t ncached; |
49 | /* |
50 | * ncached and stats are both modified frequently. Let's keep them |
51 | * close so that they have a higher chance of being on the same |
52 | * cacheline, thus less write-backs. |
53 | */ |
54 | cache_bin_stats_t tstats; |
55 | /* |
56 | * Stack of available objects. |
57 | * |
58 | * To make use of adjacent cacheline prefetch, the items in the avail |
59 | * stack goes to higher address for newer allocations. avail points |
60 | * just above the available space, which means that |
61 | * avail[-ncached, ... -1] are available items and the lowest item will |
62 | * be allocated first. |
63 | */ |
64 | void **avail; |
65 | }; |
66 | |
67 | typedef struct cache_bin_array_descriptor_s cache_bin_array_descriptor_t; |
68 | struct cache_bin_array_descriptor_s { |
69 | /* |
70 | * The arena keeps a list of the cache bins associated with it, for |
71 | * stats collection. |
72 | */ |
73 | ql_elm(cache_bin_array_descriptor_t) link; |
74 | /* Pointers to the tcache bins. */ |
75 | cache_bin_t *bins_small; |
76 | cache_bin_t *bins_large; |
77 | }; |
78 | |
79 | static inline void |
80 | cache_bin_array_descriptor_init(cache_bin_array_descriptor_t *descriptor, |
81 | cache_bin_t *bins_small, cache_bin_t *bins_large) { |
82 | ql_elm_new(descriptor, link); |
83 | descriptor->bins_small = bins_small; |
84 | descriptor->bins_large = bins_large; |
85 | } |
86 | |
87 | JEMALLOC_ALWAYS_INLINE void * |
88 | cache_bin_alloc_easy(cache_bin_t *bin, bool *success) { |
89 | void *ret; |
90 | |
91 | bin->ncached--; |
92 | |
93 | /* |
94 | * Check for both bin->ncached == 0 and ncached < low_water |
95 | * in a single branch. |
96 | */ |
97 | if (unlikely(bin->ncached <= bin->low_water)) { |
98 | bin->low_water = bin->ncached; |
99 | if (bin->ncached == -1) { |
100 | bin->ncached = 0; |
101 | *success = false; |
102 | return NULL; |
103 | } |
104 | } |
105 | |
106 | /* |
107 | * success (instead of ret) should be checked upon the return of this |
108 | * function. We avoid checking (ret == NULL) because there is never a |
109 | * null stored on the avail stack (which is unknown to the compiler), |
110 | * and eagerly checking ret would cause pipeline stall (waiting for the |
111 | * cacheline). |
112 | */ |
113 | *success = true; |
114 | ret = *(bin->avail - (bin->ncached + 1)); |
115 | |
116 | return ret; |
117 | } |
118 | |
119 | #endif /* JEMALLOC_INTERNAL_CACHE_BIN_H */ |
120 | |