This source file includes following definitions.
- bits_per_long
- bitmap_zero
- __clear_bit
- __set_bit
- test_bit
- __ffs
- memheap_buddy_find_order
- find_next_bit
- mca_memheap_buddy_module_init
- buddy_init
- buddy_cleanup
- _buddy_alloc
- _buddy_free
- buddy_free
- buddy_private_free
- _do_alloc
- do_alloc
- do_private_alloc
- mca_memheap_buddy_alloc
- mca_memheap_buddy_private_alloc
- mca_memheap_buddy_private_free
- mca_memheap_buddy_align
- mca_memheap_buddy_realloc
- mca_memheap_buddy_free
- mca_memheap_buddy_finalize
1
2
3
4
5
6
7
8
9
10
11
12 #include "oshmem_config.h"
13 #include "oshmem/proc/proc.h"
14 #include "oshmem/mca/spml/spml.h"
15 #include "oshmem/mca/memheap/memheap.h"
16 #include "oshmem/mca/memheap/buddy/memheap_buddy.h"
17 #include "oshmem/mca/memheap/buddy/memheap_buddy_component.h"
18 #include "oshmem/mca/memheap/base/base.h"
19 #include "opal/class/opal_hash_table.h"
20 #include "opal/class/opal_object.h"
21
22 static int buddy_init(mca_memheap_buddy_module_t* buddy);
23
24 mca_memheap_buddy_module_t memheap_buddy = {
25 {
26 &mca_memheap_buddy_component,
27 mca_memheap_buddy_finalize,
28 mca_memheap_buddy_alloc,
29 mca_memheap_buddy_align,
30 mca_memheap_buddy_realloc,
31 mca_memheap_buddy_free,
32
33 mca_memheap_buddy_private_alloc,
34 mca_memheap_buddy_private_free,
35
36 mca_memheap_base_get_mkey,
37 mca_memheap_base_is_symmetric_addr,
38 mca_memheap_modex_recv_all,
39
40 0
41 },
42 1
43 };
44
45
46
47
48 static inline unsigned int bits_per_long(void)
49 {
50 return BITS_PER_BYTE * sizeof(unsigned long);
51 }
52
53 static inline void bitmap_zero(unsigned long *dst, unsigned long nbits)
54 {
55 unsigned long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
56 memset(dst, 0, len);
57 }
58
59
60
61
62 static inline void __clear_bit(unsigned long nr, volatile void * addr)
63 {
64 int *m = ((int *) addr) + (nr >> 5);
65 *m &= ~(1 << (nr & 31));
66 }
67
68
69
70
71 static inline void __set_bit(unsigned long nr, volatile void * addr)
72 {
73 int *m = ((int *) addr) + (nr >> 5);
74 *m |= 1 << (nr & 31);
75 }
76
77 static inline int test_bit(int nr, const volatile void * addr)
78 {
79 return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
80 }
81
82
83
84
85
86
87
88 static inline __opal_attribute_always_inline__ unsigned long __ffs(unsigned long word)
89 {
90 int num = 0;
91 #if SIZEOF_LONG == 8
92 if ((word & 0xffffffff) == 0) {
93 num += 32;
94 word >>= 32;
95 }
96 #endif
97
98 if ((word & 0xffff) == 0) {
99 num += 16;
100 word >>= 16;
101 }
102 if ((word & 0xff) == 0) {
103 num += 8;
104 word >>= 8;
105 }
106 if ((word & 0xf) == 0) {
107 num += 4;
108 word >>= 4;
109 }
110 if ((word & 0x3) == 0) {
111 num += 2;
112 word >>= 2;
113 }
114 if ((word & 0x1) == 0)
115 num += 1;
116 return num;
117 }
118
119
120 static inline unsigned memheap_buddy_find_order(unsigned long size)
121 {
122 unsigned order;
123
124 if (size & (size - 1))
125 order = 1;
126 else
127 order = 0;
128
129 while (size >>= 1) {
130 order++;
131 }
132 return order;
133 }
134
135
136
137
138
139
140
141
142 static inline unsigned long find_next_bit(const unsigned long *addr,
143 unsigned long size,
144 unsigned long offset)
145 {
146 const unsigned long *p = addr + BITOP_WORD(offset);
147 unsigned long result = offset & ~(bits_per_long() - 1);
148 unsigned long tmp;
149
150 if (offset >= size)
151 return size;
152 size -= result;
153 offset %= bits_per_long();
154 if (offset) {
155 tmp = *(p++);
156 tmp &= (~0UL << offset);
157 if (size < bits_per_long())
158 goto found_first;
159 if (tmp)
160 goto found_middle;
161 size -= bits_per_long();
162 result += bits_per_long();
163 }
164 while (size & ~(bits_per_long() - 1)) {
165 if ((tmp = *(p++)))
166 goto found_middle;
167 result += bits_per_long();
168 size -= bits_per_long();
169 }
170 if (!size)
171 return result;
172 tmp = *p;
173
174 found_first: tmp &= (~0UL >> (bits_per_long() - size));
175 if (tmp == 0UL)
176 return result + size;
177 found_middle: return result + __ffs(tmp);
178 }
179
180
181
182
183 int mca_memheap_buddy_module_init(memheap_context_t *context)
184 {
185 if (!context || !context->user_size || !context->private_size) {
186 return OSHMEM_ERR_BAD_PARAM;
187 }
188
189
190 OBJ_CONSTRUCT(&memheap_buddy.lock, opal_mutex_t);
191
192 memheap_buddy.heap.max_order = memheap_log2(context->user_size);
193 memheap_buddy.heap.min_order = MEMHEAP_BASE_MIN_ORDER;
194 memheap_buddy.private_heap.max_order = memheap_log2(context->private_size);
195 memheap_buddy.private_heap.min_order = MEMHEAP_BASE_MIN_ORDER;
196
197 if (context->user_size != (1ULL << memheap_buddy.heap.max_order)) {
198 MEMHEAP_VERBOSE(1,
199 "Memheap rounded to the nearest power of two: requested %llu bytes, allocated %llu bytes",
200 (unsigned long long)context->user_size, 1ULL << memheap_buddy.heap.max_order);
201 }
202
203 assert(context->private_size == (1ULL << memheap_buddy.private_heap.max_order));
204
205 memheap_buddy.heap.symmetric_heap = context->user_base_addr;
206 memheap_buddy.private_heap.symmetric_heap = context->private_base_addr;
207
208 memheap_buddy.super.memheap_size = (1ULL << memheap_buddy.heap.max_order);
209
210 MEMHEAP_VERBOSE(1,
211 "symmetric heap memory (user+private): %llu bytes",
212 (unsigned long long)(context->user_size + context->private_size));
213
214
215 if (OSHMEM_SUCCESS != buddy_init(&memheap_buddy)) {
216 MEMHEAP_ERROR("Failed to setup MEMHEAP buddy allocator");
217 goto err;
218 }
219
220 return OSHMEM_SUCCESS;
221
222 err: mca_memheap_buddy_finalize();
223 return OSHMEM_ERROR;
224 }
225
226 static int buddy_init(mca_memheap_buddy_module_t* buddy)
227 {
228 unsigned long long total_size;
229 unsigned i;
230 unsigned long long s;
231
232
233 memheap_buddy.heap.symmetric_heap_hashtable = OBJ_NEW(opal_hash_table_t);
234 if (NULL == memheap_buddy.heap.symmetric_heap_hashtable) {
235 MEMHEAP_ERROR("Opal failed to allocate hashtable object");
236 goto err;
237 }
238 memheap_buddy.private_heap.symmetric_heap_hashtable =
239 OBJ_NEW(opal_hash_table_t);
240 if (NULL == memheap_buddy.private_heap.symmetric_heap_hashtable) {
241 MEMHEAP_ERROR("Opal failed to allocate hashtable object");
242 goto err;
243 }
244
245 opal_hash_table_init(memheap_buddy.heap.symmetric_heap_hashtable,
246 DEFAULT_HASHTABLE_SIZE);
247 opal_hash_table_init(memheap_buddy.private_heap.symmetric_heap_hashtable,
248 DEFAULT_HASHTABLE_SIZE);
249
250 buddy->heap.bits = (unsigned long**) calloc((buddy->heap.max_order + 1),
251 sizeof(unsigned long *));
252 buddy->private_heap.bits =
253 (unsigned long**) calloc((buddy->private_heap.max_order + 1),
254 sizeof(unsigned long *));
255 buddy->heap.num_free = (unsigned int*) calloc((buddy->heap.max_order + 1),
256 sizeof(unsigned int));
257 buddy->private_heap.num_free =
258 (unsigned int*) calloc((buddy->private_heap.max_order + 1),
259 sizeof(unsigned int));
260 if ((NULL == buddy->heap.bits) || (NULL == buddy->heap.num_free)
261 || (NULL == buddy->private_heap.bits)
262 || (NULL == buddy->private_heap.num_free)) {
263
264 MEMHEAP_ERROR("Failed to allocate buddy allocator");
265 goto err;
266 }
267
268 total_size = 0;
269 for (i = buddy->heap.min_order; i <= buddy->heap.max_order; ++i) {
270 s = BITS_TO_LONGS(1UL << (buddy->heap.max_order - i));
271 MEMHEAP_VERBOSE(20,
272 "%d: (order=%d) allocating %llu longs (sizeof long = %d)",
273 i, buddy->heap.max_order, s, (int)sizeof(unsigned long));
274 total_size += s * sizeof(unsigned long);
275 buddy->heap.bits[i] = (unsigned long*) malloc(s
276 * sizeof(unsigned long));
277 if (NULL == buddy->heap.bits[i]) {
278 MEMHEAP_ERROR("Failed to allocate buddy->allocator");
279 goto err;
280 }
281 bitmap_zero(buddy->heap.bits[i], 1UL << (buddy->heap.max_order - i));
282 }
283 MEMHEAP_VERBOSE(5, "MEMHEAP metadata size = %llu bytes", total_size);
284
285 total_size = 0;
286 for (i = buddy->private_heap.min_order; i <= buddy->private_heap.max_order;
287 ++i) {
288 s = BITS_TO_LONGS(1UL << (buddy->private_heap.max_order - i));
289 MEMHEAP_VERBOSE(20,
290 "%d: (order=%d) allocating %llu longs (sizeof long = %d)",
291 i, buddy->private_heap.max_order, s, (int)sizeof(unsigned long));
292 total_size += s * sizeof(unsigned long);
293 buddy->private_heap.bits[i] = (unsigned long*) malloc(s
294 * sizeof(unsigned long));
295 if (NULL == buddy->private_heap.bits[i]) {
296 MEMHEAP_ERROR("Failed to allocate buddy->allocator");
297 goto err;
298 }
299 bitmap_zero(buddy->private_heap.bits[i],
300 1UL << (buddy->private_heap.max_order - i));
301 }
302 MEMHEAP_VERBOSE(5,
303 "private MEMHEAP metadata size = %llu bytes",
304 total_size);
305
306 set_bit(0, buddy->heap.bits[buddy->heap.max_order]);
307 set_bit(0, buddy->private_heap.bits[buddy->private_heap.max_order]);
308 buddy->heap.num_free[buddy->heap.max_order] = 1;
309 buddy->private_heap.num_free[buddy->private_heap.max_order] = 1;
310
311 return OSHMEM_SUCCESS;
312
313 err: return OSHMEM_ERROR;
314 }
315
316 static int buddy_cleanup(mca_memheap_buddy_module_t* buddy)
317 {
318 unsigned int i;
319
320 MEMHEAP_VERBOSE(5, "buddy cleanup");
321 if (NULL == buddy) {
322 return OSHMEM_SUCCESS;
323 }
324
325 for (i = 0; i <= buddy->heap.max_order; ++i) {
326 if (NULL != buddy->heap.bits && NULL != buddy->heap.bits[i]) {
327 free(buddy->heap.bits[i]);
328 }
329 }
330
331 for (i = 0; i <= buddy->private_heap.max_order; ++i) {
332 if (NULL != buddy->private_heap.bits
333 && NULL != buddy->private_heap.bits[i]) {
334 free(buddy->private_heap.bits[i]);
335 }
336 }
337
338 if (NULL != buddy->heap.bits) {
339 free(buddy->heap.bits);
340 }
341 if (NULL != buddy->heap.num_free) {
342 free(buddy->heap.num_free);
343 }
344
345 if (NULL != buddy->private_heap.bits) {
346 free(buddy->private_heap.bits);
347 }
348 if (NULL != buddy->private_heap.num_free) {
349 free(buddy->private_heap.num_free);
350 }
351
352 OBJ_DESTRUCT(&buddy->lock);
353 return OSHMEM_SUCCESS;
354 }
355
356 static int _buddy_alloc(unsigned order,
357 uint32_t* seg,
358 mca_memheap_buddy_heap_t *heap)
359 {
360 uint32_t o;
361 uint32_t m;
362
363 MEMHEAP_VERBOSE(20, "order=%d size=%d", order, 1<<order);
364 OPAL_THREAD_LOCK(&memheap_buddy.lock);
365 for (o = order; o <= heap->max_order; ++o) {
366 if (heap->num_free[o]) {
367 m = 1 << (heap->max_order - o);
368 *seg = find_first_bit(heap->bits[o], m);
369 MEMHEAP_VERBOSE(20,
370 "found free bit: order=%d, bits=0x%lx m=%d, *seg=%d",
371 o, heap->bits[o][0], m, *seg);
372 if (*seg < m)
373 goto found;
374 }
375 }
376
377 OPAL_THREAD_UNLOCK(&memheap_buddy.lock);
378 return OSHMEM_ERROR;
379
380 found:
381 clear_bit(*seg, heap->bits[o]);
382 --(heap->num_free[o]);
383
384 while (o > order) {
385 --o;
386 *seg <<= 1;
387 set_bit(*seg ^ 1, heap->bits[o]);
388 ++(heap->num_free[o]);
389 }
390
391 OPAL_THREAD_UNLOCK(&memheap_buddy.lock);
392 *seg <<= order;
393
394 return OSHMEM_SUCCESS;
395 }
396
397 static int _buddy_free(mca_memheap_buddy_module_t* buddy,
398 uint32_t seg,
399 unsigned order,
400 mca_memheap_buddy_heap_t *heap)
401 {
402 MEMHEAP_VERBOSE(20, "order=%d size=%d seg=%d", order, 1<<order, seg);
403 seg >>= order;
404 OPAL_THREAD_LOCK(&buddy->lock);
405
406 while (test_bit(seg ^ 1, heap->bits[order])) {
407 clear_bit(seg ^ 1, heap->bits[order]);
408 --(heap->num_free[order]);
409 seg >>= 1;
410 ++order;
411 }
412
413 set_bit(seg, heap->bits[order]);
414 ++(heap->num_free[order]);
415 OPAL_THREAD_UNLOCK(&buddy->lock);
416 return OSHMEM_SUCCESS;
417 }
418
419 static int buddy_free(mca_memheap_buddy_module_t* buddy,
420 uint32_t seg,
421 unsigned order)
422 {
423 return _buddy_free(buddy, seg, order, &buddy->heap);
424 }
425
426 static int buddy_private_free(mca_memheap_buddy_module_t* buddy,
427 uint32_t seg,
428 unsigned order)
429 {
430 return _buddy_free(buddy, seg, order, &buddy->private_heap);
431 }
432
433 static int _do_alloc(uint32_t order,
434 void **p_buff,
435 mca_memheap_buddy_heap_t *heap)
436 {
437 int rc;
438 unsigned long base;
439 uint32_t offset;
440 unsigned long addr;
441
442 if (order < heap->min_order)
443 order = heap->min_order;
444
445 *p_buff = 0;
446 if (order > heap->max_order) {
447
448 MEMHEAP_VERBOSE(5, "Allocation overflow of symmetric heap size");
449 return OSHMEM_ERROR;
450 }
451
452 base = (unsigned long) heap->symmetric_heap;
453
454 if (OSHMEM_SUCCESS != _buddy_alloc(order, &offset, heap)) {
455 MEMHEAP_VERBOSE(5, "Buddy Allocator failed to return a base address");
456 return OSHMEM_ERROR;
457 }
458
459
460 addr = base + offset;
461
462 rc = opal_hash_table_set_value_uint64(heap->symmetric_heap_hashtable,
463 addr,
464 (void *) (unsigned long) order);
465
466 if (OPAL_SUCCESS != rc) {
467 MEMHEAP_VERBOSE(5, "Failed to insert order to hashtable");
468 goto alloc_error;
469 }
470
471 *p_buff = (void*) addr;
472 MCA_SPML_CALL(memuse_hook(*p_buff, 1ULL<<order));
473 return OSHMEM_SUCCESS;
474
475 alloc_error: _buddy_free(&memheap_buddy, offset, order, heap);
476 return OSHMEM_ERROR;
477 }
478
479 static int do_alloc(uint32_t order, void **p_buff)
480 {
481 return _do_alloc(order, p_buff, &(memheap_buddy.heap));
482 }
483
484 static int do_private_alloc(uint32_t order, void **p_buff)
485 {
486 return _do_alloc(order, p_buff, &(memheap_buddy.private_heap));
487 }
488
489
490
491
492
493 int mca_memheap_buddy_alloc(size_t size, void** p_buff)
494 {
495
496 uint32_t order;
497
498 order = memheap_buddy_find_order(size);
499
500 return do_alloc(order, p_buff);
501 }
502
503 int mca_memheap_buddy_private_alloc(size_t size, void** p_buff)
504 {
505 uint32_t order;
506 int status = 0;
507 order = memheap_buddy_find_order(size);
508
509 status = do_private_alloc(order, p_buff);
510
511 MEMHEAP_VERBOSE(20, "private alloc addr: %p", *p_buff);
512
513 return status;
514 }
515
516 int mca_memheap_buddy_private_free(void* ptr)
517 {
518 int rc;
519 uint32_t offset;
520 unsigned long addr;
521 unsigned long base;
522 void *order;
523
524 if (0 == ptr) {
525 return OSHMEM_SUCCESS;
526 }
527
528 base = (unsigned long) memheap_buddy.private_heap.symmetric_heap;
529 addr = (unsigned long) ptr;
530 offset = addr - base;
531
532 rc =
533 opal_hash_table_get_value_uint64(memheap_buddy.private_heap.symmetric_heap_hashtable,
534 addr,
535 &order);
536 if (OPAL_SUCCESS != rc) {
537 return OSHMEM_ERROR;
538 }
539
540 buddy_private_free(&memheap_buddy,
541 offset,
542 (unsigned) (unsigned long) order);
543 opal_hash_table_remove_value_uint64(memheap_buddy.private_heap.symmetric_heap_hashtable,
544 addr);
545
546 return OSHMEM_SUCCESS;
547 }
548
549 int mca_memheap_buddy_align(size_t align, size_t size, void **p_buff)
550 {
551 uint32_t order;
552
553 if (align == 0) {
554 *p_buff = 0;
555 return OSHMEM_ERROR;
556 }
557
558
559 if (align & (align - 1)) {
560 *p_buff = 0;
561 return OSHMEM_ERROR;
562 }
563
564 order = memheap_buddy_find_order(size);
565 if ((unsigned long) align > (1UL << order))
566 order = memheap_buddy_find_order(align);
567
568 return do_alloc(order, p_buff);
569 }
570
571 int mca_memheap_buddy_realloc(size_t new_size, void *p_buff, void **p_new_buff)
572 {
573 int rc;
574 unsigned long addr;
575 void *order;
576 size_t old_size;
577 char *tmp_buf;
578
579
580 if (NULL == p_buff)
581 return mca_memheap_buddy_alloc(new_size, p_new_buff);
582
583 addr = (unsigned long) p_buff;
584
585 rc =
586 opal_hash_table_get_value_uint64(memheap_buddy.heap.symmetric_heap_hashtable,
587 addr,
588 &order);
589 if (OPAL_SUCCESS != rc) {
590 *p_new_buff = NULL;
591 return OSHMEM_ERROR;
592 }
593
594
595 if (0 == new_size) {
596 *p_new_buff = NULL;
597 return mca_memheap_buddy_free(p_buff);
598 }
599
600 old_size = 1UL << (unsigned long) order;
601
602
603 if (new_size <= old_size) {
604 *p_new_buff = p_buff;
605 return OSHMEM_SUCCESS;
606 }
607
608 if (new_size > (1UL << memheap_buddy.heap.max_order)) {
609 *p_new_buff = NULL;
610 return OSHMEM_ERR_OUT_OF_RESOURCE;
611 }
612
613 if (old_size + new_size >= (1UL << memheap_buddy.heap.max_order)) {
614
615
616 tmp_buf = (char *) malloc(old_size);
617 if (!tmp_buf)
618 return OSHMEM_ERR_OUT_OF_RESOURCE;
619 memcpy(tmp_buf, p_buff, old_size);
620 mca_memheap_buddy_free(p_buff);
621 } else
622 tmp_buf = p_buff;
623
624
625 rc = mca_memheap_buddy_alloc(new_size, p_new_buff);
626 if (OSHMEM_SUCCESS != rc) {
627 *p_new_buff = NULL;
628 if (old_size + new_size >= (1UL << memheap_buddy.heap.max_order)
629 && tmp_buf) {
630 free(tmp_buf);
631 }
632 return rc;
633 }
634
635 memcpy(*p_new_buff, tmp_buf, old_size);
636
637 if (old_size + new_size < (1UL << memheap_buddy.heap.max_order))
638 mca_memheap_buddy_free(p_buff);
639 else if (tmp_buf)
640 free(tmp_buf);
641
642 return OSHMEM_SUCCESS;
643 }
644
645
646
647
648
649 int mca_memheap_buddy_free(void* ptr)
650 {
651 int rc;
652 uint32_t offset;
653 unsigned long addr;
654 unsigned long base;
655 void *order;
656
657 base = (unsigned long) memheap_buddy.heap.symmetric_heap;
658 addr = (unsigned long) ptr;
659 offset = addr - base;
660
661 rc =
662 opal_hash_table_get_value_uint64(memheap_buddy.heap.symmetric_heap_hashtable,
663 addr,
664 &order);
665 if (OPAL_SUCCESS != rc) {
666 return OSHMEM_ERROR;
667 }
668
669 buddy_free(&memheap_buddy, offset, (unsigned) (unsigned long) order);
670 opal_hash_table_remove_value_uint64(memheap_buddy.heap.symmetric_heap_hashtable,
671 addr);
672
673 return OSHMEM_SUCCESS;
674 }
675
676 int mca_memheap_buddy_finalize()
677 {
678 MEMHEAP_VERBOSE(5, "deregistering symmetric heap");
679
680
681 if (memheap_buddy.heap.max_order == 0)
682 return OSHMEM_SUCCESS;
683
684
685 if (memheap_buddy.heap.symmetric_heap_hashtable) {
686 OBJ_RELEASE(memheap_buddy.heap.symmetric_heap_hashtable);
687 }
688 if (memheap_buddy.private_heap.symmetric_heap_hashtable) {
689 OBJ_RELEASE(memheap_buddy.private_heap.symmetric_heap_hashtable);
690 }
691
692 buddy_cleanup(&memheap_buddy);
693
694 return OSHMEM_SUCCESS;
695 }
696