6565
6666#endif // USE_PAGE
6767
68+ // Define if array-based block management is used.
69+ // Array-based block management
70+ // Pros: No additional data segment is needed.
71+ // Cons: Block size is large, so copying blocks is costly.
72+ // Linked list-based block management
73+ // Pros: Block size is small, so copying blocks is lightweight.
74+ // Cons: Each element has an additional data segment for linked list.
75+
76+ #define USE_ARRAY_BASED_BLOCK
77+
6878////////////////////////////////////////////////////////////////////////////////
6979// Utility
7080////////////////////////////////////////////////////////////////////////////////
@@ -400,8 +410,10 @@ static void write_extensible_array(struct extensible_array *p_array, int index,
400410////////////////////////////////////////////////////////////////////////////////
401411
402412struct element {
413+ #ifndef USE_ARRAY_BASED_BLOCK
403414 struct element * next ;
404415 // element is the first sizeof(element) bytes of an element.
416+ #endif
405417};
406418
407419#ifdef USE_PAGE
@@ -413,17 +425,21 @@ struct memory_bulk {
413425
414426struct block {
415427 int num_elements ;
428+ #ifdef USE_ARRAY_BASED_BLOCK
429+ struct element * elements [BLOCKSIZE ]; // This is part of block, so never freed.
430+ #else
416431 struct element * head ;
417432 struct element * tail ;
433+ #endif
418434};
419435
420436struct local_pool {
421437 int num_elements ;
422- struct block * blocks ;
423438#ifdef USE_PAGE
424439 size_t extra_mem_size ;
425440 void * p_extra_mem_ptr ;
426441#endif
442+ struct block blocks [LOCALPOOL_NUM_BLOCKS ];
427443} __attribute__((aligned (ZM_CACHELINE_SIZE )));
428444
429445struct global_pool {
@@ -453,23 +469,30 @@ static inline void atomic_insert_bulk(struct global_pool *p_global_pool, struct
453469 while (1 ) {
454470 struct memory_bulk * cur_bulk = p_global_pool -> bulk ;
455471 bulk -> next = cur_bulk ;
456- if (zm_atomic_compare_exchange_weak (& p_global_pool -> bulk , & cur_bulk , bulk , zm_memord_acq_rel , zm_memord_release ))
472+ if (zm_atomic_compare_exchange_weak (& p_global_pool -> bulk , & cur_bulk , bulk , zm_memord_acq_rel , zm_memord_acquire ))
457473 return ;
458474 }
459475}
460476#endif
461477
462478static inline void * element_to_ptr (struct element * element ) {
479+ #ifdef USE_ARRAY_BASED_BLOCK
480+ return (void * )element ;
481+ #else
463482 return (void * )(((char * )element ) + sizeof (struct element ));
483+ #endif
464484}
465485
466486static inline struct element * ptr_to_element (void * ptr ) {
487+ #ifdef USE_ARRAY_BASED_BLOCK
488+ return (struct element * )ptr ;
489+ #else
467490 return (struct element * )(((char * )ptr ) - sizeof (struct element ));
491+ #endif
468492}
469493
470494static struct local_pool * local_pool_create () {
471495 struct local_pool * local_pool = (struct local_pool * )aligned_calloc (sizeof (struct local_pool ));
472- local_pool -> blocks = (struct block * )aligned_calloc (sizeof (struct block ) * LOCALPOOL_NUM_BLOCKS );
473496 return local_pool ;
474497}
475498
@@ -563,7 +586,11 @@ int zm_pool_alloc(zm_pool_t handle, void **ptr) {
563586 }
564587 }
565588 if (GLOBAL_TO_LOCAL_NUM_BLOCKS != num_taken_blocks ) {
566- element_size = ((sizeof (struct element ) + global_pool -> element_size + MALLOC_ALIGNMENT - 1 ) / MALLOC_ALIGNMENT ) * MALLOC_ALIGNMENT ;
589+ #ifdef USE_ARRAY_BASED_BLOCK
590+ element_size = (global_pool -> element_size + MALLOC_ALIGNMENT - 1 ) & (~(MALLOC_ALIGNMENT - 1 ));
591+ #else
592+ element_size = (sizeof (struct element ) + global_pool -> element_size + MALLOC_ALIGNMENT - 1 ) & (~(MALLOC_ALIGNMENT - 1 ));
593+ #endif
567594 }
568595 }
569596 lock_release (& global_pool -> lock );
@@ -581,8 +608,12 @@ int zm_pool_alloc(zm_pool_t handle, void **ptr) {
581608
582609 struct block * block = & blocks [block_i ];
583610 int block_num_elements = 0 ;
611+ #ifdef USE_ARRAY_BASED_BLOCK
612+ struct element * * block_elements = block -> elements ;
613+ #else
584614 struct element * block_head = NULL ;
585615 struct element * block_tail = NULL ;
616+ #endif
586617 struct memory_bulk * new_bulk = NULL ;
587618
588619 while (num_remaining_elements ) {
@@ -601,23 +632,31 @@ int zm_pool_alloc(zm_pool_t handle, void **ptr) {
601632 struct element * new_element = (struct element * )p_extra_mem_ptr ;
602633 p_extra_mem_ptr += element_size ;
603634 extra_mem_size -= element_size ;
635+ #ifdef USE_ARRAY_BASED_BLOCK
636+ block_elements [block_num_elements ] = new_element ;
637+ #else
604638 new_element -> next = NULL ;
605- // Put it to a tail block.
606639 if (block_num_elements == 0 ) {
607640 block_head = new_element ;
608641 block_tail = new_element ;
609642 } else {
610643 block_tail -> next = new_element ;
611644 block_tail = new_element ;
612645 }
646+ #endif
613647 block_num_elements ++ ;
614648 if (block_num_elements == BLOCKSIZE ) {
649+ #ifndef USE_ARRAY_BASED_BLOCK
615650 block -> head = block_head ;
616651 block -> tail = block_tail ;
652+ #endif
617653 block -> num_elements = block_num_elements ;
618654 block_i ++ ;
619655 block = & blocks [block_i ];
620656 block_num_elements = 0 ;
657+ #ifdef USE_ARRAY_BASED_BLOCK
658+ block_elements = block -> elements ;
659+ #endif
621660 }
622661 num_remaining_elements -- ;
623662 }
@@ -636,28 +675,41 @@ int zm_pool_alloc(zm_pool_t handle, void **ptr) {
636675 struct block * blocks = local_pool -> blocks ;
637676 struct block * block = & blocks [block_i ];
638677 int block_num_elements = 0 ;
678+ #ifdef USE_ARRAY_BASED_BLOCK
679+ struct element * * block_elements = block -> elements ;
680+ #else
639681 struct element * block_head = NULL ;
640682 struct element * block_tail = NULL ;
683+ #endif
641684 for (int i = 0 ; i < num_remaining_elements ; i ++ ) {
642685 // Allocate all single elements.
643686 struct element * new_element = (struct element * )aligned_malloc (element_size );
644- new_element -> next = NULL ;
645687 // Put it to a tail block.
688+ #ifdef USE_ARRAY_BASED_BLOCK
689+ block_elements [block_num_elements ] = new_element ;
690+ #else
691+ new_element -> next = NULL ;
646692 if (block_num_elements == 0 ) {
647693 block_head = new_element ;
648694 block_tail = new_element ;
649695 } else {
650696 block_tail -> next = new_element ;
651697 block_tail = new_element ;
652698 }
699+ #endif
653700 block_num_elements ++ ;
654701 if (block_num_elements == BLOCKSIZE ) {
702+ #ifndef USE_ARRAY_BASED_BLOCK
655703 block -> head = block_head ;
656704 block -> tail = block_tail ;
705+ #endif
657706 block -> num_elements = block_num_elements ;
658707 block_i ++ ;
659708 block = & blocks [block_i ];
660709 block_num_elements = 0 ;
710+ #ifdef USE_ARRAY_BASED_BLOCK
711+ block_elements = block -> elements ;
712+ #endif
661713 }
662714 }
663715 assert (block_num_elements == 0 );
@@ -670,10 +722,14 @@ int zm_pool_alloc(zm_pool_t handle, void **ptr) {
670722 local_pool -> num_elements -= 1 ;
671723 int block_i = local_pool -> num_elements >> BLOCKSIZE_LOG ;
672724 struct block * block = & local_pool -> blocks [block_i ];
725+ #ifdef USE_ARRAY_BASED_BLOCK
726+ struct element * element = block -> elements [-- block -> num_elements ];
727+ #else
673728 struct element * element = block -> head ;
674729 struct element * next = element -> next ;
675730 block -> head = next ;
676731 block -> num_elements -= 1 ;
732+ #endif
677733 * ptr = element_to_ptr (element );
678734 }
679735 return 0 ;
@@ -734,6 +790,9 @@ int zm_pool_free(zm_pool_t handle, void *ptr) {
734790 local_pool -> num_elements += 1 ;
735791 struct block * block = & local_pool -> blocks [block_i ];
736792 struct element * element = ptr_to_element (ptr );
793+ #ifdef USE_ARRAY_BASED_BLOCK
794+ block -> elements [++ block -> num_elements ] = element ;
795+ #else
737796 if (zm_unlikely (block -> num_elements == 0 )) {
738797 block -> head = element ;
739798 block -> tail = element ;
@@ -743,6 +802,7 @@ int zm_pool_free(zm_pool_t handle, void *ptr) {
743802 block -> head = element ;
744803 }
745804 block -> num_elements += 1 ;
805+ #endif
746806 }
747807 return 0 ;
748808}
0 commit comments