Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin' into 1.8.7
Browse files Browse the repository at this point in the history
Conflicts:
	Gemfile.lock
	kernel/common/hash_hamt.rb
brixen committed Jan 28, 2015
2 parents 034f958 + e641668 commit 34e71c6
Showing 18 changed files with 291 additions and 164 deletions.
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
language: cpp

compiler:
- gcc
- clang

before_install:
- echo $LANG
- echo $LC_ALL
@@ -10,15 +12,23 @@ before_install:
- rvm use $RVM --install --binary --fuzzy
- gem update --system
- gem --version

before_script:
- travis_retry bundle
- if [ $TRAVIS_OS_NAME == linux ]; then travis_retry ./configure --llvm-config llvm-config-3.4; fi
- if [ $TRAVIS_OS_NAME == osx ]; then travis_retry ./configure --llvm-config /usr/local/opt/llvm/bin/llvm-config; fi

script: rake

after_success:
- if [ $TRAVIS_BRANCH == $TRAVIS_TAG ]; then rake deploy; fi

branches:
only:
- master
- 1.8.7
- /^v\d+\./

notifications:
email: false
irc:
@@ -32,9 +42,12 @@ notifications:
on_success: change
on_failure: always
on_start: false

env:
- RVM=2.0.0 LANG="en_US.UTF-8"

os:
- linux
- osx

osx_image: xcode61
27 changes: 25 additions & 2 deletions configure
Original file line number Diff line number Diff line change
@@ -597,8 +597,12 @@ Unsupported language version requested: #{version}. Options are #{@supported_ver
if which
config = File.join(which, "llvm-config")
elsif @darwin
out = `brew list llvm | grep '/llvm-config$'`
config = out.chomp if $?.success?
if macports?
config = macports_llvm_config
else
out = `brew list llvm | grep '/llvm-config$'`
config = out.chomp if $?.success?
end
end
end

@@ -1987,6 +1991,25 @@ Available commands are:
message.index("\n") != nil
end
end

# Returns true if MacPorts is installed in its default location.
def macports?
File.exists? '/opt/local/bin/port'
end

# Query MacPorts for the path to the latest installed version of
# llvm-config that is within the range of supported LLVM versions.
def macports_llvm_config
supported_versions = (3.0 .. 3.5)
installed_ports = `port installed | egrep -o 'llvm-[^ ]+'`.split
latest_usable_port = installed_ports.sort.select do |fname|
version = fname.match(/-\K.*/)[0].to_f
supported_versions.include? version
end.last
avail_binaries = `port contents #{latest_usable_port} |
fgrep llvm-config`.split
avail_binaries.reject { |fname| fname.include? 'libexec' }.last
end
end

STDOUT.sync = true
4 changes: 4 additions & 0 deletions rakelib/deploy.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
desc "Deploy a Rubinius release"
task :deploy do
puts "Deploying #{ENV["TRAVIS_TAG"]}..."
end
105 changes: 64 additions & 41 deletions vm/builtin/thread.cpp
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
#include "ontology.hpp"
#include "on_stack.hpp"
#include "metrics.hpp"
#include "util/logger.hpp"

