diff --git a/src/runtime/atomic.h b/src/runtime/atomic.h new file mode 100644 index 00000000..d1ab1f23 --- /dev/null +++ b/src/runtime/atomic.h @@ -0,0 +1,30 @@ +#ifndef RUNTIME_ATOMIC_H_ +#define RUNTIME_ATOMIC_H_ + +#include + +#ifdef _WIN32 + +#include + +static inline uint32_t atomic_inc(volatile uint32_t *p) { + return InterlockedIncrement(p); +} + +static inline uint32_t atomic_dec(volatile uint32_t *p) { + return InterlockedDecrement(p); +} + +#else + +static inline uint32_t atomic_inc(volatile uint32_t *p) { + return __sync_add_and_fetch(p, 1u); +} + +static inline uint32_t atomic_dec(volatile uint32_t *p) { + return __sync_sub_and_fetch(p, 1u); +} + +#endif + +#endif // RUNTIME_ATOMIC_H_ diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 0174d3d8..85707c1b 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -5,6 +5,7 @@ #include #include #include "runtime/alloc.h" +#include "runtime/atomic.h" #include "runtime/tree.h" #include "runtime/length.h" #include "runtime/language.h" @@ -356,7 +357,7 @@ Tree *ts_tree_make_missing_leaf(TreePool *pool, TSSymbol symbol, const TSLanguag void ts_tree_retain(Tree *self) { assert(self->ref_count > 0); - self->ref_count++; + atomic_inc(&self->ref_count); assert(self->ref_count != 0); } @@ -366,8 +367,7 @@ void ts_tree_release(TreePool *pool, Tree *self) { while (pool->tree_stack.size > 0) { Tree *tree = array_pop(&pool->tree_stack); assert(tree->ref_count > 0); - tree->ref_count--; - if (tree->ref_count == 0) { + if (atomic_dec(&tree->ref_count) == 0) { if (tree->children.size > 0) { for (uint32_t i = 0; i < tree->children.size; i++) { array_push(&pool->tree_stack, tree->children.contents[i]); diff --git a/src/runtime/tree.h b/src/runtime/tree.h index da5f1e90..0eb6f929 100644 --- a/src/runtime/tree.h +++ b/src/runtime/tree.h @@ -29,7 +29,7 @@ typedef Array(Tree *) TreeArray; struct Tree { Length padding; Length size; - uint32_t ref_count; + volatile uint32_t ref_count; uint32_t bytes_scanned; uint32_t error_cost; uint32_t node_count;