Skip to content

Commit 3521be5

Browse files
committed
tests
1 parent 2c6c01e commit 3521be5

File tree

3 files changed

+284
-176
lines changed

3 files changed

+284
-176
lines changed

src/pool/pool_disjoint.c

Lines changed: 2 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,7 @@
55
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
*/
77

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"
709

7110
static __TLS umf_result_t TLS_last_allocation_error;
7211

@@ -113,119 +52,6 @@ static size_t CutOff = (size_t)1 << 31; // 2GB
11352
#endif
11453
}
11554

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-
22955
slab_t *create_slab(bucket_t *bucket) {
23056
assert(bucket);
23157

@@ -331,7 +157,7 @@ void *slab_get_chunk(slab_t *slab) {
331157
slab->num_allocated += 1;
332158

333159
// 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;
335161

336162
return free_chunk;
337163
}

src/pool/pool_disjoint_internal.h

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright (C) 2022-2024 Intel Corporation
3+
*
4+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*/
7+
8+
#ifndef UMF_POOL_DISJOINT_INTERNAL_H
9+
#define UMF_POOL_DISJOINT_INTERNAL_H 1
10+
11+
#include <assert.h>
12+
#include <errno.h>
13+
#include <stdbool.h>
14+
#include <stdlib.h>
15+
#include <string.h>
16+
17+
#include <umf/memory_pool.h>
18+
#include <umf/memory_pool_ops.h>
19+
#include <umf/memory_provider.h>
20+
#include <umf/pools/pool_disjoint.h>
21+
22+
#include "critnib/critnib.h"
23+
#include "uthash/utlist.h"
24+
25+
#include "base_alloc_global.h"
26+
#include "provider_tracking.h"
27+
#include "utils_common.h"
28+
#include "utils_concurrency.h"
29+
#include "utils_log.h"
30+
#include "utils_math.h"
31+
#include "utils_sanitizers.h"
32+
33+
typedef struct bucket_t bucket_t;
34+
typedef struct slab_t slab_t;
35+
typedef struct slab_list_item_t slab_list_item_t;
36+
typedef struct disjoint_pool_t disjoint_pool_t;
37+
38+
typedef struct bucket_t {
39+
size_t size;
40+
41+
// Linked list of slabs which have at least 1 available chunk.
42+
slab_list_item_t *available_slabs;
43+
44+
// Linked list of slabs with 0 available chunk.
45+
slab_list_item_t *unavailable_slabs;
46+
47+
// Protects the bucket and all the corresponding slabs
48+
utils_mutex_t bucket_lock;
49+
50+
// Reference to the allocator context, used access memory allocation
51+
// routines, slab map and etc.
52+
disjoint_pool_t *pool;
53+
54+
umf_disjoint_pool_shared_limits_t *shared_limits;
55+
56+
// For buckets used in chunked mode, a counter of slabs in the pool.
57+
// For allocations that use an entire slab each, the entries in the Available
58+
// list are entries in the pool.Each slab is available for a new
59+
// allocation.The size of the Available list is the size of the pool.
60+
// For allocations that use slabs in chunked mode, slabs will be in the
61+
// Available list if any one or more of their chunks is free.The entire slab
62+
// is not necessarily free, just some chunks in the slab are free. To
63+
// implement pooling we will allow one slab in the Available list to be
64+
// entirely empty. Normally such a slab would have been freed. But
65+
// now we don't, and treat this slab as "in the pool".
66+
// When a slab becomes entirely free we have to decide whether to return it
67+
// to the provider or keep it allocated. A simple check for size of the
68+
// Available list is not sufficient to check whether any slab has been
69+
// pooled yet.We would have to traverse the entire Available listand check
70+
// if any of them is entirely free. Instead we keep a counter of entirely
71+
// empty slabs within the Available list to speed up the process of checking
72+
// if a slab in this bucket is already pooled.
73+
size_t chunked_slabs_in_pool;
74+
75+
// Statistics
76+
size_t alloc_pool_count;
77+
size_t free_count;
78+
size_t curr_slabs_in_use;
79+
size_t curr_slabs_in_pool;
80+
size_t max_slabs_in_pool;
81+
size_t alloc_count;
82+
size_t max_slabs_in_use;
83+
} bucket_t;
84+
85+
// Represents the allocated memory block of size 'slab_min_size'
86+
// Internally, it splits the memory block into chunks. The number of
87+
// chunks depends of the size of a Bucket which created the Slab.
88+
// Note: Bucket's methods are responsible for thread safety of Slab access,
89+
// so no locking happens here.
90+
typedef struct slab_t {
91+
// Pointer to the allocated memory of slab_min_size bytes
92+
void *mem_ptr;
93+
size_t slab_size;
94+
95+
// Represents the current state of each chunk: if the bit is set then the
96+
// chunk is allocated, and if the chunk is free for allocation otherwise
97+
bool *chunks;
98+
size_t num_chunks;
99+
100+
// Total number of allocated chunks at the moment.
101+
size_t num_allocated;
102+
103+
// The bucket which the slab belongs to
104+
bucket_t *bucket;
105+
106+
// Hints where to start search for free chunk in a slab
107+
size_t first_free_chunk_idx;
108+
109+
// Store iterator to the corresponding node in avail/unavail list
110+
// to achieve O(1) removal
111+
slab_list_item_t *iter;
112+
} slab_t;
113+
114+
typedef struct slab_list_item_t {
115+
slab_t *val;
116+
struct slab_list_item_t *prev, *next;
117+
} slab_list_item_t;
118+
119+
typedef struct umf_disjoint_pool_shared_limits_t {
120+
size_t max_size;
121+
size_t total_size; // requires atomic access
122+
} umf_disjoint_pool_shared_limits_t;
123+
124+
typedef struct disjoint_pool_t {
125+
// It's important for the map to be destroyed last after buckets and their
126+
// slabs This is because slab's destructor removes the object from the map.
127+
critnib *known_slabs; // (void *, slab_t *)
128+
129+
// TODO: prev std::shared_timed_mutex - ok?
130+
utils_mutex_t known_slabs_map_lock;
131+
132+
// Handle to the memory provider
133+
umf_memory_provider_handle_t provider;
134+
135+
// Array of bucket_t*
136+
bucket_t **buckets;
137+
size_t buckets_num;
138+
139+
// Configuration for this instance
140+
umf_disjoint_pool_params_t params;
141+
142+
umf_disjoint_pool_shared_limits_t *default_shared_limits;
143+
144+
// Used in algorithm for finding buckets
145+
size_t min_bucket_size_exp;
146+
147+
// Coarse-grain allocation min alignment
148+
size_t provider_min_page_size;
149+
} disjoint_pool_t;
150+
151+
slab_t *create_slab(bucket_t *bucket);
152+
void destroy_slab(slab_t *slab);
153+
154+
void *slab_get(const slab_t *slab);
155+
void *slab_get_end(const slab_t *slab);
156+
void *slab_get_chunk(slab_t *slab);
157+
158+
bool slab_has_avail(const slab_t *slab);
159+
void slab_free_chunk(slab_t *slab, void *ptr);
160+
161+
void slab_reg(slab_t *slab);
162+
void slab_reg_by_addr(void *addr, slab_t *slab);
163+
void slab_unreg(slab_t *slab);
164+
void slab_unreg_by_addr(void *addr, slab_t *slab);
165+
166+
bucket_t *create_bucket(size_t sz, disjoint_pool_t *pool,
167+
umf_disjoint_pool_shared_limits_t *shared_limits);
168+
void destroy_bucket(bucket_t *bucket);
169+
170+
void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool);
171+
bool bucket_can_pool(bucket_t *bucket, bool *to_pool);
172+
void bucket_decrement_pool(bucket_t *bucket, bool *from_pool);
173+
void *bucket_get_chunk(bucket_t *bucket, bool *from_pool);
174+
size_t bucket_chunk_cut_off(bucket_t *bucket);
175+
size_t bucket_capacity(bucket_t *bucket);
176+
void bucket_free_chunk(bucket_t *bucket, void *ptr, slab_t *slab,
177+
bool *to_pool);
178+
void bucket_count_alloc(bucket_t *bucket, bool from_pool);
179+
180+
void *bucket_get_slab(bucket_t *bucket, bool *from_pool);
181+
size_t bucket_slab_alloc_size(bucket_t *bucket);
182+
size_t bucket_slab_min_size(bucket_t *bucket);
183+
slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket, bool *from_pool);
184+
slab_list_item_t *bucket_get_avail_full_slab(bucket_t *bucket, bool *from_pool);
185+
void bucket_free_slab(bucket_t *bucket, slab_t *slab, bool *to_pool);
186+
187+
bucket_t *disjoint_pool_find_bucket(disjoint_pool_t *pool, size_t size);
188+
189+
#endif // UMF_POOL_DISJOINT_INTERNAL_H

0 commit comments

Comments
 (0)