remove td::this_thread::yield function. usleep_for(1) used instead

This commit is contained in:
Arseny Smirnov 2022-07-14 16:15:17 +04:00
parent b8bd39dc6f
commit 7ddc3099f6
11 changed files with 58 additions and 20 deletions

View File

@ -51,7 +51,7 @@ class Backoff {
if (cnt < 50) { if (cnt < 50) {
return true; return true;
} else { } else {
td::this_thread::yield(); td::usleep_for(1);
return cnt < 500; return cnt < 500;
} }
} }

View File

@ -194,7 +194,7 @@ Status NetQueryDispatcher::wait_dc_init(DcId dc_id, bool force) {
return Status::Error("Closing"); return Status::Error("Closing");
} }
#if !TD_THREAD_UNSUPPORTED #if !TD_THREAD_UNSUPPORTED
td::this_thread::yield(); td::usleep_for(1);
#endif #endif
} }
} }

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include "td/utils/type_traits.h" #include "td/utils/type_traits.h"
@ -20,6 +21,15 @@ template <class T>
class AtomicRead { class AtomicRead {
public: public:
void read(T &dest) const { void read(T &dest) const {
int it = 0;
const int wait_each_it = 4;
auto wait = [&]() {
it++;
if (it % wait_each_it == 0) {
usleep_for(1);
}
};
while (true) { while (true) {
static_assert(TD_IS_TRIVIALLY_COPYABLE(T), "T must be trivially copyable"); static_assert(TD_IS_TRIVIALLY_COPYABLE(T), "T must be trivially copyable");
auto version_before = version.load(); auto version_before = version.load();
@ -30,7 +40,7 @@ class AtomicRead {
break; break;
} }
} }
td::this_thread::yield(); wait();
} }
} }

View File

@ -14,6 +14,7 @@
#include "td/utils/format.h" #include "td/utils/format.h"
#include "td/utils/HazardPointers.h" #include "td/utils/HazardPointers.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include "td/utils/ScopeGuard.h" #include "td/utils/ScopeGuard.h"
@ -305,7 +306,7 @@ class MpmcQueueOld {
if (try_pop(value, thread_id)) { if (try_pop(value, thread_id)) {
return value; return value;
} }
td::this_thread::yield(); td::usleep_for(1);
} }
} }
@ -429,7 +430,7 @@ class MpmcQueue {
if (try_pop(value, thread_id)) { if (try_pop(value, thread_id)) {
return value; return value;
} }
td::this_thread::yield(); td::usleep_for(1);
} }
} }

View File

@ -8,6 +8,7 @@
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include <algorithm> #include <algorithm>
@ -29,16 +30,17 @@ class MpmcEagerWaiter {
slot.yields = 0; slot.yields = 0;
slot.worker_id = worker_id; slot.worker_id = worker_id;
} }
void wait(Slot &slot) { void wait(Slot &slot) {
if (slot.yields < RoundsTillSleepy) { if (slot.yields < RoundsTillSleepy) {
td::this_thread::yield(); yield();
slot.yields++; slot.yields++;
} else if (slot.yields == RoundsTillSleepy) { } else if (slot.yields == RoundsTillSleepy) {
auto state = state_.load(std::memory_order_relaxed); auto state = state_.load(std::memory_order_relaxed);
if (!State::has_worker(state)) { if (!State::has_worker(state)) {
auto new_state = State::with_worker(state, slot.worker_id); auto new_state = State::with_worker(state, slot.worker_id);
if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) { if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) {
td::this_thread::yield(); yield();
slot.yields++; slot.yields++;
return; return;
} }
@ -47,12 +49,12 @@ class MpmcEagerWaiter {
return; return;
} }
} }
td::this_thread::yield(); yield();
slot.yields = 0; slot.yields = 0;
} else if (slot.yields < RoundsTillAsleep) { } else if (slot.yields < RoundsTillAsleep) {
auto state = state_.load(std::memory_order_acquire); auto state = state_.load(std::memory_order_acquire);
if (State::still_sleepy(state, slot.worker_id)) { if (State::still_sleepy(state, slot.worker_id)) {
td::this_thread::yield(); yield();
slot.yields++; slot.yields++;
return; return;
} }
@ -121,6 +123,10 @@ class MpmcEagerWaiter {
condition_variable_.notify_all(); condition_variable_.notify_all();
} }
} }
static void yield() {
// whatever, this is better than sched_yield
usleep_for(1);
}
}; };
class MpmcSleepyWaiter { class MpmcSleepyWaiter {
@ -208,7 +214,7 @@ class MpmcSleepyWaiter {
} }
if (slot.state_ == Slot::Search) { if (slot.state_ == Slot::Search) {
if (slot.yield_cnt++ < 10 && false) { if (slot.yield_cnt++ < 10 && false) {
td::this_thread::yield(); // TODO some sleep backoff is possible
return; return;
} }

View File

@ -6,6 +6,7 @@
// //
#pragma once #pragma once
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include <atomic> #include <atomic>
@ -30,7 +31,7 @@ class SpinLock {
//TODO pause //TODO pause
return true; return true;
} else { } else {
td::this_thread::yield(); usleep_for(1);
return true; return true;
} }
} }

