Skip to content
This repository
Browse code

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
Dirkjan Bussink dbussink authored
14 vm/environment.cpp
@@ -32,7 +32,6 @@
32 32 #endif
33 33
34 34 #include "signal.hpp"
35   -#include "finalizer.hpp"
36 35 #include "object_utils.hpp"
37 36
38 37 #include "inline_cache.hpp"
@@ -83,8 +82,7 @@ namespace rubinius {
83 82 , argv_(argv)
84 83 , signature_(0)
85 84 , version_(0)
86   - , signal_handler_(NULL)
87   - , finalizer_handler_(NULL)
  85 + , sig_handler_(NULL)
88 86 {
89 87 #ifdef ENABLE_LLVM
90 88 if(!llvm::llvm_start_multithreaded()) {
@@ -135,8 +133,7 @@ namespace rubinius {
135 133 }
136 134
137 135 Environment::~Environment() {
138   - delete signal_handler_;
139   - delete finalizer_handler_;
  136 + delete sig_handler_;
140 137
141 138 VM::discard(state, root_vm);
142 139 SharedState::discard(shared);
@@ -315,7 +312,7 @@ namespace rubinius {
315 312 #endif
316 313
317 314 state->vm()->set_run_signals(true);
318   - signal_handler_ = new SignalHandler(state);
  315 + sig_handler_ = new SignalHandler(state);
319 316
320 317 #ifndef RBX_WINDOWS
321 318 // Ignore sigpipe.
@@ -352,10 +349,6 @@ namespace rubinius {
352 349 signal(SIGTERM, quit_handler);
353 350 }
354 351
355   - void Environment::start_finalizer() {
356   - finalizer_handler_ = new FinalizerHandler(state);
357   - }
358   -
359 352 void Environment::load_vm_options(int argc, char**argv) {
360 353 /* Parse -X options from RBXOPT environment variable. We parse these
361 354 * first to permit arguments passed directly to the VM to override
@@ -899,7 +892,6 @@ namespace rubinius {
899 892 load_kernel(runtime);
900 893
901 894 start_signals();
902   - start_finalizer();
903 895 run_file(runtime + "/loader.rbc");
904 896
905 897 state->vm()->thread_state()->clear();
5 vm/environment.hpp
@@ -13,7 +13,6 @@ namespace rubinius {
13 13 class ConfigParser;
14 14 class QueryAgent;
15 15 class SignalHandler;
16   - class FinalizerHandler;
17 16
18 17 /**
19 18 * Thrown when unable to find Rubinius runtime directories.
@@ -57,8 +56,7 @@ namespace rubinius {
57 56 // The Ruby library version with which the .rbc file is compatible.
58 57 int version_;
59 58
60   - SignalHandler* signal_handler_;
61   - FinalizerHandler* finalizer_handler_;
  59 + SignalHandler* sig_handler_;
62 60
63 61 std::string system_prefix_;
64 62
@@ -110,7 +108,6 @@ namespace rubinius {
110 108 int exit_code(STATE);
111 109
112 110 void start_signals();
113   - void start_finalizer();
114 111 void start_agent(int port);
115 112 };
116 113
171 vm/finalizer.cpp
... ... @@ -1,171 +0,0 @@
1   -#include "config.h"
2   -#include "vm.hpp"
3   -#include "finalizer.hpp"
4   -#include "on_stack.hpp"
5   -#include "objectmemory.hpp"
6   -
7   -#include "builtin/module.hpp"
8   -#include "builtin/array.hpp"
9   -
10   -#include "builtin/array.hpp"
11   -#include "builtin/module.hpp"
12   -#include "builtin/class.hpp"
13   -
14   -#include "capi/handle.hpp"
15   -
16   -#include "builtin/thread.hpp"
17   -
18   -namespace rubinius {
19   -
20   - Object* finalizer_handler_tramp(STATE) {
21   - state->shared().finalizer_handler()->perform(state);
22   - return cNil;
23   - }
24   -
25   - FinalizerHandler::FinalizerHandler(STATE)
26   - : AuxiliaryThread()
27   - , shared_(state->shared())
28   - , target_(state->vm())
29   - , self_(NULL)
30   - , thread_(state)
31   - , exit_(false)
32   - {
33   - shared_.auxiliary_threads()->register_thread(this);
34   - shared_.set_finalizer_handler(this);
35   -
36   - lock_.init();
37   - cond_.init();
38   -
39   - start_thread(state);
40   - }
41   -
42   - FinalizerHandler::~FinalizerHandler() {
43   - shared_.auxiliary_threads()->unregister_thread(this);
44   - }
45   -
46   - void FinalizerHandler::start_thread(STATE) {
47   - SYNC(state);
48   - if(self_) return;
49   - self_ = state->shared().new_vm();
50   - thread_.set(Thread::create(state, self_, G(thread), finalizer_handler_tramp, false, true));
51   - run(state);
52   - }
53   -
54   - void FinalizerHandler::stop_thread(STATE) {
55   - SYNC(state);
56   - if(!self_) return;
57   -
58   - // Thread might have already been stopped
59   - pthread_t os = self_->os_thread();
60   - exit_ = true;
61   -
62   - cond_.signal();
63   - void* return_value;
64   - pthread_join(os, &return_value);
65   - self_ = NULL;
66   - }
67   -
68   - void FinalizerHandler::shutdown(STATE) {
69   - stop_thread(state);
70   - }
71   -
72   - void FinalizerHandler::before_exec(STATE) {
73   - stop_thread(state);
74   - }
75   -
76   - void FinalizerHandler::after_exec(STATE) {
77   - exit_ = false;
78   - start_thread(state);
79   - }
80   -
81   - void FinalizerHandler::before_fork(STATE) {
82   - stop_thread(state);
83   - }
84   -
85   - void FinalizerHandler::after_fork_parent(STATE) {
86   - exit_ = false;
87   - start_thread(state);
88   - }
89   -
90   - void FinalizerHandler::after_fork_child(STATE) {
91   - exit_ = false;
92   - cond_.init();
93   - start_thread(state);
94   - }
95   -
96   - void FinalizerHandler::run(STATE) {
97   - int error = thread_.get()->fork_attached(state);
98   - if(error) rubinius::bug("Unable to start finalizer handler thread");
99   - }
100   -
101   - void FinalizerHandler::perform(STATE) {
102   - GCTokenImpl gct;
103   - utilities::thread::Thread::set_os_name("rbx.finalizer");
104   -
105   - state->vm()->thread->hard_unlock(state, gct);
106   -
107   - CallFrame* call_frame = 0;
108   -
109   - while(!exit_) {
110   - FinalizeObject* fi;
111   -
112   - // Take the lock, remove the first one from the list,
113   - // then process it.
114   - {
115   - utilities::thread::Mutex::LockGuard lg(lock_);
116   -
117   - while(queue_.empty()) {
118   - GCIndependent indy(state);
119   - cond_.wait(lock_);
120   - if(exit_) return;
121   - }
122   -
123   - fi = queue_.front();
124   - queue_.pop_front();
125   - }
126   -
127   - state->vm()->set_call_frame(0);
128   - if(fi->ruby_finalizer) {
129   - // Rubinius specific code. If the finalizer is cTrue, then
130   - // send the object the finalize message
131   - if(fi->ruby_finalizer == cTrue) {
132   - fi->object->send(state, call_frame, state->symbol("__finalize__"));
133   - } else {
134   - Array* ary = Array::create(state, 1);
135   - ary->set(state, 0, fi->object->id(state));
136   -
137   - OnStack<1> os(state, ary);
138   -
139   - fi->ruby_finalizer->send(state, call_frame, G(sym_call), ary);
140   - }
141   - }
142   -
143   - if(fi->finalizer) {
144   - (*fi->finalizer)(state, fi->object);
145   - }
146   - // Unhook any handle used by fi->object so that we don't accidentally
147   - // try and mark it later (after we've finalized it)
148   - if(capi::Handle* handle = fi->object->handle(state)) {
149   - handle->forget_object();
150   - fi->object->clear_handle(state);
151   - }
152   -
153   - // If the object was remembered, unremember it.
154   - if(fi->object->remembered_p()) {
155   - state->memory()->unremember_object(fi->object);
156   - }
157   -
158   - fi->status = FinalizeObject::eFinalized;
159   - }
160   -
161   - }
162   -
163   - void FinalizerHandler::schedule(FinalizeObject* fi) {
164   - utilities::thread::Mutex::LockGuard lg(lock_);
165   - queue_.push_back(fi);
166   - }
167   -
168   - void FinalizerHandler::signal() {
169   - cond_.signal();
170   - }
171   -}
56 vm/finalizer.hpp
... ... @@ -1,56 +0,0 @@
1   -#ifndef RBX_FINALIZER_HPP
2   -#define RBX_FINALIZER_HPP
3   -
4   -#include "lock.hpp"
5   -#include "auxiliary_threads.hpp"
6   -
7   -#include "gc/finalize.hpp"
8   -#include "gc/root.hpp"
9   -
10   -#include <list>
11   -
12   -namespace rubinius {
13   - class VM;
14   - class State;
15   - struct CallFrame;
16   - class Thread;
17   -
18   - Object* handle_tramp(STATE);
19   -
20   - class FinalizerHandler : public AuxiliaryThread, public Lockable {
21   - SharedState& shared_;
22   - VM* target_;
23   - VM* self_;
24   -
25   - TypedRoot<Thread*> thread_;
26   - std::list<FinalizeObject*> queue_;
27   - utilities::thread::Mutex lock_;
28   - utilities::thread::Condition cond_;
29   - bool exit_;
30   -
31   - public:
32   -
33   - FinalizerHandler(STATE);
34   - virtual ~FinalizerHandler();
35   -
36   - void perform(State*);
37   -
38   - void schedule(FinalizeObject* fi);
39   - void signal();
40   -
41   - void start_thread(STATE);
42   - void stop_thread(STATE);
43   -
44   - void shutdown(STATE);
45   - void before_exec(STATE);
46   - void after_exec(STATE);
47   - void before_fork(STATE);
48   - void after_fork_parent(STATE);
49   - void after_fork_child(STATE);
50   -
51   - void run(State*);
52   - };
53   -}
54   -
55   -#endif
56   -
5 vm/gc/finalize.hpp
... ... @@ -1,6 +1,3 @@
1   -#ifndef RBX_GC_FINALIZE_HPP
2   -#define RBX_GC_FINALIZE_HPP
3   -
4 1 namespace rubinius {
5 2
6 3 class Object;
@@ -34,5 +31,3 @@ namespace rubinius {
34 31 }
35 32 };
36 33 }
37   -
38   -#endif
95 vm/objectmemory.cpp
@@ -6,7 +6,6 @@
6 6 #include "config.h"
7 7 #include "vm.hpp"
8 8 #include "objectmemory.hpp"
9   -#include "finalizer.hpp"
10 9 #include "gc/marksweep.hpp"
11 10 #include "gc/baker.hpp"
12 11 #include "gc/immix.hpp"
@@ -55,6 +54,8 @@ namespace rubinius {
55 54 , allow_gc_(true)
56 55 , slab_size_(4096)
57 56 , running_finalizers_(false)
  57 + , added_finalizers_(false)
  58 + , finalizer_thread_(state, nil<Thread>())
58 59 , shared_(state->shared)
59 60
60 61 , collect_young_now(false)
@@ -105,6 +106,8 @@ namespace rubinius {
105 106 lock_init(state->vm());
106 107 contention_lock_.init();
107 108 finalizer_lock_.init();
  109 + finalizer_var_.init();
  110 + finalizer_thread_.set(nil<Thread>());
108 111 }
109 112
110 113 void ObjectMemory::assign_object_id(STATE, Object* obj) {
@@ -579,11 +582,16 @@ namespace rubinius {
579 582 }
580 583
581 584 state->restart_world();
  585 + bool added = added_finalizers_;
  586 + added_finalizers_ = false;
582 587
583 588 UNSYNC;
584   - FinalizerHandler* finalizer = state->shared().finalizer_handler();
585   - if(finalizer) {
586   - finalizer->signal();
  589 +
  590 + if(added) {
  591 + if(finalizer_thread_.get() == cNil) {
  592 + start_finalizer_thread(state);
  593 + }
  594 + finalizer_var_.signal();
587 595 }
588 596 }
589 597
@@ -968,7 +976,72 @@ namespace rubinius {
968 976 }
969 977
970 978 void ObjectMemory::add_to_finalize(FinalizeObject* fi) {
971   - shared_.finalizer_handler()->schedule(fi);
  979 + SCOPE_LOCK(ManagedThread::current(), finalizer_lock_);
  980 + to_finalize_.push_back(fi);
  981 + added_finalizers_ = true;
  982 + }
  983 +
  984 + void ObjectMemory::in_finalizer_thread(STATE) {
  985 + CallFrame* call_frame = 0;
  986 + utilities::thread::Thread::set_os_name("rbx.finalizer");
  987 +
  988 + GCTokenImpl gct;
  989 + state->vm()->thread->hard_unlock(state, gct);
  990 +
  991 + // Forever
  992 + for(;;) {
  993 + FinalizeObject* fi;
  994 +
  995 + // Take the lock, remove the first one from the list,
  996 + // then process it.
  997 + {
  998 + SCOPE_LOCK(state->vm(), finalizer_lock_);
  999 +
  1000 + state->vm()->set_call_frame(0);
  1001 +
  1002 + while(to_finalize_.empty()) {
  1003 + GCIndependent indy(state);
  1004 + finalizer_var_.wait(finalizer_lock_);
  1005 + }
  1006 +
  1007 + fi = to_finalize_.front();
  1008 + to_finalize_.pop_front();
  1009 + }
  1010 +
  1011 + if(fi->ruby_finalizer) {
  1012 + // Rubinius specific code. If the finalizer is cTrue, then
  1013 + // send the object the finalize message
  1014 + if(fi->ruby_finalizer == cTrue) {
  1015 + fi->object->send(state, call_frame, state->symbol("__finalize__"));
  1016 + } else {
  1017 + Array* ary = Array::create(state, 1);
  1018 + ary->set(state, 0, fi->object->id(state));
  1019 +
  1020 + OnStack<1> os(state, ary);
  1021 +
  1022 + fi->ruby_finalizer->send(state, call_frame, G(sym_call), ary);
  1023 + }
  1024 + }
  1025 +
  1026 + if(fi->finalizer) {
  1027 + (*fi->finalizer)(state, fi->object);
  1028 + }
  1029 + // Unhook any handle used by fi->object so that we don't accidentally
  1030 + // try and mark it later (after we've finalized it)
  1031 + if(capi::Handle* handle = fi->object->handle(state)) {
  1032 + handle->forget_object();
  1033 + fi->object->clear_handle(state);
  1034 + }
  1035 +
  1036 + // If the object was remembered, unremember it.
  1037 + if(fi->object->remembered_p()) {
  1038 + unremember_object(fi->object);
  1039 + }
  1040 +
  1041 + fi->status = FinalizeObject::eFinalized;
  1042 + }
  1043 +
  1044 + state->checkpoint(gct, 0);
972 1045 }
973 1046
974 1047 void ObjectMemory::run_all_finalizers(STATE) {
@@ -1014,6 +1087,18 @@ namespace rubinius {
1014 1087 running_finalizers_ = false;
1015 1088 }
1016 1089
  1090 + Object* in_finalizer(STATE) {
  1091 + state->shared().om->in_finalizer_thread(state);
  1092 + return cNil;
  1093 + }
  1094 +
  1095 + void ObjectMemory::start_finalizer_thread(STATE) {
  1096 + VM* vm = state->shared().new_vm();
  1097 + Thread* thr = Thread::create(state, vm, G(thread), in_finalizer, false, true);
  1098 + finalizer_thread_.set(thr);
  1099 + thr->fork(state);
  1100 + }
  1101 +
1017 1102 size_t& ObjectMemory::loe_usage() {
1018 1103 return mark_sweep_->allocated_bytes;
1019 1104 }
14 vm/objectmemory.hpp
@@ -167,15 +167,24 @@ namespace rubinius {
167 167 /// True if finalizers are currently being run.
168 168 bool running_finalizers_;
169 169
170   - /// A mutex which protects registering finalizers
  170 + /// True if finalizers were added in this GC cycle.
  171 + bool added_finalizers_;
  172 +
  173 + /// A mutex which protects running the finalizers
171 174 rubinius::Mutex finalizer_lock_;
172 175
  176 + /// A condition variable used to control access to
  177 + /// to_finalize_
  178 + utilities::thread::Condition finalizer_var_;
  179 +
173 180 /// Mutex used to manage lock contention
174 181 utilities::thread::Mutex contention_lock_;
175 182
176 183 /// Condition variable used to manage lock contention
177 184 utilities::thread::Condition contention_var_;
178 185
  186 + TypedRoot<Thread*> finalizer_thread_;
  187 +
179 188 SharedState& shared_;
180 189
181 190 public:
@@ -373,6 +382,9 @@ namespace rubinius {
373 382 void inflate_for_id(STATE, ObjectHeader* obj, uint32_t id);
374 383 void inflate_for_handle(STATE, ObjectHeader* obj, capi::Handle* handle);
375 384
  385 + void in_finalizer_thread(STATE);
  386 + void start_finalizer_thread(STATE);
  387 +
376 388 /// This only has one use! Don't use it!
377 389 Object* allocate_object_raw(size_t bytes);
378 390
1  vm/shared_state.cpp
@@ -33,7 +33,6 @@ namespace rubinius {
33 33 : initialized_(false)
34 34 , auxiliary_threads_(0)
35 35 , signal_handler_(0)
36   - , finalizer_handler_(0)
37 36 , global_handles_(new capi::Handles)
38 37 , global_serial_(0)
39 38 , world_(new WorldState)
11 vm/shared_state.hpp
@@ -37,7 +37,6 @@ namespace rubinius {
37 37 }
38 38
39 39 class SignalHandler;
40   - class FinalizerHandler;
41 40 class ObjectMemory;
42 41 class GlobalCache;
43 42 class ConfigParser;
@@ -66,7 +65,6 @@ namespace rubinius {
66 65 bool initialized_;
67 66 AuxiliaryThreads* auxiliary_threads_;
68 67 SignalHandler* signal_handler_;
69   - FinalizerHandler* finalizer_handler_;
70 68
71 69 capi::Handles* global_handles_;
72 70 std::list<capi::Handle*> cached_handles_;
@@ -139,14 +137,7 @@ namespace rubinius {
139 137 signal_handler_ = thr;
140 138 }
141 139
142   - FinalizerHandler* finalizer_handler() {
143   - return finalizer_handler_;
144   - }
145   -
146   - void set_finalizer_handler(FinalizerHandler* thr) {
147   - finalizer_handler_ = thr;
148   - }
149   -
  140 + static SharedState* standalone(VM*);
150 141 VM* new_vm();
151 142 void remove_vm(VM*);
152 143
12 vm/signal.cpp
@@ -21,11 +21,11 @@
21 21 #include "windows_compat.h"
22 22
23 23 namespace rubinius {
24   - static SignalHandler* signal_handler_ = 0;
  24 + static SignalHandler* handler_ = 0;
25 25 pthread_t main_thread;
26 26
27   - Object* signal_handler_tramp(STATE) {
28   - state->shared().signal_handler()->perform(state);
  27 + Object* handle_tramp(STATE) {
  28 + handler_->perform(state);
29 29 return cNil;
30 30 }
31 31
@@ -38,7 +38,7 @@ namespace rubinius {
38 38 , exit_(false)
39 39 , thread_(state)
40 40 {
41   - signal_handler_ = this;
  41 + handler_ = this;
42 42 main_thread = pthread_self();
43 43
44 44 shared_.auxiliary_threads()->register_thread(this);
@@ -62,7 +62,7 @@ namespace rubinius {
62 62 SYNC(state);
63 63 if(self_) return;
64 64 self_ = state->shared().new_vm();
65   - thread_.set(Thread::create(state, self_, G(thread), signal_handler_tramp, false, true));
  65 + thread_.set(Thread::create(state, self_, G(thread), handle_tramp, false, true));
66 66 run(state);
67 67
68 68 }
@@ -180,7 +180,7 @@ namespace rubinius {
180 180 }
181 181
182 182 void SignalHandler::signal_tramp(int sig) {
183   - signal_handler_->handle_signal(sig);
  183 + handler_->handle_signal(sig);
184 184 }
185 185
186 186 void SignalHandler::handle_signal(int sig) {

0 comments on commit 75537c1

Please sign in to comment.
Something went wrong with that request. Please try again.