Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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.