From 613761f4751eb0fc8fddd2c6ec644e585907ccb9 Mon Sep 17 00:00:00 2001 From: Shin-ichi MORITA Date: Thu, 24 Aug 2023 21:40:02 +0900 Subject: [PATCH] Fixed not scanning registers on Windows. --- include/xemmai/engine.h | 21 +++++++++++++++++---- include/xemmai/object.h | 7 +++++-- include/xemmai/thread.h | 2 ++ include/xemmai/value.h | 10 +--------- src/engine.cc | 4 ++-- src/fiber.cc | 29 ++++------------------------- src/thread.cc | 11 +++++++++++ 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/include/xemmai/engine.h b/include/xemmai/engine.h index 01c59414..2fa4ca3b 100644 --- a/include/xemmai/engine.h +++ b/include/xemmai/engine.h @@ -121,6 +121,20 @@ class t_engine while (sem_wait(&v_epoch__received) == -1) if (errno != EINTR) throw std::system_error(errno, std::generic_category()); } #endif + t_object** f_epoch_increment(t_object**& a_p0, t_object**& a_p1, t_object** a_q1, t_object** a_decrements) + { + for (; a_p1 < a_q1; ++a_p1) { + auto p = *a_p0++; + auto q = *a_p1; + if (p == q) continue; + p = f_object__find(p); + if (p == q) continue; + if (p) p->f_increment(); + if (q) *a_decrements++ = q; + *a_p1 = p; + } + return a_decrements; + } void f_collector(); void f_debug_stop_and_wait(std::unique_lock& a_lock); void f_debug_enter_and_notify() @@ -321,10 +335,9 @@ inline void t_thread::t_internal::f_epoch_suspend() #endif #ifdef _WIN32 SuspendThread(v_handle); - CONTEXT context; - context.ContextFlags = CONTEXT_CONTROL; - GetThreadContext(v_handle, &context); - auto sp = reinterpret_cast(context.Rsp); + v_context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + GetThreadContext(v_handle, &v_context); + auto sp = reinterpret_cast(v_context.Rsp); MEMORY_BASIC_INFORMATION mbi; for (auto p = sp;;) { VirtualQuery(p, &mbi, sizeof(mbi)); diff --git a/include/xemmai/object.h b/include/xemmai/object.h index c78f3870..154279df 100644 --- a/include/xemmai/object.h +++ b/include/xemmai/object.h @@ -30,10 +30,13 @@ class t_object friend class t_engine; friend class t_with_lock_for_read; friend class t_with_lock_for_write; +#ifdef _WIN32 + friend struct t_thread; + + static inline XEMMAI__PORTABLE__THREAD struct t_roots +#else static inline XEMMAI__PORTABLE__THREAD struct -#ifdef _WIN32 - t_roots #endif { t_object* v_next; diff --git a/include/xemmai/thread.h b/include/xemmai/thread.h index 0c37ce47..46354aae 100644 --- a/include/xemmai/thread.h +++ b/include/xemmai/thread.h @@ -23,6 +23,8 @@ struct t_thread #endif #ifdef _WIN32 HANDLE v_handle = NULL; + CONTEXT v_context_last{}; + CONTEXT v_context; #endif t_object* volatile* v_reviving = nullptr; diff --git a/include/xemmai/value.h b/include/xemmai/value.h index 0fa0e765..5e5977c5 100644 --- a/include/xemmai/value.h +++ b/include/xemmai/value.h @@ -50,25 +50,17 @@ class t_slot static inline XEMMAI__PORTABLE__THREAD t_object* volatile* v_next; #ifdef _WIN32 - static void f__push(t_object* a_object) + void f__push(t_object* a_object) #else XEMMAI__PORTABLE__ALWAYS_INLINE static void f_push(t_object* a_object) #endif { -#ifdef _WIN32 - auto p = v_instance->v_head; -#else auto p = v_head; -#endif *p = a_object; if (p == v_next) v_instance->f_next(); else -#ifdef _WIN32 - [[likely]] v_instance->v_head = p + 1; -#else [[likely]] v_head = p + 1; -#endif } t_object* volatile v_objects[V_SIZE]; diff --git a/src/engine.cc b/src/engine.cc index 6b12a4a7..97e1517e 100644 --- a/src/engine.cc +++ b/src/engine.cc @@ -533,12 +533,12 @@ void t_engine::f_debug_continue(t_thread* a_stepping) #ifdef _WIN32 void t_slot::t_increments::f_push(t_object* a_object) { - f__push(a_object); + v_instance->f__push(a_object); } void t_slot::t_decrements::f_push(t_object* a_object) { - f__push(a_object); + v_instance->f__push(a_object); } t_object* t_engine::f_allocate(size_t a_size) diff --git a/src/fiber.cc b/src/fiber.cc index 30581580..1349aefe 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -81,31 +81,18 @@ void t_fiber::t_internal::f_epoch_copy() void t_fiber::t_internal::f_epoch_scan() { - auto m = v_estack_used - v_estack.get(); - auto used0 = v_estack_buffer.get() + m; - auto used1 = v_estack_last_head + m; + auto used1 = v_estack_last_head + (v_estack_used - v_estack.get()); auto used2 = v_estack_last_used; v_estack_last_used = used1; - v_estack_decrements = v_estack_buffer.get(); auto n = v_stack_bottom - v_stack_top; auto top0 = v_stack_copy - n; auto top1 = v_stack_last_bottom - n; auto top2 = v_stack_last_top; v_stack_last_top = top1; - v_stack_decrements = v_stack_last_bottom; std::lock_guard lock(f_engine()->v_object__heap.f_mutex()); auto p0 = v_estack_buffer.get(); auto p1 = v_estack_last_head; - for (auto used = std::min(used1, used2); p1 < used; ++p1) { - auto p = *p0++; - auto q = *p1; - if (p == q) continue; - p = f_engine()->f_object__find(p); - if (p == q) continue; - if (p) p->f_increment(); - if (q) *v_estack_decrements++ = q; - *p1 = p; - } + v_estack_decrements = f_engine()->f_epoch_increment(p0, p1, std::min(used1, used2), p0); if (used1 > used2) do { auto p = f_engine()->f_object__find(*p0++); @@ -114,6 +101,7 @@ void t_fiber::t_internal::f_epoch_scan() } while (p1 < used1); else for (; p1 < used2; ++p1) if (*p1) *v_estack_decrements++ = *p1; + v_stack_decrements = v_stack_last_bottom; if (top1 < top2) do { auto p = f_engine()->f_object__find(*top0++); @@ -122,16 +110,7 @@ void t_fiber::t_internal::f_epoch_scan() } while (top1 < top2); else for (; top2 < top1; ++top2) if (*top2) *v_stack_decrements++ = *top2; - for (; top0 < v_stack_copy; ++top1) { - auto p = *top0++; - auto q = *top1; - if (p == q) continue; - p = f_engine()->f_object__find(p); - if (p == q) continue; - if (p) p->f_increment(); - if (q) *v_stack_decrements++ = q; - *top1 = p; - } + v_stack_decrements = f_engine()->f_epoch_increment(top0, top1, v_stack_last_bottom, v_stack_decrements); } void t_fiber::t_internal::f_epoch_decrement() diff --git a/src/thread.cc b/src/thread.cc index 227e7e5e..b117dfec 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -37,12 +37,20 @@ void t_thread::t_internal::f_epoch() if (v_done > 0) { ++v_done; for (auto p = v_fibers; p; p = p->v_next) p->f_epoch_copy(); +#ifdef _WIN32 + v_context = {}; +#endif } else { f_epoch_suspend(); for (auto p = v_fibers; p; p = p->v_next) p->f_epoch_copy(); f_epoch_resume(); } for (auto p = v_fibers; p; p = p->v_next) p->f_epoch_scan(); +#ifdef _WIN32 + auto p0 = reinterpret_cast(&v_context); + auto p1 = reinterpret_cast(&v_context_last); + auto decrements = f_engine()->f_epoch_increment(p0, p1, reinterpret_cast(&v_context_last + 1), p0); +#endif v_increments.f_flush(); for (auto p = &v_fibers; *p;) { auto q = *p; @@ -54,6 +62,9 @@ void t_thread::t_internal::f_epoch() delete q; } } +#ifdef _WIN32 + for (auto p = reinterpret_cast(&v_context); p != decrements; ++p) (*p)->f_decrement(); +#endif v_decrements.f_flush(); }