/usr/include/urcu/static/wfstack.h is in liburcu-dev 0.6.7-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #ifndef _URCU_WFSTACK_STATIC_H
#define _URCU_WFSTACK_STATIC_H
/*
* wfstack-static.h
*
* Userspace RCU library - Stack with Wait-Free push, Blocking pop.
*
* TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See wfstack.h for linking
* dynamically with the userspace rcu library.
*
* Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <pthread.h>
#include <assert.h>
#include <poll.h>
#include <urcu/compiler.h>
#include <urcu/uatomic.h>
#ifdef __cplusplus
extern "C" {
#endif
#define CDS_WF_STACK_END ((void *)0x1UL)
#define CDS_WFS_ADAPT_ATTEMPTS 10 /* Retry if being set */
#define CDS_WFS_WAIT 10 /* Wait 10 ms if being set */
static inline
void _cds_wfs_node_init(struct cds_wfs_node *node)
{
node->next = NULL;
}
static inline
void _cds_wfs_init(struct cds_wfs_stack *s)
{
int ret;
s->head = CDS_WF_STACK_END;
ret = pthread_mutex_init(&s->lock, NULL);
assert(!ret);
}
/*
* Returns 0 if stack was empty, 1 otherwise.
*/
static inline
int _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
{
struct cds_wfs_node *old_head;
assert(node->next == NULL);
/*
* uatomic_xchg() implicit memory barrier orders earlier stores to node
* (setting it to NULL) before publication.
*/
old_head = uatomic_xchg(&s->head, node);
/*
* At this point, dequeuers see a NULL node->next, they should busy-wait
* until node->next is set to old_head.
*/
CMM_STORE_SHARED(node->next, old_head);
return (old_head != CDS_WF_STACK_END);
}
/*
* Returns NULL if stack is empty.
*/
static inline
struct cds_wfs_node *
___cds_wfs_pop_blocking(struct cds_wfs_stack *s)
{
struct cds_wfs_node *head, *next;
int attempt = 0;
retry:
head = CMM_LOAD_SHARED(s->head);
if (head == CDS_WF_STACK_END)
return NULL;
/*
* Adaptative busy-looping waiting for push to complete.
*/
while ((next = CMM_LOAD_SHARED(head->next)) == NULL) {
if (++attempt >= CDS_WFS_ADAPT_ATTEMPTS) {
poll(NULL, 0, CDS_WFS_WAIT); /* Wait for 10ms */
attempt = 0;
} else
caa_cpu_relax();
}
if (uatomic_cmpxchg(&s->head, head, next) == head)
return head;
else
goto retry; /* Concurrent modification. Retry. */
}
static inline
struct cds_wfs_node *
_cds_wfs_pop_blocking(struct cds_wfs_stack *s)
{
struct cds_wfs_node *retnode;
int ret;
ret = pthread_mutex_lock(&s->lock);
assert(!ret);
retnode = ___cds_wfs_pop_blocking(s);
ret = pthread_mutex_unlock(&s->lock);
assert(!ret);
return retnode;
}
#ifdef __cplusplus
}
#endif
#endif /* _URCU_WFSTACK_STATIC_H */
|