Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Revert "Revert "Setup finalizer thread as an auxiliary thread""

This reverts commit 75537c1.
  • Loading branch information...
commit 9a748d03ad4f578c97eee0b65b620285170bd74e 1 parent f9cb075
@brixen brixen authored
View
14 vm/environment.cpp
@@ -32,6 +32,7 @@
#endif
#include "signal.hpp"
+#include "finalizer.hpp"
#include "object_utils.hpp"
#include "inline_cache.hpp"
@@ -82,7 +83,8 @@ namespace rubinius {
, argv_(argv)
, signature_(0)
, version_(0)
- , sig_handler_(NULL)
+ , signal_handler_(NULL)
+ , finalizer_handler_(NULL)
{
#ifdef ENABLE_LLVM
if(!llvm::llvm_start_multithreaded()) {
@@ -133,7 +135,8 @@ namespace rubinius {
}
Environment::~Environment() {
- delete sig_handler_;
+ delete signal_handler_;
+ delete finalizer_handler_;
VM::discard(state, root_vm);
SharedState::discard(shared);
@@ -312,7 +315,7 @@ namespace rubinius {
#endif
state->vm()->set_run_signals(true);
- sig_handler_ = new SignalHandler(state);
+ signal_handler_ = new SignalHandler(state);
#ifndef RBX_WINDOWS
// Ignore sigpipe.
@@ -349,6 +352,10 @@ namespace rubinius {
signal(SIGTERM, quit_handler);
}
+ void Environment::start_finalizer() {
+ finalizer_handler_ = new FinalizerHandler(state);
+ }
+
void Environment::load_vm_options(int argc, char**argv) {
/* Parse -X options from RBXOPT environment variable. We parse these
* first to permit arguments passed directly to the VM to override
@@ -892,6 +899,7 @@ namespace rubinius {
load_kernel(runtime);
start_signals();
+ start_finalizer();
run_file(runtime + "/loader.rbc");
state->vm()->thread_state()->clear();
View
5 vm/environment.hpp
@@ -13,6 +13,7 @@ namespace rubinius {
class ConfigParser;
class QueryAgent;
class SignalHandler;
+ class FinalizerHandler;
/**
* Thrown when unable to find Rubinius runtime directories.
@@ -56,7 +57,8 @@ namespace rubinius {
// The Ruby library version with which the .rbc file is compatible.
int version_;
- SignalHandler* sig_handler_;
+ SignalHandler* signal_handler_;
+ FinalizerHandler* finalizer_handler_;
std::string system_prefix_;
@@ -108,6 +110,7 @@ namespace rubinius {
int exit_code(STATE);
void start_signals();
+ void start_finalizer();
void start_agent(int port);
};
View
171 vm/finalizer.cpp
@@ -0,0 +1,171 @@
+#include "config.h"
+#include "vm.hpp"
+#include "finalizer.hpp"
+#include "on_stack.hpp"
+#include "objectmemory.hpp"
+
+#include "builtin/module.hpp"
+#include "builtin/array.hpp"
+
+#include "builtin/array.hpp"
+#include "builtin/module.hpp"
+#include "builtin/class.hpp"
+
+#include "capi/handle.hpp"
+
+#include "builtin/thread.hpp"
+
+namespace rubinius {
+
+ Object* finalizer_handler_tramp(STATE) {
+ state->shared().finalizer_handler()->perform(state);
+ return cNil;
+ }
+
+ FinalizerHandler::FinalizerHandler(STATE)
+ : AuxiliaryThread()
+ , shared_(state->shared())
+ , target_(state->vm())
+ , self_(NULL)
+ , thread_(state)
+ , exit_(false)
+ {
+ shared_.auxiliary_threads()->register_thread(this);
+ shared_.set_finalizer_handler(this);
+
+ lock_.init();
+ cond_.init();
+
+ start_thread(state);
+ }
+
+ FinalizerHandler::~FinalizerHandler() {
+ shared_.auxiliary_threads()->unregister_thread(this);
+ }
+
+ void FinalizerHandler::start_thread(STATE) {
+ SYNC(state);
+ if(self_) return;
+ self_ = state->shared().new_vm();
+ thread_.set(Thread::create(state, self_, G(thread), finalizer_handler_tramp, false, true));
+ run(state);
+ }
+
+ void FinalizerHandler::stop_thread(STATE) {
+ SYNC(state);
+ if(!self_) return;
+
+ // Thread might have already been stopped
+ pthread_t os = self_->os_thread();
+ exit_ = true;
+
+ cond_.signal();
+ void* return_value;
+ pthread_join(os, &return_value);
+ self_ = NULL;
+ }
+
+ void FinalizerHandler::shutdown(STATE) {
+ stop_thread(state);
+ }
+
+ void FinalizerHandler::before_exec(STATE) {
+ stop_thread(state);
+ }
+
+ void FinalizerHandler::after_exec(STATE) {
+ exit_ = false;
+ start_thread(state);
+ }
+
+ void FinalizerHandler::before_fork(STATE) {
+ stop_thread(state);
+ }
+
+ void FinalizerHandler::after_fork_parent(STATE) {
+ exit_ = false;
+ start_thread(state);
+ }
+
+ void FinalizerHandler::after_fork_child(STATE) {
+ exit_ = false;
+ cond_.init();
+ start_thread(state);
+ }
+
+ void FinalizerHandler::run(STATE) {
+ int error = thread_.get()->fork_attached(state);
+ if(error) rubinius::bug("Unable to start finalizer handler thread");
+ }
+
+ void FinalizerHandler::perform(STATE) {
+ GCTokenImpl gct;
+ utilities::thread::Thread::set_os_name("rbx.finalizer");
+
+ state->vm()->thread->hard_unlock(state, gct);
+
+ CallFrame* call_frame = 0;
+
+ while(!exit_) {
+ FinalizeObject* fi;
+
+ // Take the lock, remove the first one from the list,
+ // then process it.
+ {
+ utilities::thread::Mutex::LockGuard lg(lock_);
+
+ while(queue_.empty()) {
+ GCIndependent indy(state);
+ cond_.wait(lock_);
+ if(exit_) return;
+ }
+
+ fi = queue_.front();
+ queue_.pop_front();
+ }
+
+ state->vm()->set_call_frame(0);
+ if(fi->ruby_finalizer) {
+ // Rubinius specific code. If the finalizer is cTrue, then
+ // send the object the finalize message
+ if(fi->ruby_finalizer == cTrue) {
+ fi->object->send(state, call_frame, state->symbol("__finalize__"));
+ } else {
+ Array* ary = Array::create(state, 1);
+ ary->set(state, 0, fi->object->id(state));
+
+ OnStack<1> os(state, ary);
+
+ fi->ruby_finalizer->send(state, call_frame, G(sym_call), ary);
+ }
+ }
+
+ if(fi->finalizer) {
+ (*fi->finalizer)(state, fi->object);
+ }
+ // Unhook any handle used by fi->object so that we don't accidentally
+ // try and mark it later (after we've finalized it)
+ if(capi::Handle* handle = fi->object->handle(state)) {
+ handle->forget_object();
+ fi->object->clear_handle(state);
+ }
+
+ // If the object was remembered, unremember it.
+ if(fi->object->remembered_p()) {
+ state->memory()->unremember_object(fi->object);
+ }
+
+ fi->status = FinalizeObject::eFinalized;
+ }
+
+ }
+
+ void FinalizerHandler::schedule(FinalizeObject* fi) {
+ utilities::thread::Mutex::LockGuard lg(lock_);
+ queue_.push_back(fi);
+ }
+
+ void FinalizerHandler::signal() {
+ cond_.signal();
+ }
+}
View
56 vm/finalizer.hpp
@@ -0,0 +1,56 @@
+#ifndef RBX_FINALIZER_HPP
+#define RBX_FINALIZER_HPP
+
+#include "lock.hpp"
+#include "auxiliary_threads.hpp"
+
+#include "gc/finalize.hpp"
+#include "gc/root.hpp"
+
+#include <list>
+
+namespace rubinius {
+ class VM;
+ class State;
+ struct CallFrame;
+ class Thread;
+
+ Object* handle_tramp(STATE);
+
+ class FinalizerHandler : public AuxiliaryThread, public Lockable {
+ SharedState& shared_;
+ VM* target_;
+ VM* self_;
+
+ TypedRoot<Thread*> thread_;
+ std::list<FinalizeObject*> queue_;
+ utilities::thread::Mutex lock_;
+ utilities::thread::Condition cond_;
+ bool exit_;
+
+ public:
+
+ FinalizerHandler(STATE);
+ virtual ~FinalizerHandler();
+
+ void perform(State*);
+
+ void schedule(FinalizeObject* fi);
+ void signal();
+
+ void start_thread(STATE);
+ void stop_thread(STATE);
+
+ void shutdown(STATE);
+ void before_exec(STATE);
+ void after_exec(STATE);
+ void before_fork(STATE);
+ void after_fork_parent(STATE);
+ void after_fork_child(STATE);
+
+ void run(State*);
+ };
+}
+
+#endif
+
View
5 vm/gc/finalize.hpp
@@ -1,3 +1,6 @@
+#ifndef RBX_GC_FINALIZE_HPP
+#define RBX_GC_FINALIZE_HPP
+
namespace rubinius {
class Object;
@@ -31,3 +34,5 @@ namespace rubinius {
}
};
}
+
+#endif
View
95 vm/objectmemory.cpp
@@ -6,6 +6,7 @@
#include "config.h"
#include "vm.hpp"
#include "objectmemory.hpp"
+#include "finalizer.hpp"
#include "gc/marksweep.hpp"
#include "gc/baker.hpp"
#include "gc/immix.hpp"
@@ -54,8 +55,6 @@ namespace rubinius {
, allow_gc_(true)
, slab_size_(4096)
, running_finalizers_(false)
- , added_finalizers_(false)
- , finalizer_thread_(state, nil<Thread>())
, shared_(state->shared)
, collect_young_now(false)
@@ -106,8 +105,6 @@ namespace rubinius {
lock_init(state->vm());
contention_lock_.init();
finalizer_lock_.init();
- finalizer_var_.init();
- finalizer_thread_.set(nil<Thread>());
}
void ObjectMemory::assign_object_id(STATE, Object* obj) {
@@ -582,16 +579,11 @@ namespace rubinius {
}
state->restart_world();
- bool added = added_finalizers_;
- added_finalizers_ = false;
UNSYNC;
-
- if(added) {
- if(finalizer_thread_.get() == cNil) {
- start_finalizer_thread(state);
- }
- finalizer_var_.signal();
+ FinalizerHandler* finalizer = state->shared().finalizer_handler();
+ if(finalizer) {
+ finalizer->signal();
}
}
@@ -976,72 +968,7 @@ namespace rubinius {
}
void ObjectMemory::add_to_finalize(FinalizeObject* fi) {
- SCOPE_LOCK(ManagedThread::current(), finalizer_lock_);
- to_finalize_.push_back(fi);
- added_finalizers_ = true;
- }
-
- void ObjectMemory::in_finalizer_thread(STATE) {
- CallFrame* call_frame = 0;
- utilities::thread::Thread::set_os_name("rbx.finalizer");
-
- GCTokenImpl gct;
- state->vm()->thread->hard_unlock(state, gct);
-
- // Forever
- for(;;) {
- FinalizeObject* fi;
-
- // Take the lock, remove the first one from the list,
- // then process it.
- {
- SCOPE_LOCK(state->vm(), finalizer_lock_);
-
- state->vm()->set_call_frame(0);
-
- while(to_finalize_.empty()) {
- GCIndependent indy(state);
- finalizer_var_.wait(finalizer_lock_);
- }
-
- fi = to_finalize_.front();
- to_finalize_.pop_front();
- }
-
- if(fi->ruby_finalizer) {
- // Rubinius specific code. If the finalizer is cTrue, then
- // send the object the finalize message
- if(fi->ruby_finalizer == cTrue) {
- fi->object->send(state, call_frame, state->symbol("__finalize__"));
- } else {
- Array* ary = Array::create(state, 1);
- ary->set(state, 0, fi->object->id(state));
-
- OnStack<1> os(state, ary);
-
- fi->ruby_finalizer->send(state, call_frame, G(sym_call), ary);
- }
- }
-
- if(fi->finalizer) {
- (*fi->finalizer)(state, fi->object);
- }
- // Unhook any handle used by fi->object so that we don't accidentally
- // try and mark it later (after we've finalized it)
- if(capi::Handle* handle = fi->object->handle(state)) {
- handle->forget_object();
- fi->object->clear_handle(state);
- }
-
- // If the object was remembered, unremember it.
- if(fi->object->remembered_p()) {
- unremember_object(fi->object);
- }
-
- fi->status = FinalizeObject::eFinalized;
- }
-
- state->checkpoint(gct, 0);
+ shared_.finalizer_handler()->schedule(fi);
}
void ObjectMemory::run_all_finalizers(STATE) {
@@ -1087,18 +1014,6 @@ namespace rubinius {
running_finalizers_ = false;
}
- Object* in_finalizer(STATE) {
- state->shared().om->in_finalizer_thread(state);
- return cNil;
- }
-
- void ObjectMemory::start_finalizer_thread(STATE) {
- VM* vm = state->shared().new_vm();
- Thread* thr = Thread::create(state, vm, G(thread), in_finalizer, false, true);
- finalizer_thread_.set(thr);
- thr->fork(state);
- }
-
size_t& ObjectMemory::loe_usage() {
return mark_sweep_->allocated_bytes;
}
View
14 vm/objectmemory.hpp
@@ -167,24 +167,15 @@ namespace rubinius {
/// True if finalizers are currently being run.
bool running_finalizers_;
- /// True if finalizers were added in this GC cycle.
- bool added_finalizers_;
-
- /// A mutex which protects running the finalizers
+ /// A mutex which protects registering finalizers
rubinius::Mutex finalizer_lock_;
- /// A condition variable used to control access to
- /// to_finalize_
- utilities::thread::Condition finalizer_var_;
-
/// Mutex used to manage lock contention
utilities::thread::Mutex contention_lock_;
/// Condition variable used to manage lock contention
utilities::thread::Condition contention_var_;
- TypedRoot<Thread*> finalizer_thread_;
-
SharedState& shared_;
public:
@@ -382,9 +373,6 @@ namespace rubinius {
void inflate_for_id(STATE, ObjectHeader* obj, uint32_t id);
void inflate_for_handle(STATE, ObjectHeader* obj, capi::Handle* handle);
- void in_finalizer_thread(STATE);
- void start_finalizer_thread(STATE);
-
/// This only has one use! Don't use it!
Object* allocate_object_raw(size_t bytes);
View
1  vm/shared_state.cpp
@@ -33,6 +33,7 @@ namespace rubinius {
: initialized_(false)
, auxiliary_threads_(0)
, signal_handler_(0)
+ , finalizer_handler_(0)
, global_handles_(new capi::Handles)
, global_serial_(0)
, world_(new WorldState)
View
11 vm/shared_state.hpp
@@ -37,6 +37,7 @@ namespace rubinius {
}
class SignalHandler;
+ class FinalizerHandler;
class ObjectMemory;
class GlobalCache;
class ConfigParser;
@@ -65,6 +66,7 @@ namespace rubinius {
bool initialized_;
AuxiliaryThreads* auxiliary_threads_;
SignalHandler* signal_handler_;
+ FinalizerHandler* finalizer_handler_;
capi::Handles* global_handles_;
std::list<capi::Handle*> cached_handles_;
@@ -137,7 +139,14 @@ namespace rubinius {
signal_handler_ = thr;
}
- static SharedState* standalone(VM*);
+ FinalizerHandler* finalizer_handler() {
+ return finalizer_handler_;
+ }
+
+ void set_finalizer_handler(FinalizerHandler* thr) {
+ finalizer_handler_ = thr;
+ }
+
VM* new_vm();
void remove_vm(VM*);
View
12 vm/signal.cpp
@@ -21,11 +21,11 @@
#include "windows_compat.h"
namespace rubinius {
- static SignalHandler* handler_ = 0;
+ static SignalHandler* signal_handler_ = 0;
pthread_t main_thread;
- Object* handle_tramp(STATE) {
- handler_->perform(state);
+ Object* signal_handler_tramp(STATE) {
+ state->shared().signal_handler()->perform(state);
return cNil;
}
@@ -38,7 +38,7 @@ namespace rubinius {
, exit_(false)
, thread_(state)
{
- handler_ = this;
+ signal_handler_ = this;
main_thread = pthread_self();
shared_.auxiliary_threads()->register_thread(this);
@@ -62,7 +62,7 @@ namespace rubinius {
SYNC(state);
if(self_) return;
self_ = state->shared().new_vm();
- thread_.set(Thread::create(state, self_, G(thread), handle_tramp, false, true));
+ thread_.set(Thread::create(state, self_, G(thread), signal_handler_tramp, false, true));
run(state);
}
@@ -180,7 +180,7 @@ namespace rubinius {
}
void SignalHandler::signal_tramp(int sig) {
- handler_->handle_signal(sig);
+ signal_handler_->handle_signal(sig);
}
void SignalHandler::handle_signal(int sig) {
Please sign in to comment.
Something went wrong with that request. Please try again.