|
5 | 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
6 | 6 | */
|
7 | 7 |
|
8 |
| -#include <assert.h> |
9 |
| -#include <errno.h> |
10 |
| -#include <stdbool.h> |
11 |
| -#include <stdlib.h> |
12 |
| -#include <string.h> |
13 |
| - |
14 |
| -#include <umf/memory_pool.h> |
15 |
| -#include <umf/memory_pool_ops.h> |
16 |
| -#include <umf/memory_provider.h> |
17 |
| -#include <umf/pools/pool_disjoint.h> |
18 |
| - |
19 |
| -#include "critnib/critnib.h" |
20 |
| -#include "uthash/utlist.h" |
21 |
| - |
22 |
| -#include "base_alloc_global.h" |
23 |
| -#include "provider_tracking.h" |
24 |
| -#include "utils_common.h" |
25 |
| -#include "utils_concurrency.h" |
26 |
| -#include "utils_log.h" |
27 |
| -#include "utils_math.h" |
28 |
| -#include "utils_sanitizers.h" |
29 |
| - |
30 |
| -typedef struct bucket_t bucket_t; |
31 |
| -typedef struct slab_t slab_t; |
32 |
| -typedef struct slab_list_item_t slab_list_item_t; |
33 |
| -typedef struct disjoint_pool_t disjoint_pool_t; |
34 |
| - |
35 |
| -slab_t *create_slab(bucket_t *bucket); |
36 |
| -void destroy_slab(slab_t *slab); |
37 |
| - |
38 |
| -void *slab_get(const slab_t *slab); |
39 |
| -void *slab_get_end(const slab_t *slab); |
40 |
| -void *slab_get_chunk(slab_t *slab); |
41 |
| - |
42 |
| -bool slab_has_avail(const slab_t *slab); |
43 |
| -void slab_free_chunk(slab_t *slab, void *ptr); |
44 |
| - |
45 |
| -void slab_reg(slab_t *slab); |
46 |
| -void slab_reg_by_addr(void *addr, slab_t *slab); |
47 |
| -void slab_unreg(slab_t *slab); |
48 |
| -void slab_unreg_by_addr(void *addr, slab_t *slab); |
49 |
| - |
50 |
| -bucket_t *create_bucket(size_t sz, disjoint_pool_t *pool, |
51 |
| - umf_disjoint_pool_shared_limits_t *shared_limits); |
52 |
| -void destroy_bucket(bucket_t *bucket); |
53 |
| - |
54 |
| -void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool); |
55 |
| -bool bucket_can_pool(bucket_t *bucket, bool *to_pool); |
56 |
| -void bucket_decrement_pool(bucket_t *bucket, bool *from_pool); |
57 |
| -void *bucket_get_chunk(bucket_t *bucket, bool *from_pool); |
58 |
| -size_t bucket_chunk_cut_off(bucket_t *bucket); |
59 |
| -size_t bucket_capacity(bucket_t *bucket); |
60 |
| -void bucket_free_chunk(bucket_t *bucket, void *ptr, slab_t *slab, |
61 |
| - bool *to_pool); |
62 |
| -void bucket_count_alloc(bucket_t *bucket, bool from_pool); |
63 |
| - |
64 |
| -void *bucket_get_slab(bucket_t *bucket, bool *from_pool); |
65 |
| -size_t bucket_slab_alloc_size(bucket_t *bucket); |
66 |
| -size_t bucket_slab_min_size(bucket_t *bucket); |
67 |
| -slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket, bool *from_pool); |
68 |
| -slab_list_item_t *bucket_get_avail_full_slab(bucket_t *bucket, bool *from_pool); |
69 |
| -void bucket_free_slab(bucket_t *bucket, slab_t *slab, bool *to_pool); |
| 8 | +#include "pool_disjoint_internal.h" |
70 | 9 |
|
71 | 10 | static __TLS umf_result_t TLS_last_allocation_error;
|
72 | 11 |
|
@@ -113,119 +52,6 @@ static size_t CutOff = (size_t)1 << 31; // 2GB
|
113 | 52 | #endif
|
114 | 53 | }
|
115 | 54 |
|
116 |
| -typedef struct bucket_t { |
117 |
| - size_t size; |
118 |
| - |
119 |
| - // Linked list of slabs which have at least 1 available chunk. |
120 |
| - slab_list_item_t *available_slabs; |
121 |
| - |
122 |
| - // Linked list of slabs with 0 available chunk. |
123 |
| - slab_list_item_t *unavailable_slabs; |
124 |
| - |
125 |
| - // Protects the bucket and all the corresponding slabs |
126 |
| - utils_mutex_t bucket_lock; |
127 |
| - |
128 |
| - // Reference to the allocator context, used access memory allocation |
129 |
| - // routines, slab map and etc. |
130 |
| - disjoint_pool_t *pool; |
131 |
| - |
132 |
| - umf_disjoint_pool_shared_limits_t *shared_limits; |
133 |
| - |
134 |
| - // For buckets used in chunked mode, a counter of slabs in the pool. |
135 |
| - // For allocations that use an entire slab each, the entries in the Available |
136 |
| - // list are entries in the pool.Each slab is available for a new |
137 |
| - // allocation.The size of the Available list is the size of the pool. |
138 |
| - // For allocations that use slabs in chunked mode, slabs will be in the |
139 |
| - // Available list if any one or more of their chunks is free.The entire slab |
140 |
| - // is not necessarily free, just some chunks in the slab are free. To |
141 |
| - // implement pooling we will allow one slab in the Available list to be |
142 |
| - // entirely empty. Normally such a slab would have been freed. But |
143 |
| - // now we don't, and treat this slab as "in the pool". |
144 |
| - // When a slab becomes entirely free we have to decide whether to return it |
145 |
| - // to the provider or keep it allocated. A simple check for size of the |
146 |
| - // Available list is not sufficient to check whether any slab has been |
147 |
| - // pooled yet.We would have to traverse the entire Available listand check |
148 |
| - // if any of them is entirely free. Instead we keep a counter of entirely |
149 |
| - // empty slabs within the Available list to speed up the process of checking |
150 |
| - // if a slab in this bucket is already pooled. |
151 |
| - size_t chunked_slabs_in_pool; |
152 |
| - |
153 |
| - // Statistics |
154 |
| - size_t alloc_pool_count; |
155 |
| - size_t free_count; |
156 |
| - size_t curr_slabs_in_use; |
157 |
| - size_t curr_slabs_in_pool; |
158 |
| - size_t max_slabs_in_pool; |
159 |
| - size_t alloc_count; |
160 |
| - size_t max_slabs_in_use; |
161 |
| -} bucket_t; |
162 |
| - |
163 |
| -// Represents the allocated memory block of size 'slab_min_size' |
164 |
| -// Internally, it splits the memory block into chunks. The number of |
165 |
| -// chunks depends of the size of a Bucket which created the Slab. |
166 |
| -// Note: Bucket's methods are responsible for thread safety of Slab access, |
167 |
| -// so no locking happens here. |
168 |
| -typedef struct slab_t { |
169 |
| - // Pointer to the allocated memory of slab_min_size bytes |
170 |
| - void *mem_ptr; |
171 |
| - size_t slab_size; |
172 |
| - |
173 |
| - // Represents the current state of each chunk: if the bit is set then the |
174 |
| - // chunk is allocated, and if the chunk is free for allocation otherwise |
175 |
| - bool *chunks; |
176 |
| - size_t num_chunks; |
177 |
| - |
178 |
| - // Total number of allocated chunks at the moment. |
179 |
| - size_t num_allocated; |
180 |
| - |
181 |
| - // The bucket which the slab belongs to |
182 |
| - bucket_t *bucket; |
183 |
| - |
184 |
| - // Hints where to start search for free chunk in a slab |
185 |
| - size_t first_free_chunk_idx; |
186 |
| - |
187 |
| - // Store iterator to the corresponding node in avail/unavail list |
188 |
| - // to achieve O(1) removal |
189 |
| - slab_list_item_t *iter; |
190 |
| -} slab_t; |
191 |
| - |
192 |
| -typedef struct slab_list_item_t { |
193 |
| - slab_t *val; |
194 |
| - struct slab_list_item_t *prev, *next; |
195 |
| -} slab_list_item_t; |
196 |
| - |
197 |
| -typedef struct umf_disjoint_pool_shared_limits_t { |
198 |
| - size_t max_size; |
199 |
| - size_t total_size; // requires atomic access |
200 |
| -} umf_disjoint_pool_shared_limits_t; |
201 |
| - |
202 |
| -typedef struct disjoint_pool_t { |
203 |
| - // It's important for the map to be destroyed last after buckets and their |
204 |
| - // slabs This is because slab's destructor removes the object from the map. |
205 |
| - critnib *known_slabs; // (void *, slab_t *) |
206 |
| - |
207 |
| - // TODO: prev std::shared_timed_mutex - ok? |
208 |
| - utils_mutex_t known_slabs_map_lock; |
209 |
| - |
210 |
| - // Handle to the memory provider |
211 |
| - umf_memory_provider_handle_t provider; |
212 |
| - |
213 |
| - // Array of bucket_t* |
214 |
| - bucket_t **buckets; |
215 |
| - size_t buckets_num; |
216 |
| - |
217 |
| - // Configuration for this instance |
218 |
| - umf_disjoint_pool_params_t params; |
219 |
| - |
220 |
| - umf_disjoint_pool_shared_limits_t *default_shared_limits; |
221 |
| - |
222 |
| - // Used in algorithm for finding buckets |
223 |
| - size_t min_bucket_size_exp; |
224 |
| - |
225 |
| - // Coarse-grain allocation min alignment |
226 |
| - size_t provider_min_page_size; |
227 |
| -} disjoint_pool_t; |
228 |
| - |
229 | 55 | slab_t *create_slab(bucket_t *bucket) {
|
230 | 56 | assert(bucket);
|
231 | 57 |
|
@@ -331,7 +157,7 @@ void *slab_get_chunk(slab_t *slab) {
|
331 | 157 | slab->num_allocated += 1;
|
332 | 158 |
|
333 | 159 | // use the found index as the next hint
|
334 |
| - slab->first_free_chunk_idx = chunk_idx; |
| 160 | + slab->first_free_chunk_idx = chunk_idx + 1; |
335 | 161 |
|
336 | 162 | return free_chunk;
|
337 | 163 | }
|
|
0 commit comments