-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsaneobj-demo-ref.c
50 lines (41 loc) · 1.13 KB
/
saneobj-demo-ref.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
#include "saneobj-demo-ref.h"
ReferencedObject_vt *vtReferencedObject(void) {
linkvt(ReferencedObject, Object) {
vt.take = ReferencedObject_take;
vt.release = ReferencedObject_release;
}
return &vt;
}
ReferencedObject *ReferencedObject_new(ReferencedObject *o, void *params) {
initnew(ReferencedObject);
return o;
}
// Usage: xadd(&refs, +1);
//
// Returns the old value of *dest.
// Due to it using Intel syntax, gcc must be given -masm=intel option or
// its assembler will error.
static int xadd(int *dest, int value) {
asm (
"LOCK XADD %0, %1"
// LOCK is only applicable to instructions which have a memory
// destination operand hence +m for *dest.
: "+m" (*dest), "+rm" (value)
:
: "cc"
);
return value;
}
int ReferencedObject_take(ReferencedObject *o) {
return xadd(&o->refs, +1);
}
// If returns 1, the object was freed; non-positive value may indicate an error
// or a highly concurrent environment; >1 indicates that more reference(s) are
// still held.
int ReferencedObject_release(ReferencedObject *o) {
int refs = xadd(&o->refs, -1);
if (refs == 1) {
delobj(o);
}
return refs;
}