-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrc.c
108 lines (88 loc) · 1.74 KB
/
rc.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "rc.h"
#include <assert.h>
#include "allocator_malloc.h"
int increment_if_not_zero(unsigned long *p)
{
unsigned long old, new;
do {
old = *p;
if(old == 0)
return -1;//inc failed
new = old+1;
if(__sync_val_compare_and_swap(p, old, new) == old) break;
}while(1);
return 0;
}
void* lfrc_list_dec (node_t * nd)
{
lfrc_refcnt_dec(nd);
}
void* lfrc_list2_dec (node_t * nd)
{
lfrc_refcnt_dec(nd);
}
node_t* rc_new_node()
{
return new_node();
}
void rc_free_node(node_t* n)
{
free_node(n);
}
/* Reads a pointer to a node and increments that node's reference count. */
node_t *safe_read(node_t **p)
{
node_t *q;
node_t *safe;
while (1) {
q = *p;
safe = (node_t *)((long)q & -2);
if (safe == NULL)
return q;
if(increment_if_not_zero(&safe->rc))
continue;
memory_barrier();
/* If the pointer hasn't changed its value.... */
if (q == *p) {
return q;
} else
lfrc_refcnt_dec(safe);
}
}
/* Decrement reference count and see if the node can be safelfreereed. */
void lfrc_refcnt_dec(node_t *p)
{
/* It's possible to acquire a reference to a marked node, and then
* want to release it. This stops us from getting a bus error.
*/
p = (node_t *)((long)p & (-2));
if (p == NULL)
return;
/* 0 => no more references to this node, but someone else is already
* reclaiming it. */
memory_barrier();
assert(p->rc > 0);
//xadd return ol value
if (atomic_xadd4(&p->rc, -1) == 1)
{
p->gc++;//for osr
lfrc_refcnt_dec(p->next);
rc_free_node(p);
}
}
void lfrc_list2_inc(node_t* nd)
{
lfrc_refcnt_inc(nd);
}
void lfrc_list_inc(node_t* nd)
{
lfrc_refcnt_inc(nd);
}
/* Increment reference count. */
void lfrc_refcnt_inc(node_t *p)
{
if (p == NULL)
return;
atomic_xadd4(&p->rc, 1);
memory_barrier();
}