ck_bag: Add support for non x86_64 architectures. Memoize n_entries lookup when iterating over a bag.

Signed-off-by: Samy Al Bahra <sbahra@repnop.org>
ck_pring
Abel Mathew 13 years ago committed by Samy Al Bahra
parent 431c24a90a
commit 8e83963d63

@ -74,8 +74,17 @@ struct ck_bag_block_info {
#define CK_BAG_DEFAULT 0
struct ck_bag_block_md {
#ifdef __x86_64__
struct ck_bag_block *ptr;
#else
struct ck_bag_block *ptr;
uintptr_t n_entries CK_CC_PACKED;
#endif
};
struct ck_bag_block {
struct ck_bag_block *next;
struct ck_bag_block_md next;
struct ck_bag_block *avail_next;
struct ck_bag_block *avail_prev;
@ -99,6 +108,7 @@ typedef struct ck_bag ck_bag_t;
struct ck_bag_iterator {
struct ck_bag_block *block;
uint16_t index;
uint16_t n_entries;
};
typedef struct ck_bag_iterator ck_bag_iterator_t;
@ -108,7 +118,11 @@ CK_CC_INLINE static struct ck_bag_block *
ck_bag_block_next(struct ck_bag_block *block)
{
#ifdef __x86_64__
return (struct ck_bag_block *)((uintptr_t)block & ~CK_BAG_BLOCK_ENTRIES_MASK);
#else
return block;
#endif
}
CK_CC_INLINE static unsigned int
@ -122,7 +136,11 @@ CK_CC_INLINE static uint16_t
ck_bag_block_count(struct ck_bag_block *block)
{
return (uintptr_t)ck_pr_load_ptr(&block->next) >> 48;
#ifdef __x86_64__
return (uintptr_t)ck_pr_load_ptr(&block->next.ptr) >> 48;
#else
return (uintptr_t)ck_pr_load_ptr(&block->next.n_entries);
#endif
}
CK_CC_INLINE static void
@ -131,6 +149,7 @@ ck_bag_iterator_init(ck_bag_iterator_t *iterator, ck_bag_t *bag)
iterator->block = ck_pr_load_ptr(&bag->head);
iterator->index = 0;
iterator->n_entries = ck_bag_block_count(iterator->block);
return;
}
@ -143,14 +162,16 @@ ck_bag_next(struct ck_bag_iterator *iterator, void **entry)
if (iterator->block == NULL)
return NULL;
n_entries = ck_bag_block_count(iterator->block);
if (iterator->index >= n_entries) {
next = ck_pr_load_ptr(&iterator->block->next);
if (iterator->index >= iterator->n_entries) {
next = ck_pr_load_ptr(&iterator->block->next.ptr);
iterator->block = ck_bag_block_next(next);
if (iterator->block == NULL || ck_bag_block_count(iterator->block) == 0)
n_entries = (iterator->block != NULL) ?
ck_bag_block_count(iterator->block) : 0;
if (n_entries == 0)
return false;
iterator->index = 0;
iterator->n_entries = n_entries;
}
if (iterator->block == NULL)

@ -93,7 +93,7 @@ ck_bag_destroy(struct ck_bag *bag)
cursor = bag->head;
while (bag->head != NULL) {
cursor = bag->head;
bag->head = ck_bag_block_next(cursor->next);
bag->head = ck_bag_block_next(cursor->next.ptr);
allocator.free(cursor, bag->info.bytes, true);
}
@ -150,7 +150,7 @@ ck_bag_put_spmc(struct ck_bag *bag, void *entry)
if (i == 0)
new_tail = new_block;
new_block->next = new_block_prev;
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;
@ -167,7 +167,7 @@ ck_bag_put_spmc(struct ck_bag *bag, void *entry)
cursor->avail_prev = NULL;
new_block->avail_prev = cursor;
n_entries_block = 0;
bag->n_blocks += blocks_alloc;
bag->n_blocks += blocks_alloc; /* n_blocks and n_avail_blocks? */
}
/* Update the Available List */
@ -204,16 +204,34 @@ ck_bag_put_spmc(struct ck_bag *bag, void *entry)
/* Update array and block->n_entries */
cursor->array[n_entries_block++] = entry;
#ifdef __x86_64__
next = ((uintptr_t)n_entries_block << 48);
#endif
ck_pr_fence_store();
/* Update bag's list */
if (bag->head == NULL || n_entries_block == 1) {
next += ((uintptr_t)(void *)ck_bag_block_next(bag->head));
ck_pr_store_ptr(&cursor->next, (void *)next);
if (n_entries_block == 1) {
#ifdef __x86_64__
if (bag->head != NULL)
next += ((uintptr_t)(void *)ck_bag_block_next(bag->head));
#else
ck_pr_store_uint(&cursor->next.n_entries, n_entries_block);
next = ck_bag_block_next(bag->head->next.ptr);
#endif
ck_pr_store_ptr(&cursor->next.ptr, (void *)next);
ck_pr_store_ptr(&bag->head, cursor);
} else {
next += ((uintptr_t)(void *)ck_bag_block_next(cursor->next));
#ifdef __x86_64__
next += ((uintptr_t)(void *)ck_bag_block_next(cursor->next.ptr));
#else
ck_pr_store_uint(&cursor->next.n_entries, n_entries_block)
#endif
ck_pr_store_ptr(&cursor->next, (void *)next);
}
ck_pr_store_uint(&bag->n_entries, bag->n_entries + 1);
@ -246,7 +264,7 @@ ck_bag_set_spmc(struct ck_bag *bag, void *compare, void *update)
return true;
}
cursor = ck_bag_block_next(cursor->next);
cursor = ck_bag_block_next(cursor->next.ptr);
}
return ck_bag_put_spmc(bag, update);
@ -271,7 +289,7 @@ ck_bag_remove_spmc(struct ck_bag *bag, void *entry)
}
prev = cursor;
cursor = ck_bag_block_next(cursor->next);
cursor = ck_bag_block_next(cursor->next.ptr);
}
return true;
@ -281,12 +299,17 @@ found:
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);
struct ck_bag_block *new_head = ck_bag_block_next(cursor->next.ptr);
ck_pr_store_ptr(&bag->head, new_head);
} else {
uintptr_t next = ((uintptr_t)prev->next & (CK_BAG_BLOCK_ENTRIES_MASK)) |
(uintptr_t)(void *)ck_bag_block_next(cursor->next);
ck_pr_store_ptr(&prev->next, (struct ck_bag_block *)next);
uintptr_t next;
#ifdef __x86_64__
next = ((uintptr_t)prev->next.ptr & (CK_BAG_BLOCK_ENTRIES_MASK)) |
(uintptr_t)(void *)ck_bag_block_next(cursor->next.ptr);
#else
next = cursor->next.ptr;
#endif
ck_pr_store_ptr(&prev->next.ptr, (struct ck_bag_block *)next);
}
/* Remove block from available list */
@ -309,15 +332,24 @@ found:
ck_pr_fence_store();
next_ptr = (uintptr_t)(void *)ck_bag_block_next(copy->next);
copy->next = (void *)(((uintptr_t)n_entries << 48) | next_ptr);
next_ptr = (uintptr_t)(void *)ck_bag_block_next(copy->next.ptr);
#ifdef __x86_64__
copy->next.ptr = (void *)(((uintptr_t)n_entries << 48) | next_ptr);
#else
copy->next.n_entries = n_entries;
copy->next.ptr = next_ptr;
#endif
if (prev == NULL) {
ck_pr_store_ptr(&bag->head, copy);
} else {
uintptr_t next = ((uintptr_t)prev->next & (CK_BAG_BLOCK_ENTRIES_MASK)) |
#ifdef __x86_64__
uintptr_t next = ((uintptr_t)prev->next.ptr & (CK_BAG_BLOCK_ENTRIES_MASK)) |
(uintptr_t)(void *)ck_bag_block_next(copy);
ck_pr_store_ptr(&prev->next, (struct ck_bag_block *)next);
ck_pr_store_ptr(&prev->next.ptr, (struct ck_bag_block *)next);
#else
ck_pr_store_ptr(&prev->next.ptr, copy);
#endif
}
if (n_entries == bag->info.max - 1) {

Loading…
Cancel
Save