-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathqueue_lf_dw.c
More file actions
139 lines (111 loc) · 2.75 KB
/
queue_lf_dw.c
File metadata and controls
139 lines (111 loc) · 2.75 KB
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
131
132
133
134
135
136
137
138
139
#include "queue.h"
#include "dw.h"
#include "test.h"
#include "allocator.h"
#include "util.h"
#include "backoff.h"
#include <stdio.h>
#include <assert.h>
struct queue {
node_t *head __attribute__ ((__aligned__(CACHESIZE)));
node_t *tail __attribute__ ((__aligned__(CACHESIZE)));
};
void queue_init(struct queue **q)
{
node_t *node = new_node();
(*q) = (struct queue*)mapmem(sizeof(struct queue));
if (node == NULL) {
fprintf(stderr, "queue_init: out of memory\n");
}
node->next = NULL;
(*q)->head = node;
(*q)->tail = node;
}
void queue_destroy(struct queue **q)
{
free(*q);
}
void enqueue(struct queue *q, long key)
{
node_t *node;
node_t *t;
node_t *next;
backoff_reset();
retry:
/* Initialize the new node. */
critical_enter();
node = new_node();
assert(node);
node->key = key;
node->next = NULL;
/* Can't insert it if it's not pointing to NULL! */
write_barrier();
while (1) {
/* Get the old tail pointer. */
t = q->tail;
if (q->tail != t) {
continue;
}
/* Help update the tail pointer if needed. */
next = t->next;
if (next != NULL) {
CAS(&q->tail, t, next);
continue;
}
/* Attempt to link in the new element. */
if (CAS(&t->next, NULL, node)) {
break;
} else{
backoff_delay();
}
}
/* Swing the tail to the new element. */
CAS(&q->tail, t, node);
critical_exit();
}
long dequeue(struct queue *q)
{
node_t *h, *t, *next;
long data;
backoff_reset();
critical_enter();
while (1) {
/* Get the old head and tail elements. */
h = q->head;
t = q->tail;
/* Get the head element's successor. */
next = h->next;
memory_barrier();
if (q->head != h) {
continue;
}
/* If the head (dummy) element is the only one, return EMPTY. */
if (next == NULL) {
critical_exit();
return -1; /* Empty. */
}
/* There are multiple elements. Help update tail if needed. */
if (h == t) {
CAS(&q->tail, t, next);
continue;
}
/*
* Save the data of the head's successor. It will become the
* new dummy node.
*/
data = next->key;
/*
* Attempt to update the head pointer so that it points to the
* new dummy node.
*/
if (CAS(&q->head, h, next)) {
break;
} else{
backoff_delay();
}
}
/* The old dummy node has been unlinked, so reclaim it. */
free_node_later(h);
critical_exit();
return data;
}