/* HACK: returns a value that should identify a native thread
* for debugging threading issues. The winpthreads library
@@ -47,7 +48,7 @@ namespace rubinius {
}

Thread* Thread::create(STATE, VM* target, Object* self, Run runner,
bool system_thread)
bool internal_thread)
{
Thread* thr = state->vm()->new_object_mature<Thread>(G(thread));

@@ -75,7 +76,7 @@ namespace rubinius {
thr->klass(state, as<Class>(self));
thr->runner_ = runner;
thr->init_lock_.init();
thr->system_thread_ = system_thread;
thr->internal_thread_ = internal_thread;

target->thread.set(thr);

@@ -217,13 +218,22 @@ namespace rubinius {
return cFalse;
}

int Thread::start_new_thread(STATE, const pthread_attr_t &attrs) {
int Thread::start_thread(STATE, const pthread_attr_t &attrs) {
Thread* self = this;
OnStack<1> os(state, self);

self->init_lock_.lock();
int error = pthread_create(&self->vm_->os_thread(), &attrs, in_new_thread, (void*)self->vm_);
if(error) {

void* (*thread_function)(void *);

if(internal_thread_) {
thread_function = internal_thread;
} else {
thread_function = ruby_thread;
}

if(int error = pthread_create(&self->vm_->os_thread(),
&attrs, thread_function, (void*)self->vm_)) {
return error;
}

@@ -240,34 +250,17 @@ namespace rubinius {
return 0;
}

void* Thread::in_new_thread(void* ptr) {
VM* vm = reinterpret_cast<VM*>(ptr);

State state_obj(vm), *state = &state_obj;

int calculate_stack = 0;
NativeMethod::init_thread(state);

std::string thread_name;

{
std::ostringstream tn;
tn << "rbx.ruby." << vm->thread_id();
VM::set_current(vm, tn.str());
thread_name = tn.str();
}

RUBINIUS_THREAD_START(const_cast<RBX_DTRACE_CHAR_P>(thread_name.c_str()),
vm->thread_id(), 0);

void Thread::execute_thread(STATE, VM* vm) {
if(cDebugThreading) {
std::cerr << "[THREAD " << vm->thread_id()
<< " (" << (unsigned int)thread_debug_self() << ") started thread]\n";
utilities::logger::debug("Thread: start thread: id: %d, pthread: %d",
vm->thread_id(), (unsigned int)thread_debug_self());
}

GCTokenImpl gct;
int calculate_stack = 0;
vm->set_root_stack(reinterpret_cast<uintptr_t>(&calculate_stack), THREAD_STACK_SIZE);

GCTokenImpl gct;
NativeMethod::init_thread(state);

// Lock the thread object and unlock it at __run__ in the ruby land.
vm->thread->alive(state, cTrue);
@@ -300,25 +293,57 @@ namespace rubinius {
(*i)->unlock_for_terminate(state, gct, 0);
}

vm->thread->init_lock_.lock();
vm->thread->stopped();

NativeMethod::cleanup_thread(state);

vm->thread->stopped();
vm->thread->init_lock_.unlock();
if(cDebugThreading) {
utilities::logger::debug("Thread: exit thread: id: %d", vm->thread_id());
}
}

void* Thread::internal_thread(void* ptr) {
VM* vm = reinterpret_cast<VM*>(ptr);

vm->shared.clear_critical(state);
SharedState& shared = vm->shared;
State state_obj(vm), *state = &state_obj;

execute_thread(state, vm);

shared.gc_independent();

return 0;
}

void* Thread::ruby_thread(void* ptr) {
VM* vm = reinterpret_cast<VM*>(ptr);

SharedState& shared = vm->shared;
State state_obj(vm), *state = &state_obj;

std::string thread_name;

{
std::ostringstream tn;
tn << "rbx.ruby." << vm->thread_id();
VM::set_current(vm, tn.str());
thread_name = tn.str();
}

RUBINIUS_THREAD_START(const_cast<RBX_DTRACE_CHAR_P>(thread_name.c_str()),
vm->thread_id(), 0);

execute_thread(state, vm);

vm->thread->vm_ = NULL;
VM::discard(state, vm);

if(cDebugThreading) {
std::cerr << "[LOCK thread " << vm->thread_id() << " exited]\n";
}
shared.clear_critical(state);
shared.gc_independent();

RUBINIUS_THREAD_STOP(const_cast<RBX_DTRACE_CHAR_P>(thread_name.c_str()),
vm->thread_id(), 0);
shared.gc_independent();

return 0;
}

@@ -334,13 +359,12 @@ namespace rubinius {
pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);

int error = start_new_thread(state, attrs);

if(error) {
if(int error = start_thread(state, attrs)) {
char buf[RBX_STRERROR_BUFSIZE];
char* err = RBX_STRERROR(error, buf, RBX_STRERROR_BUFSIZE);
Exception::thread_error(state, err);
}

return cNil;
}

@@ -349,7 +373,7 @@ namespace rubinius {
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);

return start_new_thread(state, attrs);
return start_thread(state, attrs);
}

Object* Thread::pass(STATE, CallFrame* calling_environment) {
@@ -461,7 +485,6 @@ namespace rubinius {

void Thread::stopped() {
alive_ = cFalse;
vm_ = NULL;
}

void Thread::init_lock() {
18 changes: 9 additions & 9 deletions vm/builtin/thread.hpp
Original file line number Diff line number Diff line change
@@ -51,10 +51,8 @@ namespace rubinius {

utilities::thread::SpinLock init_lock_;

/// Whether this is an internal VM thread that should
/// not be exposed in Ruby land but does need to be a
/// managed thread.
bool system_thread_;
/// An internal thread, for example, the GC finalizer thread.
bool internal_thread_;

/// The VM state for this thread and this thread alone
VM* vm_;
@@ -98,8 +96,8 @@ namespace rubinius {
return vm_;
}

bool system_thread() const {
return system_thread_;
bool internal_thread() const {
return internal_thread_;
}

public:
@@ -291,10 +289,12 @@ namespace rubinius {
* @see Thread::allocate().
*/
static Thread* create(STATE, VM* target, Object* self, Run runner,
bool system_thread = false);
bool internal_thread = false);

