Stack area in blocking region with -O0

-O0 e$B$G%3%s%Q%$%k$7$?e(B ruby e$B$G0J2<$N$h$&$K$9$k$H!“e(Bstack
e$B$Ne(B
mark e$B$GJQ$J$H$3$m$r%”%/%;%9$7$^$9!#e(B

% valgrind ./ruby -ve ‘Thread.new { gets }; 10.times { GC.start }’
==4690== Memcheck, a memory error detector.
==4690== Copyright © 2002-2007, and GNU GPL’d, by Julian Seward et al.
==4690== Using LibVEX rev 1854, a library for dynamic binary
translation.
==4690== Copyright © 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==4690== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation
framework.
==4690== Copyright © 2000-2007, and GNU GPL’d, by Julian Seward et al.
==4690== For more details, rerun with: -v
==4690==
ruby 1.9.2dev (2009-11-09 trunk 25699) [i686-linux]
==4690== Invalid read of size 4
==4690== at 0x80643AD: mark_locations_array (gc.c:1313)
==4690== by 0x8064575: gc_mark_locations (gc.c:1329)
==4690== by 0x8066182: rb_gc_mark_machine_stack (gc.c:2221)
==4690== by 0x814EC56: rb_thread_mark (vm.c:1630)
==4690== by 0x8064F07: gc_mark_children (gc.c:1713)
==4690== by 0x8064A11: gc_mark (gc.c:1508)
==4690== by 0x8064A3B: rb_gc_mark (gc.c:1514)
==4690== by 0x814E66F: vm_mark_each_thread_func (vm.c:1432)
==4690== by 0x80F3C2C: st_foreach (st.c:747)
==4690== by 0x814E6DC: rb_vm_mark (vm.c:1455)
==4690== by 0x8064F07: gc_mark_children (gc.c:1713)
==4690== by 0x8064A11: gc_mark (gc.c:1508)
==4690== Address 0x48d6140 is not stack’d, malloc’d or (recently)
free’d
==4690==
==4690== ERROR SUMMARY: 70 errors from 1 contexts (suppressed: 29 from
1)
==4690== malloc/free: in use at exit: 890,874 bytes in 13,756 blocks.
==4690== malloc/free: 15,651 allocs, 1,895 frees, 2,158,101 bytes
allocated.
==4690== For counts of detected errors, rerun with: -v
==4690== searching for pointers to 13,756 not-freed blocks.
==4690== checked 962,284 bytes.
==4690==
==4690== LEAK SUMMARY:
==4690== definitely lost: 222,005 bytes in 9,073 blocks.
==4690== possibly lost: 136 bytes in 1 blocks.
==4690== still reachable: 668,733 bytes in 4,682 blocks.
==4690== suppressed: 0 bytes in 0 blocks.
==4690== Rerun with --leak-check=full to see details of leaked memory.

e$BD4$Y$F$$k$H!"$3$NJQ$J$H$3$m$H$$$&$N$O!"%9%?%C%/$,[email protected]$H$3e(B
e$B$m$G$9!#$I$&$be(B rb_thread_t e$B$Ne(B machine_stack_end
e$B$r5-O?$7$?8ee(B
e$B$K%9%?%C%/$,=L$s$G$=$N%?%$%
%s%0$Ge(B GC e$B$,5/$-$k$H$$$&$3$H$N$he(B
e$B$&$G$9!#e(B

machine_stack_end e$B$N5-O?$+$i%9%l%C%I$N%9%$%C%A$K;j$k$^$G$K%9e(B
e$B%?%C%/$,=L$^$J$$$h$&[email protected]$G$-$^$9!#e(B

% svn diff --diff-cmd diff -x ‘-u -p’
Index: thread.c

— thread.c (revision 25700)
+++ thread.c (working copy)
@@ -97,13 +97,17 @@ static void set_unblock_function(rb_thre
struct rb_unblock_callback *old);
static void reset_unblock_function(rb_thread_t *th, const struct
rb_unblock_callback *old);

-static inline void blocking_region_begin(rb_thread_t *th, struct
rb_blocking_region_buffer *region,

  •       rb_unblock_function_t *func, void *arg);
    

static inline void blocking_region_end(rb_thread_t *th, struct
rb_blocking_region_buffer *region);

+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \

  • do { \
  • rb_gc_save_machine_context(th); \
  • SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
  • } while (0)

#define GVL_UNLOCK_BEGIN() do {
rb_thread_t *_th_stored = GET_THREAD(); \

  • rb_gc_save_machine_context(_th_stored); \
  • RB_GC_SAVE_MACHINE_CONTEXT(_th_stored);
    native_mutex_unlock(&_th_stored->vm->global_vm_lock)

#define GVL_UNLOCK_END()
@@ -960,7 +964,7 @@ rb_thread_schedule_rec(int sched_depth)

thread_debug(“rb_thread_schedule/switch start\n”);

  • rb_gc_save_machine_context(th);
  • RB_GC_SAVE_MACHINE_CONTEXT(th);
    native_mutex_unlock(&th->vm->global_vm_lock);
    {
    native_thread_yield();
    @@ -983,18 +987,16 @@ rb_thread_schedule(void)
    }

/* blocking region */
-static inline void
-blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer
*region,

  •      rb_unblock_function_t *func, void *arg)
    

-{

  • region->prev_status = th->status;
  • th->blocking_region_buffer = region;
  • set_unblock_function(th, func, arg, &region->oldubf);
  • th->status = THREAD_STOPPED;
  • thread_debug(“enter blocking region (%p)\n”, (void *)th);
  • rb_gc_save_machine_context(th);
  • native_mutex_unlock(&th->vm->global_vm_lock);
    -}
    +#define blocking_region_begin(th, region, func, arg) \
  • do { \
  • (region)->prev_status = (th)->status; \
  • (th)->blocking_region_buffer = (region); \
  • set_unblock_function((th), (func), (arg), &(region)->oldubf); \
  • (th)->status = THREAD_STOPPED; \
  • thread_debug(“enter blocking region (%p)\n”, (void *)(th)); \
  • RB_GC_SAVE_MACHINE_CONTEXT(th); \
  • native_mutex_unlock(&(th)->vm->global_vm_lock); \
  • } while (0)

static inline void
blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer
*region)
@@ -2599,7 +2601,6 @@ rb_gc_set_stack_end(VALUE **stack_end_p)
void
rb_gc_save_machine_context(rb_thread_t *th)
{

  • SET_MACHINE_STACK_END(&th->machine_stack_end);
    FLUSH_REGISTER_WINDOWS;
    #ifdef __ia64
    th->machine_register_stack_end = rb_ia64_bsp();