This source file includes following definitions.
- mca_allocator_bucket_init
- mca_allocator_bucket_alloc
- mca_allocator_bucket_alloc_align
- mca_allocator_bucket_realloc
- mca_allocator_bucket_free
- mca_allocator_bucket_cleanup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "opal_config.h"
21 #include "opal/constants.h"
22 #include "opal/mca/allocator/bucket/allocator_bucket_alloc.h"
23
24
25
26
27 #define MCA_ALLOCATOR_BUCKET_1_SIZE 8
28
29
30
31
32 #define MCA_ALLOCATOR_BUCKET_1_BITSHIFTS 3
33
34
35
36
37
38 mca_allocator_bucket_t * mca_allocator_bucket_init(
39 mca_allocator_base_module_t * mem,
40 int num_buckets,
41 mca_allocator_base_component_segment_alloc_fn_t get_mem_funct,
42 mca_allocator_base_component_segment_free_fn_t free_mem_funct)
43 {
44 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
45 int i;
46 size_t size;
47
48 if(num_buckets <= 0) {
49 num_buckets = 30;
50 }
51
52 size = sizeof(mca_allocator_bucket_bucket_t) * num_buckets;
53 mem_options->buckets = (mca_allocator_bucket_bucket_t*) malloc(size);
54 if(NULL == mem_options->buckets) {
55 return(NULL);
56 }
57 for(i = 0; i < num_buckets; i++) {
58 mem_options->buckets[i].free_chunk = NULL;
59 mem_options->buckets[i].segment_head = NULL;
60 OBJ_CONSTRUCT(&(mem_options->buckets[i].lock), opal_mutex_t);
61 }
62 mem_options->num_buckets = num_buckets;
63 mem_options->get_mem_fn = get_mem_funct;
64 mem_options->free_mem_fn = free_mem_funct;
65 return(mem_options);
66 }
67
68
69
70
71
72
73
74 void * mca_allocator_bucket_alloc(mca_allocator_base_module_t * mem,
75 size_t size)
76 {
77 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
78
79 int bucket_num = 0;
80 size_t bucket_size = MCA_ALLOCATOR_BUCKET_1_SIZE;
81 size_t allocated_size;
82 mca_allocator_bucket_chunk_header_t * chunk;
83 mca_allocator_bucket_chunk_header_t * first_chunk;
84 mca_allocator_bucket_segment_head_t * segment_header;
85
86 size += sizeof(mca_allocator_bucket_chunk_header_t);
87
88
89 while(size > bucket_size) {
90 bucket_num++;
91 bucket_size <<= 1;
92 }
93
94
95 OPAL_THREAD_LOCK(&(mem_options->buckets[bucket_num].lock));
96
97 if(NULL != mem_options->buckets[bucket_num].free_chunk) {
98 chunk = mem_options->buckets[bucket_num].free_chunk;
99 mem_options->buckets[bucket_num].free_chunk = chunk->u.next_free;
100 chunk->u.bucket = bucket_num;
101
102 chunk += 1;
103
104 OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
105 return((void *) chunk);
106 }
107
108 allocated_size = bucket_size;
109
110
111 allocated_size += sizeof(mca_allocator_bucket_segment_head_t);
112
113 segment_header = (mca_allocator_bucket_segment_head_t *)
114 mem_options->get_mem_fn(mem_options->super.alc_context, &allocated_size);
115 if(NULL == segment_header) {
116
117 OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
118 return(NULL);
119 }
120
121
122 allocated_size -= (sizeof(mca_allocator_bucket_segment_head_t) + bucket_size);
123 chunk = first_chunk = segment_header->first_chunk =
124 (mca_allocator_bucket_chunk_header_t *) (segment_header + 1);
125
126 segment_header->next_segment = mem_options->buckets[bucket_num].segment_head;
127 mem_options->buckets[bucket_num].segment_head = segment_header;
128 if(allocated_size >= bucket_size) {
129 mem_options->buckets[bucket_num].free_chunk =
130 (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size);
131 chunk->next_in_segment = (mca_allocator_bucket_chunk_header_t *)
132 ((char *)chunk + bucket_size);
133 while(allocated_size >= bucket_size) {
134 chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size);
135 chunk->u.next_free = (mca_allocator_bucket_chunk_header_t *)
136 ((char *) chunk + bucket_size);
137 chunk->next_in_segment = chunk->u.next_free;
138 allocated_size -= bucket_size;
139 }
140 chunk->next_in_segment = first_chunk;
141 chunk->u.next_free = NULL;
142 } else {
143 first_chunk->next_in_segment = first_chunk;
144 }
145 first_chunk->u.bucket = bucket_num;
146 OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
147
148 return((void *) (first_chunk + 1));
149 }
150
151
152
153
154 void * mca_allocator_bucket_alloc_align(mca_allocator_base_module_t * mem,
155 size_t size, size_t alignment)
156 {
157 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
158 int bucket_num = 1;
159 void * ptr;
160 size_t aligned_max_size, bucket_size;
161 size_t alignment_off, allocated_size;
162 mca_allocator_bucket_chunk_header_t * chunk;
163 mca_allocator_bucket_chunk_header_t * first_chunk;
164 mca_allocator_bucket_segment_head_t * segment_header;
165 char * aligned_memory;
166
167
168
169
170 aligned_max_size = size + alignment + sizeof(mca_allocator_bucket_chunk_header_t)
171 + sizeof(mca_allocator_bucket_segment_head_t);
172 bucket_size = size + sizeof(mca_allocator_bucket_chunk_header_t);
173 allocated_size = aligned_max_size;
174
175 ptr = mem_options->get_mem_fn(mem_options->super.alc_context, &allocated_size);
176 if(NULL == ptr) {
177 return(NULL);
178 }
179
180 segment_header = (mca_allocator_bucket_segment_head_t *) ptr;
181
182 first_chunk = (mca_allocator_bucket_chunk_header_t *) (segment_header + 1);
183
184
185 aligned_memory = (char *) (first_chunk + 1);
186
187 alignment_off = ((size_t) aligned_memory) % alignment;
188 aligned_memory += (alignment - alignment_off);
189
190
191 first_chunk = (mca_allocator_bucket_chunk_header_t *) aligned_memory - 1;
192 while(bucket_size > MCA_ALLOCATOR_BUCKET_1_SIZE) {
193 bucket_size >>= 1;
194 bucket_num++;
195 }
196 bucket_size = 1;
197 bucket_size <<= MCA_ALLOCATOR_BUCKET_1_BITSHIFTS + bucket_num;
198
199
200
201 allocated_size -= aligned_max_size;
202 chunk = segment_header->first_chunk = first_chunk;
203
204 OPAL_THREAD_LOCK(&(mem_options->buckets[bucket_num].lock));
205
206 segment_header->next_segment = mem_options->buckets[bucket_num].segment_head;
207 mem_options->buckets[bucket_num].segment_head = segment_header;
208 if(allocated_size >= bucket_size) {
209 mem_options->buckets[bucket_num].free_chunk =
210 (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size);
211 chunk->next_in_segment = (mca_allocator_bucket_chunk_header_t *)
212 ((char *)chunk + bucket_size);
213 while(allocated_size >= bucket_size) {
214 chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size);
215 chunk->u.next_free = (mca_allocator_bucket_chunk_header_t *)
216 ((char *) chunk + bucket_size);
217 chunk->next_in_segment = chunk->u.next_free;
218 allocated_size -= bucket_size;
219 }
220 chunk->next_in_segment = first_chunk;
221 chunk->u.next_free = NULL;
222 } else {
223 first_chunk->next_in_segment = first_chunk;
224 }
225 first_chunk->u.bucket = bucket_num;
226 OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
227
228 return((void *) (aligned_memory));
229 }
230
231
232
233
234 void * mca_allocator_bucket_realloc(mca_allocator_base_module_t * mem,
235 void * ptr, size_t size)
236 {
237 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
238
239 size_t bucket_size = 1;
240 int bucket_num;
241 void * ret_ptr;
242
243 mca_allocator_bucket_chunk_header_t * chunk = (mca_allocator_bucket_chunk_header_t *) ptr - 1;
244 bucket_num = chunk->u.bucket;
245
246 bucket_size <<= (bucket_num + MCA_ALLOCATOR_BUCKET_1_BITSHIFTS);
247
248
249 bucket_size -= sizeof(mca_allocator_bucket_chunk_header_t);
250
251
252 if(size <= bucket_size) {
253 return(ptr);
254 }
255
256 ret_ptr = mca_allocator_bucket_alloc((mca_allocator_base_module_t *) mem_options, size);
257 if(NULL == ret_ptr) {
258
259 return(NULL);
260 }
261
262 memcpy(ret_ptr, ptr, bucket_size);
263
264 mca_allocator_bucket_free((mca_allocator_base_module_t *) mem_options, ptr);
265 return(ret_ptr);
266 }
267
268
269
270
271
272
273 void mca_allocator_bucket_free(mca_allocator_base_module_t * mem, void * ptr)
274 {
275 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
276 mca_allocator_bucket_chunk_header_t * chunk = (mca_allocator_bucket_chunk_header_t *) ptr - 1;
277 int bucket_num = chunk->u.bucket;
278 OPAL_THREAD_LOCK(&(mem_options->buckets[bucket_num].lock));
279 chunk->u.next_free = mem_options->buckets[bucket_num].free_chunk;
280 mem_options->buckets[bucket_num].free_chunk = chunk;
281 OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
282 }
283
284
285
286
287
288
289
290 int mca_allocator_bucket_cleanup(mca_allocator_base_module_t * mem)
291 {
292 mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem;
293 int i;
294 mca_allocator_bucket_chunk_header_t * next_chunk;
295 mca_allocator_bucket_chunk_header_t * chunk;
296 mca_allocator_bucket_chunk_header_t * first_chunk;
297 mca_allocator_bucket_segment_head_t ** segment_header;
298 mca_allocator_bucket_segment_head_t * segment;
299 bool empty = true;
300
301 for(i = 0; i < mem_options->num_buckets; i++) {
302 OPAL_THREAD_LOCK(&(mem_options->buckets[i].lock));
303 segment_header = &(mem_options->buckets[i].segment_head);
304 if( NULL == (*segment_header) ) {
305 OPAL_THREAD_UNLOCK(&(mem_options->buckets[i].lock));
306 continue;
307 }
308
309
310
311
312
313 empty = true;
314 segment = mem_options->buckets[i].segment_head;
315 while( (true == empty) && (NULL != segment) ) {
316 first_chunk = segment->first_chunk;
317 chunk = first_chunk;
318
319 do {
320 if(chunk->u.bucket == i) {
321 empty = false;
322 break;
323 }
324 chunk = chunk->next_in_segment;
325 } while(chunk != first_chunk);
326
327 segment = segment->next_segment;
328 }
329 if( true == empty ) {
330 mca_allocator_bucket_segment_head_t* next_segment;
331 segment = mem_options->buckets[i].segment_head;
332 while( NULL != segment ) {
333 next_segment = segment->next_segment;
334
335 if(mem_options->free_mem_fn)
336 mem_options->free_mem_fn(mem->alc_context, segment);
337 segment = next_segment;
338 }
339 mem_options->buckets[i].free_chunk = NULL;
340 mem_options->buckets[i].segment_head = NULL;
341 } else {
342
343 while(NULL != *segment_header) {
344 first_chunk = (*segment_header)->first_chunk;
345 chunk = first_chunk;
346 empty = true;
347
348 do {
349 if(chunk->u.bucket == i) {
350 empty = false;
351 }
352 chunk = chunk->next_in_segment;
353 } while(empty && (chunk != first_chunk));
354 if(empty) {
355 chunk = first_chunk;
356
357 do {
358 if(mem_options->buckets[i].free_chunk == chunk) {
359 mem_options->buckets[i].free_chunk = chunk->u.next_free;
360 } else {
361 next_chunk = mem_options->buckets[i].free_chunk;
362 while(next_chunk->u.next_free != chunk) {
363 next_chunk = next_chunk->u.next_free;
364 }
365 next_chunk->u.next_free = chunk->u.next_free;
366 }
367 } while((chunk = chunk->next_in_segment) != first_chunk);
368
369 segment = *segment_header;
370 *segment_header = segment->next_segment;
371
372 if(mem_options->free_mem_fn)
373 mem_options->free_mem_fn(mem->alc_context, segment);
374 } else {
375
376 segment_header = &((*segment_header)->next_segment);
377 }
378 }
379 }
380
381 OPAL_THREAD_UNLOCK(&(mem_options->buckets[i].lock));
382 }
383 return(OPAL_SUCCESS);
384 }