From 97123492c1ace1b477a169d3067cc1205343de78 Mon Sep 17 00:00:00 2001 From: Huiba Li Date: Mon, 25 Nov 2024 11:54:15 +0800 Subject: [PATCH] make cross-vcpu interrupt latency lower, by more frequent checking of standby queue. (#625) --- thread/thread.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/thread/thread.cpp b/thread/thread.cpp index 5541e496..5ebbbf31 100644 --- a/thread/thread.cpp +++ b/thread/thread.cpp @@ -304,6 +304,7 @@ namespace photon this->node = head; } thread* eject_whole_atomic() { + if (!node) return nullptr; SCOPED_LOCK(lock); auto p = node; node = nullptr; @@ -1071,24 +1072,26 @@ R"( #endif } static uint32_t last_tsc = 0; - static inline void if_update_now(bool accurate = false) { + static inline bool if_update_now(bool accurate = false) { #if defined(__x86_64__) && defined(__linux__) && defined(ENABLE_MIMIC_VDSO) if (likely(__mimic_vdso_time_x86)) { return photon::now = __mimic_vdso_time_x86.get_now(accurate); } #endif if (likely(ts_updater.load(std::memory_order_relaxed))) { - return; + return true; } if (unlikely(accurate)) { update_now(); - return; + return true; } uint32_t tsc = _rdtsc(); if (unlikely(last_tsc != tsc)) { last_tsc = tsc; update_now(); + return true; } + return false; } NowTime __update_now() { last_tsc = _rdtsc(); @@ -1141,10 +1144,10 @@ R"( } return count; } - - if_update_now(); - while(!sleepq.empty()) - { + if (sleepq.empty() || !if_update_now()) { + return count; + } + do { auto th = sleepq.front(); if (th->ts_wakeup > now) break; SCOPED_LOCK(th->lock); @@ -1154,7 +1157,7 @@ R"( AtomicRunQ().insert_tail(th); count++; } - } + } while(!sleepq.empty()); return count; } @@ -1781,18 +1784,16 @@ R"( void reset_master_event_engine_default() { CURRENT->get_vcpu()->reset_master_event_engine_default(); } - static void* idle_stub(void*) - { + static void* idler(void*) { RunQ rq; auto last_idle = now; auto vcpu = rq.current->get_vcpu(); while (vcpu->state != states::DONE) { - while (!AtomicRunQ(rq).single()) { + while (resume_threads() > 0 || !AtomicRunQ(rq).single()) { thread_yield(); if (unlikely(sat_sub(now, last_idle) >= 1000UL)) { last_idle = now; vcpu->master_event_engine->wait_and_fire_events(0); - resume_threads(); } } if (vcpu->state == states::DONE) @@ -1802,12 +1803,10 @@ R"( // fall in actual sleep auto usec = 10 * 1024 * 1024; // max auto& sleepq = vcpu->sleepq; - if (!sleepq.empty()) - usec = min(usec, - sat_sub(sleepq.front()->ts_wakeup, now)); + if (!sleepq.empty()) usec = min(usec, + sat_sub(sleepq.front()->ts_wakeup, now)); last_idle = now; vcpu->master_event_engine->wait_and_fire_events(usec); - resume_threads(); } return nullptr; } @@ -1899,7 +1898,7 @@ R"( th->state = states::RUNNING; th->init_main_thread_stack(); auto vcpu = new (ptr) vcpu_t; - vcpu->idle_worker = thread_create(&idle_stub, nullptr); + vcpu->idle_worker = thread_create(&idler, nullptr); thread_enable_join(vcpu->idle_worker); if_update_now(true); return ++_n_vcpu; @@ -1914,7 +1913,7 @@ R"( auto vcpu = rq.current->get_vcpu(); wait_all(rq, vcpu); assert(!AtomicRunQ(rq).single()); - assert(vcpu->nthreads == 2); // idle_stub & current alive + assert(vcpu->nthreads == 2); // idler & current alive vcpu->state = states::DONE; // instruct idle_worker to exit thread_join(vcpu->idle_worker); rq.current->state = states::DONE;