Skip to content

Commit

Permalink
wfstack: implement mutex-free wfstack with transparent union
Browse files Browse the repository at this point in the history
This allows users more freedom to use alternative synchronization
mechanisms.

Changes since v1:
- Fix typos in cds_wfs_stack_ptr_t documentation.
  Thanks to Mathieu for spotting.

Signed-off-by: Eric Wong <[email protected]>
Cc: Paul E. McKenney <[email protected]>
Cc: Lai Jiangshan <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Signed-off-by: Mathieu Desnoyers <[email protected]>
  • Loading branch information
Eric Wong authored and compudj committed Sep 2, 2014
1 parent f637f19 commit 718eb63
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
18 changes: 15 additions & 3 deletions urcu/static/wfstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ void _cds_wfs_node_init(struct cds_wfs_node *node)
node->next = NULL;
}

/*
* __cds_wfs_init: initialize wait-free stack.
*/
static inline void ___cds_wfs_init(struct __cds_wfs_stack *s)
{
s->head = CDS_WFS_END;
}

/*
* cds_wfs_init: initialize wait-free stack.
*/
Expand All @@ -99,8 +107,10 @@ static inline bool ___cds_wfs_end(void *node)
*
* No memory barrier is issued. No mutual exclusion is required.
*/
static inline bool _cds_wfs_empty(struct cds_wfs_stack *s)
static inline bool _cds_wfs_empty(cds_wfs_stack_ptr_t u_stack)
{
struct __cds_wfs_stack *s = u_stack._s;

return ___cds_wfs_end(CMM_LOAD_SHARED(s->head));
}

Expand All @@ -114,8 +124,9 @@ static inline bool _cds_wfs_empty(struct cds_wfs_stack *s)
* Returns non-zero otherwise.
*/
static inline
int _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
int _cds_wfs_push(cds_wfs_stack_ptr_t u_stack, struct cds_wfs_node *node)
{
struct __cds_wfs_stack *s = u_stack._s;
struct cds_wfs_head *old_head, *new_head;

assert(node->next == NULL);
Expand Down Expand Up @@ -269,8 +280,9 @@ ___cds_wfs_pop_nonblocking(struct cds_wfs_stack *s)
*/
static inline
struct cds_wfs_head *
___cds_wfs_pop_all(struct cds_wfs_stack *s)
___cds_wfs_pop_all(cds_wfs_stack_ptr_t u_stack)
{
struct __cds_wfs_stack *s = u_stack._s;
struct cds_wfs_head *head;

/*
Expand Down
23 changes: 21 additions & 2 deletions urcu/wfstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,25 @@ struct cds_wfs_head {
struct cds_wfs_node node;
};

struct __cds_wfs_stack {
struct cds_wfs_head *head;
};

struct cds_wfs_stack {
struct cds_wfs_head *head;
pthread_mutex_t lock;
};

/*
* The transparent union allows calling functions that work on both
* struct cds_wfs_stack and struct __cds_wfs_stack on any of those two
* types.
*/
typedef union __attribute__((__transparent_union__)) {
struct __cds_wfs_stack *_s;
struct cds_wfs_stack *s;
} cds_wfs_stack_ptr_t;

#ifdef _LGPL_SOURCE

#include <urcu/static/wfstack.h>
Expand Down Expand Up @@ -135,12 +149,17 @@ extern void cds_wfs_node_init(struct cds_wfs_node *node);
*/
extern void cds_wfs_init(struct cds_wfs_stack *s);

/*
* __cds_wfs_init: initialize wait-free stack.
*/
extern void __cds_wfs_init(struct __cds_wfs_stack *s);

/*
* cds_wfs_empty: return whether wait-free stack is empty.
*
* No memory barrier is issued. No mutual exclusion is required.
*/
extern bool cds_wfs_empty(struct cds_wfs_stack *s);
extern bool cds_wfs_empty(cds_wfs_stack_ptr_t u_stack);

/*
* cds_wfs_push: push a node into the stack.
Expand All @@ -151,7 +170,7 @@ extern bool cds_wfs_empty(struct cds_wfs_stack *s);
* Returns 0 if the stack was empty prior to adding the node.
* Returns non-zero otherwise.
*/
extern int cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node);
extern int cds_wfs_push(cds_wfs_stack_ptr_t u_stack, struct cds_wfs_node *node);

/*
* cds_wfs_pop_blocking: pop a node from the stack.
Expand Down
9 changes: 7 additions & 2 deletions wfstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ void cds_wfs_init(struct cds_wfs_stack *s)
_cds_wfs_init(s);
}

void __cds_wfs_init(struct __cds_wfs_stack *s)
{
___cds_wfs_init(s);
}

bool cds_wfs_empty(struct cds_wfs_stack *s)
{
return _cds_wfs_empty(s);
Expand Down Expand Up @@ -112,7 +117,7 @@ struct cds_wfs_node *
return ___cds_wfs_pop_with_state_nonblocking(s, state);
}

struct cds_wfs_head *__cds_wfs_pop_all(struct cds_wfs_stack *s)
struct cds_wfs_head *__cds_wfs_pop_all(cds_wfs_stack_ptr_t u_stack)
{
return ___cds_wfs_pop_all(s);
return ___cds_wfs_pop_all(u_stack);
}

0 comments on commit 718eb63

Please sign in to comment.