History

Reduce assembly footprint of execute function to allow for specialized tool dispatcher logic Fix locking strategy in scheduler - Release lock prior to notify Change default build optimization to 'for speed' rather than 'full' Add current thread quanta to register and specify size for thread state enum No longer free tool dispatcher after all tools have detached

arr committed 10 years ago

Commit 81423391 parent ed790b411 files · +241 −66Browse files

Showing the changes to src/vm/tool_dispatch.cpp (1 of 11 files). Show all

Unified · Split

src/vm/tool_dispatch.cpp+66−4
@@ -7,6 +7,7 @@ · 6 unmodified lines
77 #include <cassert>
88 #include <vector>
99 #include <debug.h>
10+#include <disvm.h>
1011 #include <vm_tools.h>
1112 #include <exceptions.h>
1213 #include <utils.h>
@@ -21,7 +22,9 @@ vm_tool_t::~vm_tool_t() · 8 unmodified lines
2122 }
2223
2324 vm_tool_dispatch_t::vm_tool_dispatch_t(vm_t &vm)
24− : _vm{ vm }
25+ : _threads_suspended{ false }
26+ , _threads_suspended_count{ 0 }
27+ , _vm { vm }
2528 {
2629 _events.cookie_counter = 1;
2730 _breakpoints.cookie_counter = 1;
@@ -161,6 +164,25 @@ void vm_tool_dispatch_t::on_thread_end(vm_thread_t &t) · 133 unmodified lines
161164 _events.fire_event_callbacks(vm_event_t::thread_end, cxt);
162165 }
163166
167+void vm_tool_dispatch_t::on_thread_broken(vm_thread_t &)
168+{
169+}
170+
171+void vm_tool_dispatch_t::block_if_thread_suspended(uint32_t thread_id)
172+{
173+ if (!_threads_suspended)
174+ return;
175+
176+ std::unique_lock<std::mutex> resume_lock{ _threads_resume_lock };
177+
178+ _threads_suspended_count++;
179+
180+ while (_threads_suspended)
181+ _threads_resume.wait(resume_lock);
182+
183+ _threads_suspended_count--;
184+}
185+
164186 vm_t& vm_tool_dispatch_t::get_vm_instance() const
165187 {
166188 return _vm;
@@ -171,7 +193,7 @@ cookie_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t · 4 unmodified lines
171193 if (!cb)
172194 throw vm_system_exception{ "Invalid callback for event" };
173195
174− std::lock_guard<std::mutex> lock{ _events.lock };
196+ std::lock_guard<std::mutex> lock{ _events.event_lock };
175197
176198 const auto cookie_id = _events.cookie_counter++;
177199
@@ -190,7 +212,7 @@ cookie_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t · 12 unmodified lines
190212
191213 void vm_tool_dispatch_t::unsubscribe_event(cookie_t cookie_id)
192214 {
193− std::lock_guard<std::mutex> lock{ _events.lock };
215+ std::lock_guard<std::mutex> lock{ _events.event_lock };
194216
195217 auto iter = _events.cookie_to_event.find(cookie_id);
196218 if (iter == _events.cookie_to_event.cend())
@@ -292,6 +314,46 @@ void vm_tool_dispatch_t::clear_breakpoint(cookie_t cookie_id) · 95 unmodified lines
292314 _breakpoints.cookie_to_details.erase(iter_cookie);
293315 }
294316
317+void vm_tool_dispatch_t::suspend_all_threads()
318+{
319+ std::lock(_threads_suspend_lock, _threads_resume_lock);
320+ std::lock_guard<std::mutex> suspend_lock{ _threads_suspend_lock, std::adopt_lock };
321+ std::lock_guard<std::mutex> resume_lock{ _threads_resume_lock, std::adopt_lock };
322+
323+ _threads_suspended = true;
324+
325+ const auto &sched = _vm.get_scheduler_control();
326+
327+ auto current = _threads_suspended_count.load();
328+ auto max = static_cast<uint32_t>(sched.get_runnable_threads().size());
329+
330+ // Sleep and check until we determine all threads have been suspended
331+ // Minus 1 to exclude the current thread.
332+ while (max != 0 && current < (max - 1))
333+ {
334+ std::this_thread::sleep_for(std::chrono::milliseconds{ 20 });
335+ current = _threads_suspended_count.load();
336+ max = static_cast<uint32_t>(sched.get_runnable_threads().size());
337+ }
338+
339+ // If the current count is ever equal to the max, then a non vm thread is
340+ // inside the tool dispatcher which may be okay, but it indicates a type of
341+ // non-invasive debugging that was not originally incorporated into this
342+ // dispatcher design.
343+ assert(max == 0 || current < max);
344+}
345+
346+void vm_tool_dispatch_t::resume_all_threads()
347+{
348+ std::lock(_threads_suspend_lock, _threads_resume_lock);
349+ std::lock_guard<std::mutex> suspend_lock{ _threads_suspend_lock, std::adopt_lock };
350+
351+ _threads_suspended = false;
352+
353+ _threads_resume_lock.unlock();
354+ _threads_resume.notify_all();
355+}
356+
295357 std::tuple<opcode_t, cookie_t> vm_tool_dispatch_t::get_original_opcode_and_cookie(const vm_registers_t &r)
296358 {
297359 const auto module = r.module_ref->module.get();
@@ -320,7 +382,7 @@ void vm_tool_dispatch_t::events_t::fire_event_callbacks(vm_event_t event_type, v · 22 unmodified lines
320382 auto event_callbacks = std::vector<vm_event_callback_t>{};
321383
322384 {
323− std::lock_guard<std::mutex> lock_local{ lock };
385+ std::lock_guard<std::mutex> lock_local{ event_lock };
324386
325387 auto &event_callbacks_tmp = callbacks[event_type];
326388 for (auto &c : event_callbacks_tmp)