int start_new_thread(STATE, const pthread_attr_t &attrs);
static void* in_new_thread(void*);
int start_thread(STATE, const pthread_attr_t &attrs);
static void execute_thread(STATE, VM* vm);
static void* internal_thread(void*);
static void* ruby_thread(void*);

public: /* TypeInfo */

2 changes: 2 additions & 0 deletions vm/console.cpp
Original file line number Diff line number Diff line change
@@ -223,6 +223,7 @@ namespace rubinius {
pthread_join(os, &return_value);
}

VM::discard(state, request_vm_);
request_vm_ = NULL;
}

@@ -238,6 +239,7 @@ namespace rubinius {
pthread_join(os, &return_value);
}

VM::discard(state, response_vm_);
response_vm_ = NULL;
}
}
2 changes: 1 addition & 1 deletion vm/environment.cpp
Original file line number Diff line number Diff line change
@@ -171,6 +171,7 @@ namespace rubinius {

void Environment::start_finalizer(STATE) {
finalizer_handler_ = new FinalizerHandler(state);
finalizer_handler_->start_thread(state);
}

void Environment::start_logging(STATE) {
@@ -809,7 +810,6 @@ namespace rubinius {
runtime.c_str(), runtime.size()));

load_kernel(runtime);
shared->finalizer_handler()->start_thread(state);

run_file(runtime + "/loader.rbc");

94 changes: 51 additions & 43 deletions vm/gc/finalize.cpp
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@

#include "gc/finalize.hpp"

#include "util/logger.hpp"

#include "dtrace/dtrace.h"

namespace rubinius {
@@ -70,7 +72,7 @@ namespace rubinius {
return current_ == end_;
}

Object* finalizer_handler_tramp(STATE) {
Object* finalizer_handler_trampoline(STATE) {
state->shared().finalizer_handler()->perform(state);
GCTokenImpl gct;
state->gc_dependent(gct, 0);
@@ -87,7 +89,8 @@ namespace rubinius {
, process_list_(NULL)
, iterator_(NULL)
, process_item_kind_(eRuby)
, exit_(false)
, thread_exit_(false)
, thread_running_(false)
, finishing_(false)
{
shared_.auxiliary_threads()->register_thread(this);
@@ -124,26 +127,36 @@ namespace rubinius {
utilities::thread::Mutex::LockGuard lg(worker_lock_);
vm_ = state->shared().new_vm();
vm_->metrics()->init(metrics::eFinalizerMetrics);
exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread), finalizer_handler_tramp, true));
thread_exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread),
finalizer_handler_trampoline, true));
run(state);
}

void FinalizerHandler::wakeup() {
utilities::thread::Mutex::LockGuard lg(worker_lock_);

thread_exit_ = true;
atomic::memory_barrier();

worker_signal();
}

void FinalizerHandler::stop_thread(STATE) {
SYNC(state);
if(!vm_) return;

pthread_t os = vm_->os_thread();
{
utilities::thread::Mutex::LockGuard lg(worker_lock_);
// Thread might have already been stopped
exit_ = true;
worker_signal();
}
if(vm_) {
wakeup();

void* return_value;
pthread_join(os, &return_value);
vm_ = NULL;
if(atomic::poll(thread_running_, false)) {
void* return_value;
pthread_t os = vm_->os_thread();
pthread_join(os, &return_value);
}

VM::discard(state, vm_);
vm_ = NULL;
}
}

