Skip to content

Commit a190e22

Browse files
committed
ObjectSpace.{dump,dump_all,dump_shapes} needs vm barrier.
I had to add a RB_VM_LOCK_LOCK() and RB_VM_LOCK_UNLOCK() for native extensions.
1 parent 866e474 commit a190e22

File tree

3 files changed

+70
-24
lines changed

3 files changed

+70
-24
lines changed

ext/objspace/objspace_dump.c

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "ruby/util.h"
3030
#include "ruby/io.h"
3131
#include "vm_callinfo.h"
32-
#include "vm_core.h"
32+
#include "vm_sync.h"
3333

3434
RUBY_EXTERN const char ruby_hexdigits[];
3535

@@ -59,6 +59,7 @@ dump_flush(struct dump_config *dc)
5959
{
6060
if (dc->buffer_len) {
6161
if (dc->stream) {
62+
// use raw fwrite, don't allow context switch
6263
size_t written = fwrite(dc->buffer, sizeof(dc->buffer[0]), dc->buffer_len, dc->stream);
6364
if (written < dc->buffer_len) {
6465
MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written);
@@ -776,15 +777,23 @@ static VALUE
776777
objspace_dump(VALUE os, VALUE obj, VALUE output)
777778
{
778779
struct dump_config dc = {0,};
779-
if (!RB_SPECIAL_CONST_P(obj)) {
780-
dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
781-
}
780+
VALUE result = Qnil;
781+
RB_VM_LOCK_LOCK();
782+
{
783+
rb_vm_barrier();
784+
785+
if (!RB_SPECIAL_CONST_P(obj)) {
786+
dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
787+
}
782788

783-
dump_output(&dc, output, Qnil, Qnil, Qnil);
789+
dump_output(&dc, output, Qnil, Qnil, Qnil);
784790

785-
dump_object(obj, &dc);
791+
dump_object(obj, &dc);
786792

787-
return dump_result(&dc);
793+
result = dump_result(&dc);
794+
}
795+
RB_VM_LOCK_UNLOCK();
796+
return result;
788797
}
789798

790799
static void
@@ -840,35 +849,51 @@ static VALUE
840849
objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
841850
{
842851
struct dump_config dc = {0,};
843-
dump_output(&dc, output, full, since, shapes);
852+
VALUE result = Qnil;
853+
RB_VM_LOCK_LOCK();
854+
{
855+
rb_vm_barrier();
844856

845-
if (!dc.partial_dump || dc.since == 0) {
846-
/* dump roots */
847-
rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
848-
if (dc.roots) dump_append(&dc, "]}\n");
849-
}
857+
dump_output(&dc, output, full, since, shapes);
850858

851-
if (RTEST(shapes)) {
852-
rb_shape_each_shape_id(shape_id_i, &dc);
853-
}
859+
if (!dc.partial_dump || dc.since == 0) {
860+
/* dump roots */
861+
rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
862+
if (dc.roots) dump_append(&dc, "]}\n");
863+
}
864+
865+
if (RTEST(shapes)) {
866+
rb_shape_each_shape_id(shape_id_i, &dc);
867+
}
854868

855-
/* dump all objects */
856-
rb_objspace_each_objects(heap_i, &dc);
869+
/* dump all objects */
870+
rb_objspace_each_objects(heap_i, &dc);
857871

858-
return dump_result(&dc);
872+
result = dump_result(&dc);
873+
}
874+
RB_VM_LOCK_UNLOCK();
875+
return result;
859876
}
860877

861878
/* :nodoc: */
862879
static VALUE
863880
objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes)
864881
{
865882
struct dump_config dc = {0,};
866-
dump_output(&dc, output, Qfalse, Qnil, shapes);
883+
VALUE result = Qnil;
884+
RB_VM_LOCK_LOCK();
885+
{
886+
rb_vm_barrier();
887+
888+
dump_output(&dc, output, Qfalse, Qnil, shapes);
867889

868-
if (RTEST(shapes)) {
869-
rb_shape_each_shape_id(shape_id_i, &dc);
890+
if (RTEST(shapes)) {
891+
rb_shape_each_shape_id(shape_id_i, &dc);
892+
}
893+
result = dump_result(&dc);
870894
}
871-
return dump_result(&dc);
895+
RB_VM_LOCK_UNLOCK();
896+
return result;
872897
}
873898

874899
void

vm_sync.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,17 @@ rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec,
283283

284284
VM_ASSERT(recorded_lock_rec == rb_ec_vm_lock_rec(ec));
285285
}
286+
287+
// For extensions, to be used like: RB_VM_LOCK_LOCK()
288+
void
289+
rb_vm_lock_lock(const char *file, int line)
290+
{
291+
rb_vm_lock(file, line);
292+
}
293+
294+
295+
// for extensions, to be used like: RB_VM_LOCK_UNLOCK
296+
void rb_vm_lock_unlock(const char *file, int line)
297+
{
298+
rb_vm_unlock(file, line);
299+
}

vm_sync.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ NOINLINE(void rb_vm_lock_enter_body_nb(unsigned int *lev APPEND_LOCATION_ARGS));
2626
NOINLINE(void rb_vm_lock_enter_body(unsigned int *lev APPEND_LOCATION_ARGS));
2727
void rb_vm_lock_leave_body_nb(unsigned int *lev APPEND_LOCATION_ARGS);
2828
void rb_vm_lock_leave_body(unsigned int *lev APPEND_LOCATION_ARGS);
29-
void rb_vm_barrier(void);
29+
30+
RUBY_SYMBOL_EXPORT_BEGIN
31+
NOINLINE(void rb_vm_barrier(void));
32+
NOINLINE(void rb_vm_lock_lock(const char *file, int line));
33+
NOINLINE(void rb_vm_lock_unlock(const char *file, int line));
34+
RUBY_SYMBOL_EXPORT_END
35+
#define RB_VM_LOCK_LOCK() rb_vm_lock_lock(__FILE__, __LINE__)
36+
#define RB_VM_LOCK_UNLOCK() rb_vm_lock_unlock(__FILE__, __LINE__)
3037

3138
#if RUBY_DEBUG
3239
// GET_VM()

0 commit comments

Comments
 (0)