-
Notifications
You must be signed in to change notification settings - Fork 47
/
msqueue.c
84 lines (64 loc) · 1.41 KB
/
msqueue.c
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
#include <stdlib.h>
#include "delay.h"
#include "msqueue.h"
#include "primitives.h"
void queue_init(queue_t * q, int nprocs)
{
node_t * node = malloc(sizeof(node_t));
node->next = NULL;
q->head = node;
q->tail = node;
q->nprocs = nprocs;
}
void queue_register(queue_t * q, handle_t * th, int id)
{
hzdptr_init(&th->hzd, q->nprocs, 2);
}
void enqueue(queue_t * q, handle_t * handle, void * data)
{
node_t * node = malloc(sizeof(node_t));
node->data = data;
node->next = NULL;
node_t * tail;
node_t * next;
while (1) {
tail = hzdptr_setv(&q->tail, &handle->hzd, 0);
next = tail->next;
if (tail != q->tail) {
continue;
}
if (next != NULL) {
CAS(&q->tail, &tail, next);
continue;
}
if (CAS(&tail->next, &next, node)) break;
}
CAS(&q->tail, &tail, node);
}
void * dequeue(queue_t * q, handle_t * handle)
{
void * data;
node_t * head;
node_t * tail;
node_t * next;
while (1) {
head = hzdptr_setv(&q->head, &handle->hzd, 0);
tail = q->tail;
next = hzdptr_set(&head->next, &handle->hzd, 1);
if (head != q->head) {
continue;
}
if (next == NULL) {
return (void *) -1;
}
if (head == tail) {
CAS(&q->tail, &tail, next);
continue;
}
data = next->data;
if (CAS(&q->head, &head, next)) break;
}
hzdptr_retire(&handle->hzd, head);
return data;
}
void queue_free(int id, int nprocs) {}