|
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