View File

@ -88,9 +88,6 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at
} }
namespace this_thread_pthread { namespace this_thread_pthread {
void yield() {
sched_yield();
}
ThreadPthread::id get_id() { ThreadPthread::id get_id() {
return pthread_self(); return pthread_self();
} }

View File

@ -83,7 +83,6 @@ class ThreadPthread {
}; };
namespace this_thread_pthread { namespace this_thread_pthread {
void yield();
ThreadPthread::id get_id(); ThreadPthread::id get_id();
} // namespace this_thread_pthread } // namespace this_thread_pthread
} // namespace detail } // namespace detail

View File

@ -70,7 +70,9 @@ class ThreadStl {
return std::forward<T>(v); return std::forward<T>(v);
} }
}; };
namespace this_thread_stl = std::this_thread; namespace this_thread_stl {
using std::this_thread::get_id;
} // namespace this_thread_stl
} // namespace detail } // namespace detail
} // namespace td } // namespace td

View File

@ -32,7 +32,7 @@ class Backoff {
if (cnt < 1) { // 50 if (cnt < 1) { // 50
return true; return true;
} else { } else {
td::this_thread::yield(); td::usleep_for(1);
return cnt < 3; // 500 return cnt < 3; // 500
} }
} }
@ -47,7 +47,7 @@ class InfBackoff {
if (cnt < 50) { if (cnt < 50) {
return true; return true;
} else { } else {
td::this_thread::yield(); td::usleep_for(1);
return true; return true;
} }
} }

View File

@ -10,12 +10,14 @@
#include "td/utils/Context.h" #include "td/utils/Context.h"
#include "td/utils/format.h" #include "td/utils/format.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <mutex>
#include <utility> #include <utility>
namespace td { namespace td {
@ -126,12 +128,12 @@ class RegisterTest {
} }
}; };
class Stage { class StageWait {
public: public:
void wait(uint64 need) { void wait(uint64 need) {
value_.fetch_add(1, std::memory_order_release); value_.fetch_add(1, std::memory_order_release);
while (value_.load(std::memory_order_acquire) < need) { while (value_.load(std::memory_order_acquire) < need) {
td::this_thread::yield(); usleep_for(1);
} }
}; };
@ -139,6 +141,26 @@ class Stage {
std::atomic<uint64> value_{0}; std::atomic<uint64> value_{0};
}; };
class StageMutex {
public:
void wait(uint64 need) {
std::unique_lock<std::mutex> lock{mutex_};
value_++;
if (value_ == need) {
cond_.notify_all();
return;
}
cond_.wait(lock, [&] { return value_ >= need; });
};
private:
std::mutex mutex_;
std::condition_variable cond_;
uint64 value_{0};
};
using Stage = StageMutex;
string rand_string(int from, int to, size_t len); string rand_string(int from, int to, size_t len);
vector<string> rand_split(Slice str); vector<string> rand_split(Slice str);