Unified · Split
| @@ -827,11 +827,11 @@ namespace disvm · 826 unmodified lines | |||
| 827 | // There is no indication if this function failed or succeeded. | 827 | // There is no indication if this function failed or succeeded. |
| 828 | virtual void enqueue_blocked_thread(uint32_t thread_id) = 0; | 828 | virtual void enqueue_blocked_thread(uint32_t thread_id) = 0; |
| 829 | 829 | ||
| 830 | // Gets the number of system threads the scheduler is utilizing | ||
| 831 | virtual std::size_t get_system_thread_count() const = 0; | ||
| 832 | |||
| 830 | // Get all VM threads | 833 | // Get all VM threads |
| 831 | virtual std::vector<std::shared_ptr<const vm_thread_t>> get_all_threads() const = 0; | 834 | virtual std::vector<std::shared_ptr<const vm_thread_t>> get_all_threads() const = 0; |
| 832 | |||
| 833 | // Get runnable VM threads | ||
| 834 | virtual std::vector<std::shared_ptr<const vm_thread_t>> get_runnable_threads() const = 0; | ||
| 835 | }; | 835 | }; |
| 836 | 836 | ||
| 837 | // VM thread scheduler interface | 837 | // VM thread scheduler interface |
| @@ -259,31 +259,19 @@ void default_scheduler_t::enqueue_blocked_thread(uint32_t thread_id) · 258 unmodified lines | |||
| 259 | } | 259 | } |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | std::vector<std::shared_ptr<const vm_thread_t>> default_scheduler_t::get_all_threads() const | 262 | std::size_t default_scheduler_t::get_system_thread_count() const |
| 263 | { | 263 | { |
| 264 | auto result = std::vector<std::shared_ptr<const vm_thread_t>>{}; | 264 | return _worker_thread_count; |
| 265 | |||
| 266 | { | ||
| 267 | std::lock_guard<std::mutex> lock{ _vm_threads_lock }; | ||
| 268 | for (auto &p : _all_vm_threads) | ||
| 269 | result.push_back(p.second->vm_thread); | ||
| 270 | } | ||
| 271 | |||
| 272 | return result; | ||
| 273 | } | 265 | } |
| 274 | 266 | ||
| 275 | std::vector<std::shared_ptr<const vm_thread_t>> default_scheduler_t::get_runnable_threads() const | 267 | std::vector<std::shared_ptr<const vm_thread_t>> default_scheduler_t::get_all_threads() const |
| 276 | { | 268 | { |
| 277 | auto result = std::vector<std::shared_ptr<const vm_thread_t>>{}; | 269 | auto result = std::vector<std::shared_ptr<const vm_thread_t>>{}; |
| 278 | 270 | ||
| 279 | { | 271 | { |
| 280 | std::lock_guard<std::mutex> lock{ _vm_threads_lock }; | 272 | std::lock_guard<std::mutex> lock{ _vm_threads_lock }; |
| 281 | for (auto id : _runnable_vm_thread_ids) | 273 | for (auto &p : _all_vm_threads) |
| 282 | { | 274 | result.push_back(p.second->vm_thread); |
| 283 | auto iter = _all_vm_threads.find(id); | ||
| 284 | assert(iter != _all_vm_threads.cend()); | ||
| 285 | result.push_back(iter->second->vm_thread); | ||
| 286 | } | ||
| 287 | } | 275 | } |
| 288 | 276 | ||
| 289 | return result; | 277 | return result; |
| @@ -45,9 +45,9 @@ namespace disvm · 44 unmodified lines | |||
| 45 | public: // vm_scheduler_control_t | 45 | public: // vm_scheduler_control_t |
| 46 | void enqueue_blocked_thread(uint32_t thread_id) override; | 46 | void enqueue_blocked_thread(uint32_t thread_id) override; |
| 47 | 47 | ||
| 48 | std::vector<std::shared_ptr<const vm_thread_t>> get_all_threads() const override; | 48 | std::size_t get_system_thread_count() const override; |
| 49 | 49 | ||
| 50 | std::vector<std::shared_ptr<const vm_thread_t>> get_runnable_threads() const override; | 50 | std::vector<std::shared_ptr<const vm_thread_t>> get_all_threads() const override; |
| 51 | 51 | ||
| 52 | private: | 52 | private: |
| 53 | struct thread_instance_t final | 53 | struct thread_instance_t final |
| @@ -332,23 +332,22 @@ void vm_tool_dispatch_t::suspend_all_threads() · 331 unmodified lines | |||
| 332 | 332 | ||
| 333 | const auto &sched = _vm.get_scheduler_control(); | 333 | const auto &sched = _vm.get_scheduler_control(); |
| 334 | 334 | ||
| 335 | auto current = _threads_suspended_count.load(); | 335 | const auto sys_thread_count = static_cast<int32_t>(sched.get_system_thread_count()); |
| 336 | auto max = static_cast<uint32_t>(sched.get_runnable_threads().size()); | 336 | assert(sys_thread_count != 0); |
| 337 | 337 | ||
| 338 | // Sleep and check until we determine all threads have been suspended | 338 | // Sleep and check until we account for all system threads associated with the VM. |
| 339 | // Minus 1 to exclude the current thread. | 339 | auto suspended = _threads_suspended_count.load(); |
| 340 | while (max != 0 && current < (max - 1)) | 340 | while ((suspended + 1) < sys_thread_count) |
| 341 | { | 341 | { |
| 342 | std::this_thread::sleep_for(std::chrono::milliseconds{ 20 }); | 342 | std::this_thread::sleep_for(std::chrono::milliseconds{ 20 }); |
| 343 | current = _threads_suspended_count.load(); | 343 | suspended = _threads_suspended_count.load(); |
| 344 | max = static_cast<uint32_t>(sched.get_runnable_threads().size()); | ||
| 345 | } | 344 | } |
| 346 | 345 | ||
| 347 | // If the current count is ever equal to the max, then a non vm thread is | 346 | // If the suspended count is ever equal to the system thread count, then a non-vm thread |
| 348 | // inside the tool dispatcher which may be okay, but it indicates a type of | 347 | // is inside the tool dispatcher which may be okay, but it indicates a type of |
| 349 | // non-invasive debugging that was not originally incorporated into this | 348 | // non-invasive debugging that was not originally incorporated into this |
| 350 | // dispatcher design. | 349 | // dispatcher design. |
| 351 | assert(max == 0 || current < max); | 350 | assert(suspended < sys_thread_count); |
| 352 | } | 351 | } |
| 353 | 352 | ||
| 354 | void vm_tool_dispatch_t::resume_all_threads() | 353 | void vm_tool_dispatch_t::resume_all_threads() |
| @@ -82,7 +82,7 @@ namespace disvm · 81 unmodified lines | |||
| 82 | vm_t &_vm; | 82 | vm_t &_vm; |
| 83 | 83 | ||
| 84 | std::atomic_bool _threads_suspended; | 84 | std::atomic_bool _threads_suspended; |
| 85 | std::atomic<uint32_t> _threads_suspended_count; | 85 | std::atomic<int32_t> _threads_suspended_count; |
| 86 | std::mutex _threads_suspend_lock; | 86 | std::mutex _threads_suspend_lock; |
| 87 | std::condition_variable _threads_resume; | 87 | std::condition_variable _threads_resume; |
| 88 | std::mutex _threads_resume_lock; | 88 | std::mutex _threads_resume_lock; |