Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Revert "Setup finalizer thread as an auxiliary thread"

This reverts commit f0a86ed.

Revert for now since it seems to cause problems (see last comment in
 #2118), so needs further investigation.
  • Loading branch information...
commit 75537c1417abb5dfcefca25441a1271d7a20216e 1 parent 37598b9
@dbussink dbussink authored
View
14 vm/environment.cpp
@@ -32,7 +32,6 @@
#endif
#include "signal.hpp"
-#include "finalizer.hpp"
#include "object_utils.hpp"
#include "inline_cache.hpp"
@@ -83,8 +82,7 @@ namespace rubinius {
, argv_(argv)
, signature_(0)
, version_(0)
- , signal_handler_(NULL)
- , finalizer_handler_(NULL)
+ , sig_handler_(NULL)
{
#ifdef ENABLE_LLVM
if(!llvm::llvm_start_multithreaded()) {
@@ -135,8 +133,7 @@ namespace rubinius {
}
Environment::~Environment() {
- delete signal_handler_;
- delete finalizer_handler_;
+ delete sig_handler_;
VM::discard(state, root_vm);
SharedState::discard(shared);
@@ -315,7 +312,7 @@ namespace rubinius {
#endif
state->vm()->set_run_signals(true);
- signal_handler_ = new SignalHandler(state);
+ sig_handler_ = new SignalHandler(state);
#ifndef RBX_WINDOWS
// Ignore sigpipe.
@@ -352,10 +349,6 @@ 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
@@ -899,7 +892,6 @@ 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,7 +13,6 @@ namespace rubinius {
class ConfigParser;
class QueryAgent;
class SignalHandler;
- class FinalizerHandler;
/**
* Thrown when unable to find Rubinius runtime directories.
@@ -57,8 +56,7 @@ namespace rubinius {
// The Ruby library version with which the .rbc file is compatible.
int version_;
- SignalHandler* signal_handler_;
- FinalizerHandler* finalizer_handler_;
+ SignalHandler* sig_handler_;
std::string system_prefix_;
@@ -110,7 +108,6 @@ namespace rubinius {
int exit_code(STATE);
void start_signals();
- void start_finalizer();
void start_agent(int port);
};
View
171 vm/finalizer.cpp
@@ -1,171 +0,0 @@
-#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
@@ -1,56 +0,0 @@
-#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,6 +1,3 @@
-#ifndef RBX_GC_FINALIZE_HPP
-#define RBX_GC_FINALIZE_HPP
-
namespace rubinius {
class Object;
@@ -34,5 +31,3 @@ namespace rubinius {
}
};
}
-
-#endif
View
95 vm/objectmemory.cpp
@@ -6,7 +6,6 @@
#include "config.h"
#include "vm.hpp"
#include "objectmemory.hpp"
-#include "finalizer.hpp"
#include "gc/marksweep.hpp"
#include "gc/baker.hpp"
#include "gc/immix.hpp"
@@ -55,6 +54,8 @@ 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)
@@ -105,6 +106,8 @@ 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) {
@@ -579,11 +582,16 @@ namespace rubinius {
}
state->restart_world();
+ bool added = added_finalizers_;
+ added_finalizers_ = false;
UNSYNC;
- FinalizerHandler* finalizer = state->shared().finalizer_handler();
- if(finalizer) {
- finalizer->signal();
+
+ if(added) {
+ if(finalizer_thread_.get() == cNil) {
+ start_finalizer_thread(state);
+ }
+ finalizer_var_.signal();
}
}
@@ -968,7 +976,72 @@ namespace rubinius {
}
void ObjectMemory::add_to_finalize(FinalizeObject* fi) {
- shared_.finalizer_handler()->schedule(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);
}
void ObjectMemory::run_all_finalizers(STATE) {
@@ -1014,6 +1087,18 @@ 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,15 +167,24 @@ namespace rubinius {
/// True if finalizers are currently being run.
bool running_finalizers_;
- /// A mutex which protects registering finalizers
+ /// True if finalizers were added in this GC cycle.
+ bool added_finalizers_;
+
+ /// A mutex which protects running the 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:
@@ -373,6 +382,9 @@ 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,7 +33,6 @@ 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,7 +37,6 @@ namespace rubinius {
}
class SignalHandler;
- class FinalizerHandler;
class ObjectMemory;
class GlobalCache;
class ConfigParser;
@@ -66,7 +65,6 @@ namespace rubinius {
bool initialized_;
AuxiliaryThreads* auxiliary_threads_;
SignalHandler* signal_handler_;
- FinalizerHandler* finalizer_handler_;
capi::Handles* global_handles_;
std::list<capi::Handle*> cached_handles_;
@@ -139,14 +137,7 @@ namespace rubinius {
signal_handler_ = thr;
}
- FinalizerHandler* finalizer_handler() {
- return finalizer_handler_;
- }
-
- void set_finalizer_handler(FinalizerHandler* thr) {
- finalizer_handler_ = thr;
- }
-
+ static SharedState* standalone(VM*);
VM* new_vm();
void remove_vm(VM*);
View
12 vm/signal.cpp
@@ -21,11 +21,11 @@
#include "windows_compat.h"
namespace rubinius {
- static SignalHandler* signal_handler_ = 0;
+ static SignalHandler* handler_ = 0;
pthread_t main_thread;
- Object* signal_handler_tramp(STATE) {
- state->shared().signal_handler()->perform(state);
+ Object* handle_tramp(STATE) {
+ handler_->perform(state);
return cNil;
}
@@ -38,7 +38,7 @@ namespace rubinius {
, exit_(false)
, thread_(state)
{
- signal_handler_ = this;
+ 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), signal_handler_tramp, false, true));
+ thread_.set(Thread::create(state, self_, G(thread), handle_tramp, false, true));
run(state);
}
@@ -180,7 +180,7 @@ namespace rubinius {
}
void SignalHandler::signal_tramp(int sig) {
- signal_handler_->handle_signal(sig);
+ handler_->handle_signal(sig);
}
void SignalHandler::handle_signal(int sig) {
Please sign in to comment.
Something went wrong with that request. Please try again.