aboutsummaryrefslogtreecommitdiffstats
path: root/missing
diff options
context:
space:
mode:
Diffstat (limited to 'missing')
-rw-r--r--missing/dtoa.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/missing/dtoa.c b/missing/dtoa.c
index 41b0a221d1..a940eabd91 100644
--- a/missing/dtoa.c
+++ b/missing/dtoa.c
@@ -526,6 +526,8 @@ typedef struct Bigint Bigint;
static Bigint *freelist[Kmax+1];
+#define BLOCKING_BIGINT ((Bigint *)(-1))
+
static Bigint *
Balloc(int k)
{
@@ -541,8 +543,10 @@ Balloc(int k)
rv = freelist[k];
while (rv) {
Bigint *rvn = rv;
- rv = ATOMIC_PTR_CAS(freelist[k], rv, rv->next);
- if (LIKELY(rvn == rv)) {
+ rv = ATOMIC_PTR_CAS(freelist[k], rv, BLOCKING_BIGINT);
+ if (LIKELY(rv != BLOCKING_BIGINT && rvn == rv)) {
+ rvn = ATOMIC_PTR_CAS(freelist[k], BLOCKING_BIGINT, rv->next);
+ assert(rvn == BLOCKING_BIGINT);
ASSUME(rv);
break;
}
@@ -589,7 +593,10 @@ Bfree(Bigint *v)
}
ACQUIRE_DTOA_LOCK(0);
do {
- vn = v->next = freelist[v->k];
+ do {
+ vn = ATOMIC_PTR_CAS(freelist[v->k], 0, 0);
+ } while (UNLIKELY(vn == BLOCKING_BIGINT));
+ v->next = vn;
} while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn));
FREE_DTOA_LOCK(0);
}