Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
rgbenson committed Feb 12, 2011
1 parent 3721d05 commit 5f56ad6
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
9 changes: 9 additions & 0 deletions b/source/stack_free_safe.sh
@@ -0,0 +1,9 @@
#!/bin/bash
set -x

set -e; make optflags='-DSTACK_FREE_SAFE_DEBUG=1' && sudo make install; set +e
#set -e; make optflags='-DXXXSTACK_FREE_SAFE_DEBUG=1' && sudo make install; set +e
PATH="/cnu/PACKAGES/ruby-ree-1.8.7-p253-thread-2-debian5/bin:$PATH" make test-all 2>&1 | tee log.txt

grep 'calling stack_free' log.txt | wc -l
grep 'calling stack_free' log.txt | grep stack_free_safe_all_dead_threads | wc -l
96 changes: 96 additions & 0 deletions eval.c
Expand Up @@ -1141,6 +1141,20 @@ rb_thread_t rb_main_thread;
#define main_thread rb_main_thread
#define curr_thread rb_curr_thread


#ifndef STACK_FREE_SAFE_DEBUG
#define STACK_FREE_SAFE_DEBUG 0
#endif

#if STACK_FREE_SAFE_DEBUG
#define stack_free_safe(TH,MSG) _stack_free_safe(TH,MSG)
#else
#define stack_free_safe(TH,MSG) _stack_free_safe(TH)
#endif


static void stack_free_safe_all_dead_threads();

static void scope_dup _((struct SCOPE *));

#define POP_SCOPE() \
Expand Down Expand Up @@ -10999,6 +11013,9 @@ rb_thread_restore_context_0(rb_thread_t th, int exit)
static int ex;
static VALUE tval;

/* Free any dead thread's stk_ptr. */
stack_free_safe_all_dead_threads();

rb_trap_immediate = 0; /* inhibit interrupts from here */
if (ruby_sandbox_restore != NULL) {
ruby_sandbox_restore(th);
Expand Down Expand Up @@ -11130,12 +11147,57 @@ rb_thread_ready(th)
}
}

static
rb_thread_t dead_thread_needs_stack_free = 0;

static
int dead_threads_need_stack_free = 0;

static int
_stack_free_safe (th
#if STACK_FREE_SAFE_DEBUG
, msg
#endif
)
rb_thread_t th;
#if STACK_FREE_SAFE_DEBUG
const char *msg;
#endif
{
if ( th->status == THREAD_KILLED && th->stk_ptr ) {
void *sp = (void*) &th;
#if STACK_FREE_SAFE_DEBUG
fprintf(stderr, "\n%s: stack_free_safe(%p): sp (%p): stk [%p, %p): ",
msg, th, sp, th->stk_ptr, th->stk_ptr + th->stk_size);
#endif
if ( (void*) th->stk_ptr <= sp && sp < (void*) (th->stk_ptr + th->stk_size) ) {
#if STACK_FREE_SAFE_DEBUG
fprintf(stderr, " cannot call stack_free(), yet. \n");
fflush(stderr);
#endif
dead_thread_needs_stack_free = th;
++ dead_threads_need_stack_free;
} else {
#if STACK_FREE_SAFE_DEBUG
fprintf(stderr, " calling stack_free(). \n");
fflush(stderr);
#endif
if ( dead_thread_needs_stack_free == th )
dead_thread_needs_stack_free = 0;
stack_free(th);
return 1; /* stack freed. */
}
}
return 0; /* stack not freed */
}

static void
rb_thread_die(th)
rb_thread_t th;
{
th->thgroup = 0;
th->status = THREAD_KILLED;
stack_free_safe(th, "rb_thread_die");
}

static void
Expand Down Expand Up @@ -13145,6 +13207,40 @@ rb_thread_wait_other_threads()
}
}

static void
stack_free_safe_all_dead_threads()
{
if ( dead_threads_need_stack_free ) {
rb_thread_t curr, th;
int left = dead_threads_need_stack_free;

#if STACK_FREE_SAFE_DEBUG
fprintf(stderr, "\nstack_free_safe_all_dead_threads(): %d\n", dead_threads_need_stack_free);
fflush(stderr);
#endif

/* stack_free_safe() will increment this flag if stack_free_safe(th) cannot call stack_free(). */
dead_threads_need_stack_free = 0;

/*
** Check the last known dead thread that needs stack_free().
** That thread might have been rb_thread_remove()'ed from the thread ring.
** Otherwise, start after current thread's stk_ptr, it should not be freeable anyway.
*/
if ( th = dead_thread_needs_stack_free ) {
if ( stack_free_safe(th, "stack_free_safe_all_dead_threads") )
if ( -- left <= 0 ) return;
}

curr = curr_thread;
FOREACH_THREAD_FROM(curr, th) {
if ( stack_free_safe(th, "stack_free_safe_all_dead_threads") )
if ( -- left <= 0 ) return;
}
END_FOREACH_FROM(curr, th);
}
}

static void
rb_thread_cleanup()
{
Expand Down

0 comments on commit 5f56ad6

Please sign in to comment.