@ -50,7 +50,7 @@ ck_bag_init(struct ck_bag *bag,
{
size_t block_overhead ;
bag - > avail_head = bag - > avail_tail = NULL ;
CK_LIST_INIT ( & bag - > avail_blocks ) ;
bag - > head = NULL ;
bag - > n_entries = 0 ;
bag - > n_blocks = 0 ;
@ -109,95 +109,50 @@ ck_bag_allocator_set(struct ck_malloc *m, size_t alloc_overhead)
bool
ck_bag_put_spmc ( struct ck_bag * bag , void * entry )
{
struct ck_bag_block * cursor , * new_block , * new_b lock_prev, * new_tail ;
struct ck_bag_block * cursor , * new_block , * new_b ag_head, * prev_block ;
uint16_t n_entries_block ;
size_t blocks_alloc , i ;
uintptr_t next = 0 ;
new_block = new_b lock_prev = new_tail = NULL ;
new_block = new_b ag_head = prev_block = NULL ;
/*
* Blocks with available entries are stored in
* the bag ' s available list .
*/
cursor = bag - > avail_head ;
cursor = CK_LIST_FIRST ( & bag - > avail_blocks ) ;
if ( cursor ! = NULL ) {
n_entries_block = ck_bag_block_count ( cursor ) ;
} else {
/* The bag is full, allocate a new set of blocks */
prev_block = CK_LIST_FIRST ( & bag - > avail_blocks ) ;
if ( bag - > alloc_strat = = CK_BAG_ALLOCATE_GEOMETRIC )
blocks_alloc = ( bag - > n_blocks + 1 ) < < 1 ;
else
blocks_alloc = 1 ;
for ( i = 0 ; i < blocks_alloc - 1 ; i + + ) {
for ( i = 0 ; i < blocks_alloc ; i + + ) {
new_block = allocator . malloc ( bag - > info . bytes ) ;
if ( new_block = = NULL )
return false ;
/*
* First node is the tail of the Bag .
* Second node is the new tail of the Available list .
*/
if ( i = = 0 )
new_tail = new_block ;
# ifndef __x86_64__
# ifdef __x86_64__
new_block - > next . ptr = NULL ;
# else
new_block - > next . n_entries = 0 ;
# endif
new_block - > next . ptr = new_block_prev ;
new_block - > avail_next = new_block_prev ;
if ( new_block_prev ! = NULL )
new_block_prev - > avail_prev = new_block ;
new_block_prev = new_block ;
if ( i = = 0 ) {
new_bag_head = new_block ;
CK_LIST_INSERT_HEAD ( & bag - > avail_blocks , new_block , avail_entry ) ;
} else {
CK_LIST_INSERT_AFTER ( prev_block , new_block , avail_entry ) ;
}
prev_block = new_block ;
}
/*
* Insert entry into last allocated block .
* cursor is new head of available list .
*/
cursor = allocator . malloc ( bag - > info . bytes ) ;
cursor - > avail_next = new_block ;
cursor - > avail_prev = NULL ;
new_block - > avail_prev = cursor ;
cursor = new_bag_head ;
n_entries_block = 0 ;
bag - > n_blocks + = blocks_alloc ; /* n_blocks and n_avail_blocks? */
}
/* Update the available list */
if ( new_block ! = NULL ) {
if ( bag - > avail_tail ! = NULL ) {
cursor - > avail_prev = bag - > avail_tail ;
bag - > avail_tail - > avail_next = cursor ;
} else {
/* Available list was previously empty */
bag - > avail_head = cursor ;
}
bag - > avail_tail = new_tail ;
} else if ( n_entries_block = = bag - > info . max - 1 ) {
/* New entry will fill up block, remove from avail list */
if ( cursor - > avail_prev ! = NULL )
cursor - > avail_prev - > avail_next = cursor - > avail_next ;
if ( cursor - > avail_next ! = NULL )
cursor - > avail_next - > avail_prev = cursor - > avail_prev ;
if ( bag - > avail_head = = cursor )
bag - > avail_head = cursor - > avail_next ;
if ( bag - > avail_tail = = cursor )
bag - > avail_tail = cursor - > avail_prev ;
/* For debugging purposes */
cursor - > avail_next = NULL ;
cursor - > avail_prev = NULL ;
bag - > n_blocks + = blocks_alloc ;
}
/* Update array and block->n_entries */
cursor - > array [ n_entries_block + + ] = entry ;
ck_pr_fence_store ( ) ;
@ -205,9 +160,9 @@ ck_bag_put_spmc(struct ck_bag *bag, void *entry)
next = ( ( uintptr_t ) n_entries_block < < 48 ) ;
# endif
/* Update bag's list */
if ( n_entries_block = = 1 ) {
if ( n_entries_block = = 1 ) {
/* Place newly filled block at the head of bag list */
if ( bag - > head ! = NULL ) {
# ifdef __x86_64__
next + = ( ( uintptr_t ) ( void * ) ck_bag_block_next ( bag - > head ) ) ;
@ -223,13 +178,17 @@ ck_bag_put_spmc(struct ck_bag *bag, void *entry)
ck_pr_store_ptr ( & cursor - > next . ptr , ( void * ) next ) ;
ck_pr_store_ptr ( & bag - > head , cursor ) ;
} else {
/* Block is already on bag list, update n_entries */
# ifdef __x86_64__
next + = ( ( uintptr_t ) ( void * ) ck_bag_block_next ( cursor - > next . ptr ) ) ;
ck_pr_store_ptr ( & cursor - > next , ( void * ) next ) ;
# else
ck_pr_store_ptr ( & cursor - > next . n_entries , ( void * ) ( uintptr_t ) n_entries_block ) ;
# endif
/* the block is full, remove from available_list */
if ( n_entries_block = = bag - > info . max ) {
CK_LIST_REMOVE ( cursor , avail_entry ) ;
}
}
@ -290,7 +249,6 @@ ck_bag_remove_spmc(struct ck_bag *bag, void *entry)
found :
/* Cursor points to containing block, block_index is index of deletion */
if ( n_entries = = 1 ) {
/* If a block's single entry is being removed, remove the block. */
if ( prev = = NULL ) {
struct ck_bag_block * new_head = ck_bag_block_next ( cursor - > next . ptr ) ;
ck_pr_store_ptr ( & bag - > head , new_head ) ;
@ -305,15 +263,8 @@ found:
ck_pr_store_ptr ( & prev - > next . ptr , ( struct ck_bag_block * ) next ) ;
}
/* Remove block from available list */
if ( cursor - > avail_prev ! = NULL )
cursor - > avail_prev - > avail_next = cursor - > avail_next ;
if ( cursor - > avail_next ! = NULL )
cursor - > avail_next - > avail_prev = cursor - > avail_prev ;
CK_LIST_REMOVE ( cursor , avail_entry ) ;
bag - > n_blocks - - ;
copy = cursor - > avail_next ;
} else {
uintptr_t next_ptr ;
@ -346,22 +297,13 @@ found:
# endif
}
if ( n_entries = = bag - > info . max - 1 ) {
/* Block was previously fully, add to head of avail. list */
copy - > avail_next = bag - > avail_head ;
copy - > avail_prev = NULL ;
bag - > avail_head = copy ;
if ( n_entries ! = bag - > info . max - 1 ) {
/* Only remove cursor if it was previously on the avail_list */
CK_LIST_REMOVE ( cursor , avail_entry ) ;
}
CK_LIST_INSERT_HEAD ( & bag - > avail_blocks , copy , avail_entry ) ;
}
/* Update available list. */
if ( bag - > avail_head = = cursor )
bag - > avail_head = copy ;
if ( bag - > avail_tail = = cursor )
bag - > avail_tail = copy ;
allocator . free ( cursor , sizeof ( struct ck_bag_block ) , true ) ;
ck_pr_store_uint ( & bag - > n_entries , bag - > n_entries - 1 ) ;
return true ;