aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_ractor.rb11
-rw-r--r--missing/dtoa.c13
2 files changed, 21 insertions, 3 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index b32a79063b..f1c3197275 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -158,6 +158,17 @@ assert_equal '[[:e1, 1], [:e2, 2]]', %q{
a #
}
+# dtoa race condition
+assert_equal '[:ok, :ok, :ok]', %q{
+ n = 3
+ n.times.map{
+ Ractor.new{
+ 10_000.times{ rand.to_s }
+ :ok
+ }
+ }.map(&:take)
+}
+
###
###
# Ractor still has several memory corruption so skip huge number of tests
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);
}