void FinalizerHandler::shutdown(STATE) {
@@ -157,7 +170,8 @@ namespace rubinius {
worker_cond_.init();
supervisor_lock_.init();
supervisor_cond_.init();
exit_ = false;
thread_exit_ = false;
thread_running_ = false;
finishing_ = false;
vm_ = NULL;

@@ -178,9 +192,12 @@ namespace rubinius {
RUBINIUS_THREAD_START(const_cast<RBX_DTRACE_CHAR_P>(thread_name),
state->vm()->thread_id(), 1);

thread_running_ = true;

state->vm()->thread->hard_unlock(state, gct, 0);
state->gc_dependent(gct, 0);

while(!exit_) {
while(!thread_exit_) {
state->vm()->set_call_frame(0);

if(!process_list_) first_process_item();
@@ -190,19 +207,19 @@ namespace rubinius {
utilities::thread::Mutex::LockGuard lg(worker_lock_);

// exit_ might have been set after we grabbed the worker_lock
if(exit_) break;
if(thread_exit_) break;

state->gc_independent(gct, 0);
worker_wait();

if(exit_) break;
if(thread_exit_) break;
}

state->gc_dependent(gct, 0);

{
utilities::thread::Mutex::LockGuard lg(worker_lock_);
if(exit_) break;
if(thread_exit_) break;
}

continue;
@@ -211,6 +228,9 @@ namespace rubinius {
finalize(state);
next_process_item();
}

thread_running_ = false;

RUBINIUS_THREAD_STOP(const_cast<RBX_DTRACE_CHAR_P>(thread_name),
state->vm()->thread_id(), 1);
}
@@ -304,7 +324,7 @@ namespace rubinius {
process_list_ = NULL;
process_item_kind_ = eRuby;
lists_->pop_back();
vm_->metrics()->m.finalizer_metrics.objects_finalized++;
if(vm_) vm_->metrics()->m.finalizer_metrics.objects_finalized++;
break;
}
}
@@ -313,22 +333,10 @@ namespace rubinius {
void FinalizerHandler::finish(STATE, GCToken gct) {
finishing_ = true;

{
utilities::thread::Mutex::LockGuard lg(worker_lock_);

exit_ = true;
worker_signal();
}

if(!(process_list_ || !lists_->empty() || !live_list_->empty())) {
stop_thread(state);
return;
}

while(true) {
{
StopTheWorld stw(state, gct, 0);
stop_thread(state);

if(process_list_ || !lists_->empty() || !live_list_->empty()) {
while(true) {
if(!process_list_) {
if(live_list_->empty() && lists_->empty()) break;

@@ -348,24 +356,24 @@ namespace rubinius {
first_process_item();
if(!process_list_) break;
}
}

while(process_list_) {
finalize(state);
next_process_item();
while(process_list_) {
finalize(state);
next_process_item();
}
}
}

if(!lists_->empty() || !live_list_->empty() || process_list_ != NULL) {
rubinius::bug("FinalizerHandler exiting with pending finalizers");
utilities::logger::warn("FinalizerHandler exiting with pending finalizers");
}

stop_thread(state);
}

void FinalizerHandler::record(Object* obj, FinalizerFunction func) {
utilities::thread::Mutex::LockGuard lg(live_guard_);

if(finishing_) return;

FinalizeObject fi;
fi.object = obj;
fi.status = FinalizeObject::eLive;
4 changes: 3 additions & 1 deletion vm/gc/finalize.hpp
Original file line number Diff line number Diff line change
@@ -95,7 +95,8 @@ namespace rubinius {
utilities::thread::Condition worker_cond_;
utilities::thread::Mutex supervisor_lock_;
utilities::thread::Condition supervisor_cond_;
bool exit_;
bool thread_exit_;
bool thread_running_;
bool finishing_;

public:
@@ -124,6 +125,7 @@ namespace rubinius {
void worker_wait();
void supervisor_signal();
void supervisor_wait();
void wakeup();

void start_thread(STATE);
void stop_thread(STATE);
62 changes: 34 additions & 28 deletions vm/gc/immix_marker.cpp
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@

namespace rubinius {

Object* immix_marker_tramp(STATE) {
Object* immix_marker_trampoline(STATE) {
state->memory()->immix_marker()->perform(state);
GCTokenImpl gct;
state->gc_dependent(gct, 0);
@@ -28,8 +28,8 @@ namespace rubinius {
, vm_(NULL)
, immix_(immix)
, data_(NULL)
, exit_(false)
, running_(false)
, thread_exit_(false)
, thread_running_(false)
, thread_(state)
{
shared_.auxiliary_threads()->register_thread(this);
@@ -52,8 +52,8 @@ namespace rubinius {
run_lock_.init();
run_cond_.init();
vm_ = NULL;
running_ = false;
exit_ = false;
thread_running_ = false;
thread_exit_ = false;
}

void ImmixMarker::start_thread(STATE) {
@@ -62,32 +62,36 @@ namespace rubinius {
utilities::thread::Mutex::LockGuard lg(run_lock_);
vm_ = state->shared().new_vm();
vm_->metrics()->init(metrics::eRubyMetrics);
exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread), immix_marker_tramp, true));
thread_exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread),
immix_marker_trampoline, true));
run(state);
}

void ImmixMarker::stop_thread(STATE) {
SYNC(state);
if(!vm_) return;
void ImmixMarker::wakeup() {
utilities::thread::Mutex::LockGuard lg(run_lock_);

exit_ = true;
thread_exit_ = true;
atomic::memory_barrier();

{
GCIndependent guard(state, 0);
run_cond_.signal();
}

while(running_) {
atomic::pause();
run_cond_.signal();
}
}
void ImmixMarker::stop_thread(STATE) {
SYNC(state);

void* return_value;
pthread_t os = vm_->os_thread();
pthread_join(os, &return_value);
if(vm_) {
wakeup();

vm_ = NULL;
if(atomic::poll(thread_running_, false)) {
void* return_value;
pthread_t os = vm_->os_thread();
pthread_join(os, &return_value);
}

VM::discard(state, vm_);
vm_ = NULL;
}
}

void ImmixMarker::shutdown(STATE) {
@@ -125,9 +129,10 @@ namespace rubinius {
state->vm()->thread_id(), 1);

state->vm()->thread->hard_unlock(state, gct, 0);
running_ = true;

while(!exit_) {
thread_running_ = true;

while(!thread_exit_) {
if(data_) {
{
timer::StopWatch<timer::milliseconds> timer(
@@ -146,7 +151,7 @@ namespace rubinius {
}
}

if(exit_) break;
if(thread_exit_) break;

{
timer::StopWatch<timer::milliseconds> timer(
@@ -156,7 +161,7 @@ namespace rubinius {

// Finish and pause
while(!state->stop_the_world()) {
if(exit_) {
if(thread_exit_) {
state->restart_world();
break;
}
@@ -174,15 +179,16 @@ namespace rubinius {
delete data_;
data_ = NULL;
}
if(exit_) break;
if(thread_exit_) break;
state->gc_independent(gct, 0);
run_cond_.wait(run_lock_);
}
state->gc_dependent(gct, 0);
}

state->memory()->clear_mature_mark_in_progress();
running_ = false;

thread_running_ = false;

RUBINIUS_THREAD_STOP(const_cast<RBX_DTRACE_CHAR_P>(thread_name),
state->vm()->thread_id(), 1);
6 changes: 4 additions & 2 deletions vm/gc/immix_marker.hpp
Original file line number Diff line number Diff line change
@@ -20,8 +20,8 @@ namespace rubinius {
ImmixGC* immix_;
GCData* data_;

bool exit_;
bool running_;
bool thread_exit_;
bool thread_running_;

TypedRoot<Thread*> thread_;

@@ -37,6 +37,8 @@ namespace rubinius {

void initialize(STATE);

void wakeup();

void start_thread(STATE);
void stop_thread(STATE);

26 changes: 17 additions & 9 deletions vm/llvm/state.cpp
Original file line number Diff line number Diff line change
@@ -103,6 +103,7 @@ namespace rubinius {
, log_(NULL)
, enabled_(false)
, thread_exit_(false)
, thread_running_(false)
, current_compiler_(0)
{
state->shared().auxiliary_threads()->register_thread(this);
@@ -210,21 +211,28 @@ namespace rubinius {
}
}

void LLVMState::wakeup() {
utilities::thread::Mutex::LockGuard lg(compile_lock_);

thread_exit_ = true;
atomic::memory_barrier();

compile_cond_.signal();
}

void LLVMState::stop_thread(STATE) {
SYNC(state);

if(vm_) {
{
utilities::thread::Mutex::LockGuard lg(compile_lock_);
thread_exit_ = true;
compile_cond_.signal();
}
wakeup();

pthread_t os = vm_->os_thread();

void* return_value;
pthread_join(os, &return_value);
if(atomic::poll(thread_running_, false)) {
void* return_value;
pthread_t os = vm_->os_thread();
pthread_join(os, &return_value);
}

VM::discard(state, vm_);
vm_ = NULL;
}
}
3 changes: 3 additions & 0 deletions vm/llvm/state.hpp
Original file line number Diff line number Diff line change
@@ -114,6 +114,7 @@ namespace rubinius {

bool enabled_;
bool thread_exit_;
bool thread_running_;

jit::Compiler* current_compiler_;

@@ -294,6 +295,8 @@ namespace rubinius {
void perform(STATE);
void stop(STATE);

void wakeup();

void start_thread(STATE);
void stop_thread(STATE);

4 changes: 3 additions & 1 deletion vm/metrics.cpp
Original file line number Diff line number Diff line change
@@ -449,7 +449,8 @@ namespace rubinius {
if(!vm_) {
vm_ = state->shared().new_vm();
thread_exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread), metrics_trampoline, true));
thread_.set(Thread::create(state, vm_, G(thread),
metrics_trampoline, true));
}

if(thread_.get()->fork_attached(state)) {
@@ -469,6 +470,7 @@ namespace rubinius {
pthread_join(os, &return_value);
}

VM::discard(state, vm_);
vm_ = NULL;
}
}
2 changes: 1 addition & 1 deletion vm/shared_state.cpp
Original file line number Diff line number Diff line change
@@ -153,7 +153,7 @@ namespace rubinius {
++i) {
if(VM* vm = (*i)->as_vm()) {
Thread *thread = vm->thread.get();
if(!thread->system_thread() && CBOOL(thread->alive())) {
if(!thread->internal_thread() && CBOOL(thread->alive())) {
threads->append(state, thread);
}
}
73 changes: 51 additions & 22 deletions vm/signal.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "config.h"
#include "release.h"
#include "vm.hpp"
#include "call_frame.hpp"
#include "environment.hpp"
@@ -50,7 +51,7 @@ namespace rubinius {
// crashing inside the crash handler.
static struct utsname machine_info;

Object* signal_handler_tramp(STATE) {
Object* signal_handler_trampoline(STATE) {
state->shared().signal_handler()->perform(state);
GCTokenImpl gct;
state->gc_dependent(gct, 0);
@@ -63,7 +64,8 @@ namespace rubinius {
, target_(state->vm())
, vm_(NULL)
, queued_signals_(0)
, exit_(false)
, thread_exit_(false)
, thread_running_(false)
, thread_(state)
{
signal_handler_ = this;
@@ -88,6 +90,8 @@ namespace rubinius {
void SignalHandler::initialize(STATE) {
worker_lock_.init();
worker_cond_.init();
thread_exit_ = false;
thread_running_ = false;
vm_ = NULL;
}

@@ -97,26 +101,37 @@ namespace rubinius {
utilities::thread::Mutex::LockGuard lg(worker_lock_);
vm_ = state->shared().new_vm();
vm_->metrics()->init(metrics::eRubyMetrics);
exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread), signal_handler_tramp, true));
thread_exit_ = false;
thread_.set(Thread::create(state, vm_, G(thread),
signal_handler_trampoline, true));
run(state);
}

void SignalHandler::wakeup() {
utilities::thread::Mutex::LockGuard lg(worker_lock_);

thread_exit_ = true;

atomic::memory_barrier();

worker_cond_.signal();
}

void SignalHandler::stop_thread(STATE) {
SYNC(state);
if(!vm_) return;

pthread_t os = vm_->os_thread();
{
utilities::thread::Mutex::LockGuard lg(worker_lock_);
// Thread might have already been stopped
exit_ = true;
worker_cond_.signal();
}
if(vm_) {
wakeup();

void* return_value;
pthread_join(os, &return_value);
vm_ = NULL;
if(atomic::poll(thread_running_, false)) {
void* return_value;
pthread_t os = vm_->os_thread();
pthread_join(os, &return_value);
}

VM::discard(state, vm_);
vm_ = NULL;
}
}

void SignalHandler::shutdown(STATE) {
@@ -155,36 +170,41 @@ namespace rubinius {
RUBINIUS_THREAD_START(const_cast<RBX_DTRACE_CHAR_P>(thread_name),
state->vm()->thread_id(), 1);

thread_running_ = true;

state->vm()->thread->hard_unlock(state, gct, 0);

while(!exit_) {
while(!thread_exit_) {
{
utilities::thread::Mutex::LockGuard lg(worker_lock_);
if(exit_) break;
if(thread_exit_) break;
state->gc_independent(gct, 0);
worker_cond_.wait(worker_lock_);
// If we should exit now, don't try to become
// dependent first but break and exit the thread
if(exit_) break;
if(thread_exit_) break;
}
state->gc_dependent(gct, 0);
{
utilities::thread::Mutex::LockGuard lg(worker_lock_);
if(exit_) break;
if(thread_exit_) break;
}

target_->wakeup(state, gct, 0);
}

thread_running_ = false;

RUBINIUS_THREAD_STOP(const_cast<RBX_DTRACE_CHAR_P>(thread_name),
state->vm()->thread_id(), 1);
}

void SignalHandler::signal_tramp(int sig) {
void SignalHandler::signal_handler(int sig) {
signal_handler_->handle_signal(sig);
}

void SignalHandler::handle_signal(int sig) {
if(exit_) return;
if(thread_exit_) return;

target_->metrics()->system_metrics.os_signals_received++;

@@ -220,7 +240,7 @@ namespace rubinius {
action.sa_handler = SIG_IGN;
watched_signals_.push_back(sig);
} else {
action.sa_handler = signal_tramp;
action.sa_handler = signal_handler;
watched_signals_.push_back(sig);
}

@@ -406,6 +426,15 @@ namespace rubinius {
logger::fatal("machine: %s", machine_info.machine);
logger::fatal("--- end system info ---");

logger::fatal("--- begin rubinius info ---");
logger::fatal("program name: %s", RBX_PROGRAM_NAME);
logger::fatal("version: %s", RBX_VERSION);
logger::fatal("ruby version: %s", RBX_RUBY_VERSION);
logger::fatal("release date: %s", RBX_RELEASE_DATE);
logger::fatal("build revision: %s", RBX_BUILD_REV);
logger::fatal("llvm version: %s", RBX_LLVM_VERSION);
logger::fatal("--- end rubinius info ---");

logger::fatal("--- begin system backtrace ---");
for(i = 0; i < frames; i++) {
logger::fatal("%s", symbols[i]);
6 changes: 4 additions & 2 deletions vm/signal.hpp
Original file line number Diff line number Diff line change
@@ -24,7 +24,8 @@ namespace rubinius {
int pending_signals_[NSIG];
int queued_signals_;

bool exit_;
bool thread_exit_;
bool thread_running_;

TypedRoot<Thread*> thread_;

@@ -50,13 +51,14 @@ namespace rubinius {

void add_signal(State*, int sig, HandlerType type = eCustom);
void handle_signal(int sig);
static void signal_tramp(int sig);
static void signal_handler(int sig);

bool deliver_signals(STATE, CallFrame* call_frame);

void print_backtraces();

void open_pipes();
void wakeup();
void start_thread(STATE);
void stop_thread(STATE);

4 changes: 2 additions & 2 deletions vm/vm.cpp
Original file line number Diff line number Diff line change
@@ -109,9 +109,9 @@ namespace rubinius {
vm->shared.remove_vm(vm);
vm->unlock(state->vm());

delete vm;

state->vm()->metrics()->system_metrics.vm_threads--;

delete vm;
}

void VM::initialize_as_root() {

0 comments on commit 34e71c6

Please sign in to comment.