Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions concurrent_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "internal/gc.h"
#include "internal/concurrent_set.h"
#include "ruby/atomic.h"
#include "ruby/ractor.h"
#include "vm_sync.h"

#define CONCURRENT_SET_CONTINUATION_BIT ((VALUE)1 << (sizeof(VALUE) * CHAR_BIT - 1))
Expand Down Expand Up @@ -102,6 +103,9 @@ rb_concurrent_set_new(const struct rb_concurrent_set_funcs *funcs, int capacity)
set->funcs = funcs;
set->entries = ZALLOC_N(struct concurrent_set_entry, capacity);
set->capacity = capacity;
/* The set is reachable from every Ractor (e.g. via C globals such as the
* frozen-string and symbol tables), so mark it shareable. */
RB_OBJ_SET_SHAREABLE(obj);
return obj;
}

Expand Down
1 change: 1 addition & 0 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -2353,6 +2353,7 @@ concurrent_set.$(OBJEXT): {$(VPATH)}missing.h
concurrent_set.$(OBJEXT): {$(VPATH)}node.h
concurrent_set.$(OBJEXT): {$(VPATH)}onigmo.h
concurrent_set.$(OBJEXT): {$(VPATH)}oniguruma.h
concurrent_set.$(OBJEXT): {$(VPATH)}ractor.h
concurrent_set.$(OBJEXT): {$(VPATH)}ruby_assert.h
concurrent_set.$(OBJEXT): {$(VPATH)}ruby_atomic.h
concurrent_set.$(OBJEXT): {$(VPATH)}rubyparser.h
Expand Down
4 changes: 4 additions & 0 deletions id_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,10 @@ rb_managed_id_table_dup(VALUE old_table)
{
struct rb_id_table *new_tbl;
VALUE obj = TypedData_Make_Struct(0, struct rb_id_table, RTYPEDDATA_TYPE(old_table), new_tbl);
/* A managed id table hangs off VM-global state (e.g. a shape tree's edge
* table grows via this dup) and is reachable from every Ractor, so mark it
* shareable. */
RB_OBJ_SET_SHAREABLE(obj);
struct rb_id_table *old_tbl = managed_id_table_ptr(old_table);
rb_id_table_init(new_tbl, old_tbl->num + 1);
rb_id_table_foreach(old_tbl, managed_id_table_dup_i, new_tbl);
Expand Down
3 changes: 3 additions & 0 deletions symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym)
if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(id_entry_list = rb_ary_entry(ids, (long)idx))) {
rb_darray_make(&entries, ID_ENTRY_UNIT);
id_entry_list = TypedData_Wrap_Struct(0, &sym_id_entry_list_type, entries);
/* Reachable from every Ractor via the global symbol table, so mark it
* shareable. */
RB_OBJ_SET_SHAREABLE(id_entry_list);
rb_ary_store(ids, (long)idx, id_entry_list);
}
else {
Expand Down
7 changes: 7 additions & 0 deletions test/ruby/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,13 @@ def test_ractor_new_raises_isolation_error_if_proc_uses_yield
end
end

def test_ractor_does_not_inherit_fiber_storage
assert_ractor(<<~'RUBY')
Fiber[:key] = "creator"
assert_nil Ractor.new { Fiber[:key] }.value
RUBY
end

def assert_make_shareable(obj)
refute Ractor.shareable?(obj), "object was already shareable"
Ractor.make_shareable(obj)
Expand Down
6 changes: 4 additions & 2 deletions vm_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1950,8 +1950,10 @@ rb_postponed_job_flush(rb_vm_t *vm)
while (triggered_bits) {
unsigned int i = bit_length(triggered_bits) - 1;
triggered_bits ^= ((1UL) << i); /* toggle ith bit off */
rb_postponed_job_func_t func = pjq->table[i].func;
void *data = pjq->table[i].data;
/* Read atomically to pair with the atomic CAS/EXCHANGE stores in
* rb_postponed_job_preregister, which can run on another thread. */
rb_postponed_job_func_t func = (rb_postponed_job_func_t)(uintptr_t)RUBY_ATOMIC_PTR_LOAD(pjq->table[i].func);
void *data = RUBY_ATOMIC_PTR_LOAD(pjq->table[i].data);
(func)(data);
}

Expand Down