diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /util/system | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'util/system')
192 files changed, 8421 insertions, 8421 deletions
diff --git a/util/system/align.cpp b/util/system/align.cpp index 711a4f12ff..1b21e7b1dc 100644 --- a/util/system/align.cpp +++ b/util/system/align.cpp @@ -1 +1 @@ -#include "align.h" +#include "align.h" diff --git a/util/system/align.h b/util/system/align.h index ea0bbc5b46..6674b93694 100644 --- a/util/system/align.h +++ b/util/system/align.h @@ -1,16 +1,16 @@ #pragma once - -#include "yassert.h" -#include "defaults.h" + +#include "yassert.h" +#include "defaults.h" #include <util/generic/bitops.h> - -template <class T> + +template <class T> static inline T AlignDown(T len, T align) noexcept { Y_ASSERT(IsPowerOf2(align)); // align should be power of 2 - return len & ~(align - 1); -} - -template <class T> + return len & ~(align - 1); +} + +template <class T> static inline T AlignUp(T len, T align) noexcept { const T alignedResult = AlignDown(len + (align - 1), align); Y_ASSERT(alignedResult >= len); // check for overflow @@ -19,31 +19,31 @@ static inline T AlignUp(T len, T align) noexcept { template <class T> static inline T AlignUpSpace(T len, T align) noexcept { - Y_ASSERT(IsPowerOf2(align)); // align should be power of 2 - return ((T)0 - len) & (align - 1); // AlignUp(len, align) - len; + Y_ASSERT(IsPowerOf2(align)); // align should be power of 2 + return ((T)0 - len) & (align - 1); // AlignUp(len, align) - len; } template <class T> static inline T* AlignUp(T* ptr, size_t align) noexcept { return (T*)AlignUp((uintptr_t)ptr, align); -} - -template <class T> +} + +template <class T> static inline T* AlignDown(T* ptr, size_t align) noexcept { return (T*)AlignDown((uintptr_t)ptr, align); -} - -template <class T> +} + +template <class T> static inline T AlignUp(T t) noexcept { - return AlignUp(t, (size_t)PLATFORM_DATA_ALIGN); -} - -template <class T> + return AlignUp(t, (size_t)PLATFORM_DATA_ALIGN); +} + +template <class T> static inline T AlignDown(T t) noexcept { - return AlignDown(t, (size_t)PLATFORM_DATA_ALIGN); -} - -template <class T> + return AlignDown(t, (size_t)PLATFORM_DATA_ALIGN); +} + +template <class T> static inline T Align(T t) noexcept { - return AlignUp(t); -} + return AlignUp(t); +} diff --git a/util/system/align_ut.cpp b/util/system/align_ut.cpp index 3ba3a3442b..4fbcb5b737 100644 --- a/util/system/align_ut.cpp +++ b/util/system/align_ut.cpp @@ -1,35 +1,35 @@ #include "align.h" #include <library/cpp/testing/unittest/registar.h> - + class TAlignTest: public TTestBase { - UNIT_TEST_SUITE(TAlignTest); - UNIT_TEST(TestDown) - UNIT_TEST(TestUp) - UNIT_TEST_SUITE_END(); - -private: - inline void TestDown() { - UNIT_ASSERT(AlignDown(0, 4) == 0); - UNIT_ASSERT(AlignDown(1, 4) == 0); - UNIT_ASSERT(AlignDown(2, 4) == 0); - UNIT_ASSERT(AlignDown(3, 4) == 0); - UNIT_ASSERT(AlignDown(4, 4) == 4); - UNIT_ASSERT(AlignDown(5, 4) == 4); - UNIT_ASSERT(AlignDown(0, 8) == 0); - UNIT_ASSERT(AlignDown(1, 8) == 0); - } + UNIT_TEST_SUITE(TAlignTest); + UNIT_TEST(TestDown) + UNIT_TEST(TestUp) + UNIT_TEST_SUITE_END(); - inline void TestUp() { - UNIT_ASSERT(AlignUp(0, 4) == 0); - UNIT_ASSERT(AlignUp(1, 4) == 4); - UNIT_ASSERT(AlignUp(2, 4) == 4); - UNIT_ASSERT(AlignUp(3, 4) == 4); - UNIT_ASSERT(AlignUp(4, 4) == 4); - UNIT_ASSERT(AlignUp(5, 4) == 8); - UNIT_ASSERT(AlignUp(0, 8) == 0); - UNIT_ASSERT(AlignUp(1, 8) == 8); - } +private: + inline void TestDown() { + UNIT_ASSERT(AlignDown(0, 4) == 0); + UNIT_ASSERT(AlignDown(1, 4) == 0); + UNIT_ASSERT(AlignDown(2, 4) == 0); + UNIT_ASSERT(AlignDown(3, 4) == 0); + UNIT_ASSERT(AlignDown(4, 4) == 4); + UNIT_ASSERT(AlignDown(5, 4) == 4); + UNIT_ASSERT(AlignDown(0, 8) == 0); + UNIT_ASSERT(AlignDown(1, 8) == 0); + } + + inline void TestUp() { + UNIT_ASSERT(AlignUp(0, 4) == 0); + UNIT_ASSERT(AlignUp(1, 4) == 4); + UNIT_ASSERT(AlignUp(2, 4) == 4); + UNIT_ASSERT(AlignUp(3, 4) == 4); + UNIT_ASSERT(AlignUp(4, 4) == 4); + UNIT_ASSERT(AlignUp(5, 4) == 8); + UNIT_ASSERT(AlignUp(0, 8) == 0); + UNIT_ASSERT(AlignUp(1, 8) == 8); + } }; UNIT_TEST_SUITE_REGISTRATION(TAlignTest); diff --git a/util/system/atexit.cpp b/util/system/atexit.cpp index 74fb10b6b1..4b72d53204 100644 --- a/util/system/atexit.cpp +++ b/util/system/atexit.cpp @@ -1,109 +1,109 @@ -#include "atexit.h" +#include "atexit.h" #include "atomic.h" -#include "yassert.h" -#include "spinlock.h" -#include "thread.h" - +#include "yassert.h" +#include "spinlock.h" +#include "thread.h" + #include <util/generic/ylimits.h> -#include <util/generic/utility.h> -#include <util/generic/deque.h> -#include <util/generic/queue.h> - -#include <tuple> - -#include <cstdlib> - -namespace { - class TAtExit { - struct TFunc { - TAtExitFunc Func; - void* Ctx; - size_t Priority; - size_t Number; - }; - - struct TCmp { - inline bool operator()(const TFunc* l, const TFunc* r) const noexcept { - return std::tie(l->Priority, l->Number) < std::tie(r->Priority, r->Number); - } - }; - - public: - inline TAtExit() noexcept - : FinishStarted_(0) - { - } - +#include <util/generic/utility.h> +#include <util/generic/deque.h> +#include <util/generic/queue.h> + +#include <tuple> + +#include <cstdlib> + +namespace { + class TAtExit { + struct TFunc { + TAtExitFunc Func; + void* Ctx; + size_t Priority; + size_t Number; + }; + + struct TCmp { + inline bool operator()(const TFunc* l, const TFunc* r) const noexcept { + return std::tie(l->Priority, l->Number) < std::tie(r->Priority, r->Number); + } + }; + + public: + inline TAtExit() noexcept + : FinishStarted_(0) + { + } + inline void Finish() noexcept { AtomicSet(FinishStarted_, 1); - - auto guard = Guard(Lock_); - - while (Items_) { - auto c = Items_.top(); - + + auto guard = Guard(Lock_); + + while (Items_) { + auto c = Items_.top(); + Y_ASSERT(c); + + Items_.pop(); - Items_.pop(); - - { - auto unguard = Unguard(guard); + { + auto unguard = Unguard(guard); - try { + try { c->Func(c->Ctx); - } catch (...) { - // ¯\_(ツ)_/¯ + } catch (...) { + // ¯\_(ツ)_/¯ } - } - } - } - - inline void Register(TAtExitFunc func, void* ctx, size_t priority) { - with_lock (Lock_) { + } + } + } + + inline void Register(TAtExitFunc func, void* ctx, size_t priority) { + with_lock (Lock_) { Store_.push_back({func, ctx, priority, Store_.size()}); - Items_.push(&Store_.back()); - } - } - + Items_.push(&Store_.back()); + } + } + inline bool FinishStarted() const { return AtomicGet(FinishStarted_); } - - private: - TAdaptiveLock Lock_; + + private: + TAdaptiveLock Lock_; TAtomic FinishStarted_; TDeque<TFunc> Store_; TPriorityQueue<TFunc*, TVector<TFunc*>, TCmp> Items_; - }; - - static TAtomic atExitLock = 0; + }; + + static TAtomic atExitLock = 0; static TAtExit* volatile atExitPtr = nullptr; - alignas(TAtExit) static char atExitMem[sizeof(TAtExit)]; - - static void OnExit() { + alignas(TAtExit) static char atExitMem[sizeof(TAtExit)]; + + static void OnExit() { if (TAtExit* const atExit = AtomicGet(atExitPtr)) { - atExit->Finish(); - atExit->~TAtExit(); + atExit->Finish(); + atExit->~TAtExit(); AtomicSet(atExitPtr, nullptr); - } - } - - static inline TAtExit* Instance() { + } + } + + static inline TAtExit* Instance() { if (TAtExit* const atExit = AtomicGet(atExitPtr)) { return atExit; } - with_lock (atExitLock) { + with_lock (atExitLock) { if (TAtExit* const atExit = AtomicGet(atExitPtr)) { return atExit; - } + } atexit(OnExit); TAtExit* const atExit = new (atExitMem) TAtExit; AtomicSet(atExitPtr, atExit); return atExit; - } - } -} - + } + } +} + void ManualRunAtExitFinalizers() { OnExit(); } @@ -115,22 +115,22 @@ bool ExitStarted() { return false; } -void AtExit(TAtExitFunc func, void* ctx, size_t priority) { - Instance()->Register(func, ctx, priority); -} - -void AtExit(TAtExitFunc func, void* ctx) { - AtExit(func, ctx, Max<size_t>()); -} - -static void TraditionalCloser(void* ctx) { +void AtExit(TAtExitFunc func, void* ctx, size_t priority) { + Instance()->Register(func, ctx, priority); +} + +void AtExit(TAtExitFunc func, void* ctx) { + AtExit(func, ctx, Max<size_t>()); +} + +static void TraditionalCloser(void* ctx) { reinterpret_cast<TTraditionalAtExitFunc>(ctx)(); -} - -void AtExit(TTraditionalAtExitFunc func) { +} + +void AtExit(TTraditionalAtExitFunc func) { AtExit(TraditionalCloser, reinterpret_cast<void*>(func)); -} - -void AtExit(TTraditionalAtExitFunc func, size_t priority) { +} + +void AtExit(TTraditionalAtExitFunc func, size_t priority) { AtExit(TraditionalCloser, reinterpret_cast<void*>(func), priority); -} +} diff --git a/util/system/atexit.h b/util/system/atexit.h index eb3188615c..e1b923504a 100644 --- a/util/system/atexit.h +++ b/util/system/atexit.h @@ -1,15 +1,15 @@ #pragma once - -#include "defaults.h" - + +#include "defaults.h" + using TAtExitFunc = void (*)(void*); using TTraditionalAtExitFunc = void (*)(); - -void AtExit(TAtExitFunc func, void* ctx); -void AtExit(TAtExitFunc func, void* ctx, size_t priority); - -void AtExit(TTraditionalAtExitFunc func); -void AtExit(TTraditionalAtExitFunc func, size_t priority); + +void AtExit(TAtExitFunc func, void* ctx); +void AtExit(TAtExitFunc func, void* ctx, size_t priority); + +void AtExit(TTraditionalAtExitFunc func); +void AtExit(TTraditionalAtExitFunc func, size_t priority); bool ExitStarted(); diff --git a/util/system/atexit_ut.cpp b/util/system/atexit_ut.cpp index 953f432811..39f88ab1a5 100644 --- a/util/system/atexit_ut.cpp +++ b/util/system/atexit_ut.cpp @@ -1,20 +1,20 @@ #include <library/cpp/testing/unittest/registar.h> + +#include "atexit.h" -#include "atexit.h" - -#include <errno.h> - +#include <errno.h> + #ifdef _win_ -// not implemented +// not implemented #else - #include <sys/types.h> - #include <sys/wait.h> + #include <sys/types.h> + #include <sys/wait.h> #endif //_win_ #include <stdio.h> #ifdef _win_ -// not implemented +// not implemented #else struct TAtExitParams { TAtExitParams(int fd_, const char* str_) @@ -27,26 +27,26 @@ struct TAtExitParams { const char* str; }; -void MyAtExitFunc(void* ptr) { +void MyAtExitFunc(void* ptr) { THolder<TAtExitParams> params{static_cast<TAtExitParams*>(ptr)}; - if (write(params->fd, params->str, strlen(params->str)) < 0) { - abort(); - } + if (write(params->fd, params->str, strlen(params->str)) < 0) { + abort(); + } } #endif -class TAtExitTest: public TTestBase { - UNIT_TEST_SUITE(TAtExitTest); - UNIT_TEST(TestAtExit) +class TAtExitTest: public TTestBase { + UNIT_TEST_SUITE(TAtExitTest); + UNIT_TEST(TestAtExit) UNIT_TEST_SUITE_END(); void TestAtExit() { #ifdef _win_ -// not implemented +// not implemented #else int ret; int pipefd[2]; - + ret = pipe(pipefd); UNIT_ASSERT(ret == 0); @@ -65,7 +65,7 @@ class TAtExitTest: public TTestBase { while (read(pipefd[0], data + last++, 1) > 0 && last < 1024) { } data[--last] = 0; - + UNIT_ASSERT(strcmp(data, "High prio\nMiddle prio\nLow-middle prio\nLow prio\nVery low prio\n") == 0); } else { close(pipefd[0]); diff --git a/util/system/atomic.cpp b/util/system/atomic.cpp index fe85ee00b7..25ad84f41a 100644 --- a/util/system/atomic.cpp +++ b/util/system/atomic.cpp @@ -1,3 +1,3 @@ -#include "atomic.h" - -static_assert(sizeof(TAtomic) == sizeof(void*), "expect sizeof(TAtomic) == sizeof(void*)"); +#include "atomic.h" + +static_assert(sizeof(TAtomic) == sizeof(void*), "expect sizeof(TAtomic) == sizeof(void*)"); diff --git a/util/system/atomic.h b/util/system/atomic.h index 80265babfd..aa3dcfff52 100644 --- a/util/system/atomic.h +++ b/util/system/atomic.h @@ -1,51 +1,51 @@ #pragma once -#include "defaults.h" - +#include "defaults.h" + using TAtomicBase = intptr_t; using TAtomic = volatile TAtomicBase; - -#if defined(__GNUC__) - #include "atomic_gcc.h" -#elif defined(_MSC_VER) - #include "atomic_win.h" + +#if defined(__GNUC__) + #include "atomic_gcc.h" +#elif defined(_MSC_VER) + #include "atomic_win.h" #else - #error unsupported platform + #error unsupported platform #endif -#if !defined(ATOMIC_COMPILER_BARRIER) - #define ATOMIC_COMPILER_BARRIER() -#endif - -static inline TAtomicBase AtomicSub(TAtomic& a, TAtomicBase v) { - return AtomicAdd(a, -v); -} - +#if !defined(ATOMIC_COMPILER_BARRIER) + #define ATOMIC_COMPILER_BARRIER() +#endif + +static inline TAtomicBase AtomicSub(TAtomic& a, TAtomicBase v) { + return AtomicAdd(a, -v); +} + static inline TAtomicBase AtomicGetAndSub(TAtomic& a, TAtomicBase v) { return AtomicGetAndAdd(a, -v); } -#if defined(USE_GENERIC_SETGET) -static inline TAtomicBase AtomicGet(const TAtomic& a) { - return a; -} - -static inline void AtomicSet(TAtomic& a, TAtomicBase v) { - a = v; -} -#endif - -static inline bool AtomicTryLock(TAtomic* a) { - return AtomicCas(a, 1, 0); -} - -static inline bool AtomicTryAndTryLock(TAtomic* a) { - return (AtomicGet(*a) == 0) && AtomicTryLock(a); -} - -static inline void AtomicUnlock(TAtomic* a) { - ATOMIC_COMPILER_BARRIER(); - AtomicSet(*a, 0); -} - -#include "atomic_ops.h" +#if defined(USE_GENERIC_SETGET) +static inline TAtomicBase AtomicGet(const TAtomic& a) { + return a; +} + +static inline void AtomicSet(TAtomic& a, TAtomicBase v) { + a = v; +} +#endif + +static inline bool AtomicTryLock(TAtomic* a) { + return AtomicCas(a, 1, 0); +} + +static inline bool AtomicTryAndTryLock(TAtomic* a) { + return (AtomicGet(*a) == 0) && AtomicTryLock(a); +} + +static inline void AtomicUnlock(TAtomic* a) { + ATOMIC_COMPILER_BARRIER(); + AtomicSet(*a, 0); +} + +#include "atomic_ops.h" diff --git a/util/system/atomic_gcc.h b/util/system/atomic_gcc.h index ed8dc2bdc5..4fc73bd5b2 100644 --- a/util/system/atomic_gcc.h +++ b/util/system/atomic_gcc.h @@ -1,9 +1,9 @@ #pragma once -#define ATOMIC_COMPILER_BARRIER() __asm__ __volatile__("" \ - : \ - : \ - : "memory") +#define ATOMIC_COMPILER_BARRIER() __asm__ __volatile__("" \ + : \ + : \ + : "memory") static inline TAtomicBase AtomicGet(const TAtomic& a) { TAtomicBase tmp; @@ -31,26 +31,26 @@ static inline void AtomicSet(TAtomic& a, TAtomicBase v) { #endif } -static inline intptr_t AtomicIncrement(TAtomic& p) { +static inline intptr_t AtomicIncrement(TAtomic& p) { return __atomic_add_fetch(&p, 1, __ATOMIC_SEQ_CST); -} - +} + static inline intptr_t AtomicGetAndIncrement(TAtomic& p) { return __atomic_fetch_add(&p, 1, __ATOMIC_SEQ_CST); } -static inline intptr_t AtomicDecrement(TAtomic& p) { - return __atomic_sub_fetch(&p, 1, __ATOMIC_SEQ_CST); -} - +static inline intptr_t AtomicDecrement(TAtomic& p) { + return __atomic_sub_fetch(&p, 1, __ATOMIC_SEQ_CST); +} + static inline intptr_t AtomicGetAndDecrement(TAtomic& p) { return __atomic_fetch_sub(&p, 1, __ATOMIC_SEQ_CST); } -static inline intptr_t AtomicAdd(TAtomic& p, intptr_t v) { - return __atomic_add_fetch(&p, v, __ATOMIC_SEQ_CST); -} - +static inline intptr_t AtomicAdd(TAtomic& p, intptr_t v) { + return __atomic_add_fetch(&p, v, __ATOMIC_SEQ_CST); +} + static inline intptr_t AtomicGetAndAdd(TAtomic& p, intptr_t v) { return __atomic_fetch_add(&p, v, __ATOMIC_SEQ_CST); } @@ -60,13 +60,13 @@ static inline intptr_t AtomicSwap(TAtomic* p, intptr_t v) { intptr_t ret; __atomic_exchange(p, &v, &ret, __ATOMIC_SEQ_CST); return ret; -} +} -static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { +static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { (void)a; // disable strange 'parameter set but not used' warning on gcc return __atomic_compare_exchange(a, &compare, &exchange, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); -} - +} + static inline intptr_t AtomicGetAndCas(TAtomic* a, intptr_t exchange, intptr_t compare) { (void)a; // disable strange 'parameter set but not used' warning on gcc __atomic_compare_exchange(a, &compare, &exchange, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); @@ -85,6 +85,6 @@ static inline intptr_t AtomicAnd(TAtomic& a, intptr_t b) { return __atomic_and_fetch(&a, b, __ATOMIC_SEQ_CST); } -static inline void AtomicBarrier() { - __sync_synchronize(); -} +static inline void AtomicBarrier() { + __sync_synchronize(); +} diff --git a/util/system/atomic_ops.h b/util/system/atomic_ops.h index 76766b4a0a..156b455369 100644 --- a/util/system/atomic_ops.h +++ b/util/system/atomic_ops.h @@ -1,8 +1,8 @@ -#pragma once - +#pragma once + #include <util/generic/typetraits.h> -template <typename T> +template <typename T> inline TAtomic* AsAtomicPtr(T volatile* target) { return reinterpret_cast<TAtomic*>(target); } @@ -15,31 +15,31 @@ inline const TAtomic* AsAtomicPtr(T const volatile* target) { // integral types template <typename T> -struct TAtomicTraits { - enum { +struct TAtomicTraits { + enum { Castable = std::is_integral<T>::value && sizeof(T) == sizeof(TAtomicBase) && !std::is_const<T>::value, - }; -}; - -template <typename T, typename TT> + }; +}; + +template <typename T, typename TT> using TEnableIfCastable = std::enable_if_t<TAtomicTraits<T>::Castable, TT>; - -template <typename T> + +template <typename T> inline TEnableIfCastable<T, T> AtomicGet(T const volatile& target) { return static_cast<T>(AtomicGet(*AsAtomicPtr(&target))); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, void> AtomicSet(T volatile& target, TAtomicBase value) { AtomicSet(*AsAtomicPtr(&target), value); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicIncrement(T volatile& target) { return static_cast<T>(AtomicIncrement(*AsAtomicPtr(&target))); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicGetAndIncrement(T volatile& target) { return static_cast<T>(AtomicGetAndIncrement(*AsAtomicPtr(&target))); } @@ -47,9 +47,9 @@ inline TEnableIfCastable<T, T> AtomicGetAndIncrement(T volatile& target) { template <typename T> inline TEnableIfCastable<T, T> AtomicDecrement(T volatile& target) { return static_cast<T>(AtomicDecrement(*AsAtomicPtr(&target))); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicGetAndDecrement(T volatile& target) { return static_cast<T>(AtomicGetAndDecrement(*AsAtomicPtr(&target))); } @@ -57,9 +57,9 @@ inline TEnableIfCastable<T, T> AtomicGetAndDecrement(T volatile& target) { template <typename T> inline TEnableIfCastable<T, T> AtomicAdd(T volatile& target, TAtomicBase value) { return static_cast<T>(AtomicAdd(*AsAtomicPtr(&target), value)); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicGetAndAdd(T volatile& target, TAtomicBase value) { return static_cast<T>(AtomicGetAndAdd(*AsAtomicPtr(&target), value)); } @@ -67,9 +67,9 @@ inline TEnableIfCastable<T, T> AtomicGetAndAdd(T volatile& target, TAtomicBase v template <typename T> inline TEnableIfCastable<T, T> AtomicSub(T volatile& target, TAtomicBase value) { return static_cast<T>(AtomicSub(*AsAtomicPtr(&target), value)); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicGetAndSub(T volatile& target, TAtomicBase value) { return static_cast<T>(AtomicGetAndSub(*AsAtomicPtr(&target), value)); } @@ -77,32 +77,32 @@ inline TEnableIfCastable<T, T> AtomicGetAndSub(T volatile& target, TAtomicBase v template <typename T> inline TEnableIfCastable<T, T> AtomicSwap(T volatile* target, TAtomicBase exchange) { return static_cast<T>(AtomicSwap(AsAtomicPtr(target), exchange)); -} - -template <typename T> +} + +template <typename T> inline TEnableIfCastable<T, bool> AtomicCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) { - return AtomicCas(AsAtomicPtr(target), exchange, compare); -} - -template <typename T> + return AtomicCas(AsAtomicPtr(target), exchange, compare); +} + +template <typename T> inline TEnableIfCastable<T, T> AtomicGetAndCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) { return static_cast<T>(AtomicGetAndCas(AsAtomicPtr(target), exchange, compare)); } template <typename T> inline TEnableIfCastable<T, bool> AtomicTryLock(T volatile* target) { - return AtomicTryLock(AsAtomicPtr(target)); -} - -template <typename T> + return AtomicTryLock(AsAtomicPtr(target)); +} + +template <typename T> inline TEnableIfCastable<T, bool> AtomicTryAndTryLock(T volatile* target) { - return AtomicTryAndTryLock(AsAtomicPtr(target)); -} - -template <typename T> -inline TEnableIfCastable<T, void> AtomicUnlock(T volatile* target) { - AtomicUnlock(AsAtomicPtr(target)); -} + return AtomicTryAndTryLock(AsAtomicPtr(target)); +} + +template <typename T> +inline TEnableIfCastable<T, void> AtomicUnlock(T volatile* target) { + AtomicUnlock(AsAtomicPtr(target)); +} template <typename T> inline TEnableIfCastable<T, T> AtomicOr(T volatile& target, TAtomicBase value) { diff --git a/util/system/atomic_ut.cpp b/util/system/atomic_ut.cpp index 07211ffba7..efe9442fe2 100644 --- a/util/system/atomic_ut.cpp +++ b/util/system/atomic_ut.cpp @@ -1,45 +1,45 @@ -#include "atomic.h" - +#include "atomic.h" + #include <library/cpp/testing/unittest/registar.h> - -#include <util/generic/ylimits.h> - + +#include <util/generic/ylimits.h> + template <typename TAtomic> class TAtomicTest - : public TTestBase { + : public TTestBase { UNIT_TEST_SUITE(TAtomicTest); - UNIT_TEST(TestAtomicInc1) - UNIT_TEST(TestAtomicInc2) + UNIT_TEST(TestAtomicInc1) + UNIT_TEST(TestAtomicInc2) UNIT_TEST(TestAtomicGetAndInc) - UNIT_TEST(TestAtomicDec) + UNIT_TEST(TestAtomicDec) UNIT_TEST(TestAtomicGetAndDec) - UNIT_TEST(TestAtomicAdd) + UNIT_TEST(TestAtomicAdd) UNIT_TEST(TestAtomicGetAndAdd) - UNIT_TEST(TestAtomicSub) + UNIT_TEST(TestAtomicSub) UNIT_TEST(TestAtomicGetAndSub) - UNIT_TEST(TestAtomicSwap) + UNIT_TEST(TestAtomicSwap) UNIT_TEST(TestAtomicOr) UNIT_TEST(TestAtomicAnd) UNIT_TEST(TestAtomicXor) - UNIT_TEST(TestCAS) + UNIT_TEST(TestCAS) UNIT_TEST(TestGetAndCAS) - UNIT_TEST(TestLockUnlock) + UNIT_TEST(TestLockUnlock) UNIT_TEST_SUITE_END(); - + private: inline void TestLockUnlock() { TAtomic v = 0; - + UNIT_ASSERT(AtomicTryLock(&v)); UNIT_ASSERT(!AtomicTryLock(&v)); UNIT_ASSERT_VALUES_EQUAL(v, 1); AtomicUnlock(&v); UNIT_ASSERT_VALUES_EQUAL(v, 0); } - + inline void TestCAS() { TAtomic v = 0; - + UNIT_ASSERT(AtomicCas(&v, 1, 0)); UNIT_ASSERT(!AtomicCas(&v, 1, 0)); UNIT_ASSERT_VALUES_EQUAL(v, 1); @@ -48,7 +48,7 @@ private: UNIT_ASSERT(AtomicCas(&v, Max<intptr_t>(), 0)); UNIT_ASSERT_VALUES_EQUAL(v, Max<intptr_t>()); } - + inline void TestGetAndCAS() { TAtomic v = 0; @@ -63,22 +63,22 @@ private: inline void TestAtomicInc1() { TAtomic v = 0; - + UNIT_ASSERT(AtomicAdd(v, 1)); UNIT_ASSERT_VALUES_EQUAL(v, 1); UNIT_ASSERT(AtomicAdd(v, 10)); UNIT_ASSERT_VALUES_EQUAL(v, 11); } - + inline void TestAtomicInc2() { TAtomic v = 0; - + UNIT_ASSERT(AtomicIncrement(v)); UNIT_ASSERT_VALUES_EQUAL(v, 1); UNIT_ASSERT(AtomicIncrement(v)); UNIT_ASSERT_VALUES_EQUAL(v, 2); } - + inline void TestAtomicGetAndInc() { TAtomic v = 0; @@ -90,13 +90,13 @@ private: inline void TestAtomicDec() { TAtomic v = 2; - + UNIT_ASSERT(AtomicDecrement(v)); UNIT_ASSERT_VALUES_EQUAL(v, 1); UNIT_ASSERT(!AtomicDecrement(v)); UNIT_ASSERT_VALUES_EQUAL(v, 0); } - + inline void TestAtomicGetAndDec() { TAtomic v = 2; @@ -108,7 +108,7 @@ private: inline void TestAtomicAdd() { TAtomic v = 0; - + UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, 1), 1); UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, 2), 3); UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, -4), -1); @@ -124,15 +124,15 @@ private: UNIT_ASSERT_VALUES_EQUAL(v, -1); } - inline void TestAtomicSub() { + inline void TestAtomicSub() { TAtomic v = 4; - + UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 1), 3); UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 2), 1); UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 3), -2); UNIT_ASSERT_VALUES_EQUAL(v, -2); } - + inline void TestAtomicGetAndSub() { TAtomic v = 4; @@ -144,7 +144,7 @@ private: inline void TestAtomicSwap() { TAtomic v = 0; - + UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, 3), 0); UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, 5), 3); UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, -7), 5); @@ -186,32 +186,32 @@ private: UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&p, nullptr), &i); UNIT_ASSERT(AtomicCas(&p, &i, nullptr)); } -}; - +}; + UNIT_TEST_SUITE_REGISTRATION(TAtomicTest<TAtomic>); #ifndef _MSC_VER // chooses type *other than* T1 -template <typename T1, typename T2, typename T3> -struct TChooser { +template <typename T1, typename T2, typename T3> +struct TChooser { using TdType = T2; }; - -template <typename T1, typename T2> -struct TChooser<T1, T1, T2> { + +template <typename T1, typename T2> +struct TChooser<T1, T1, T2> { using TdType = T2; }; + +template <typename T1> +struct TChooser<T1, T1, T1> {}; -template <typename T1> -struct TChooser<T1, T1, T1> {}; - - #if defined(__IOS__) && defined(_32_) -using TAltAtomic = int; - #else + #if defined(__IOS__) && defined(_32_) +using TAltAtomic = int; + #else using TAltAtomic = volatile TChooser<TAtomicBase, long, long long>::TdType; - #endif + #endif -class TTTest: public TAtomicTest<TAltAtomic> { +class TTTest: public TAtomicTest<TAltAtomic> { public: TString Name() const noexcept override { return "TAtomicTest<TAltAtomic>"; diff --git a/util/system/atomic_win.h b/util/system/atomic_win.h index 65c290e6cc..fa21bd4b9b 100644 --- a/util/system/atomic_win.h +++ b/util/system/atomic_win.h @@ -1,79 +1,79 @@ #pragma once -#include <intrin.h> - +#include <intrin.h> + #define USE_GENERIC_SETGET #if defined(_i386_) + + #pragma intrinsic(_InterlockedIncrement) + #pragma intrinsic(_InterlockedDecrement) + #pragma intrinsic(_InterlockedExchangeAdd) + #pragma intrinsic(_InterlockedExchange) + #pragma intrinsic(_InterlockedCompareExchange) - #pragma intrinsic(_InterlockedIncrement) - #pragma intrinsic(_InterlockedDecrement) - #pragma intrinsic(_InterlockedExchangeAdd) - #pragma intrinsic(_InterlockedExchange) - #pragma intrinsic(_InterlockedCompareExchange) - -static inline intptr_t AtomicIncrement(TAtomic& a) { - return _InterlockedIncrement((volatile long*)&a); +static inline intptr_t AtomicIncrement(TAtomic& a) { + return _InterlockedIncrement((volatile long*)&a); } - + static inline intptr_t AtomicGetAndIncrement(TAtomic& a) { return _InterlockedIncrement((volatile long*)&a) - 1; } -static inline intptr_t AtomicDecrement(TAtomic& a) { - return _InterlockedDecrement((volatile long*)&a); +static inline intptr_t AtomicDecrement(TAtomic& a) { + return _InterlockedDecrement((volatile long*)&a); } - + static inline intptr_t AtomicGetAndDecrement(TAtomic& a) { return _InterlockedDecrement((volatile long*)&a) + 1; } -static inline intptr_t AtomicAdd(TAtomic& a, intptr_t b) { - return _InterlockedExchangeAdd((volatile long*)&a, b) + b; +static inline intptr_t AtomicAdd(TAtomic& a, intptr_t b) { + return _InterlockedExchangeAdd((volatile long*)&a, b) + b; } - + static inline intptr_t AtomicGetAndAdd(TAtomic& a, intptr_t b) { return _InterlockedExchangeAdd((volatile long*)&a, b); } static inline intptr_t AtomicSwap(TAtomic* a, intptr_t b) { return _InterlockedExchange((volatile long*)a, b); -} - -static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { - return _InterlockedCompareExchange((volatile long*)a, exchange, compare) == compare; -} +} +static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { + return _InterlockedCompareExchange((volatile long*)a, exchange, compare) == compare; +} + static inline intptr_t AtomicGetAndCas(TAtomic* a, intptr_t exchange, intptr_t compare) { return _InterlockedCompareExchange((volatile long*)a, exchange, compare); } #else // _x86_64_ - #pragma intrinsic(_InterlockedIncrement64) - #pragma intrinsic(_InterlockedDecrement64) - #pragma intrinsic(_InterlockedExchangeAdd64) - #pragma intrinsic(_InterlockedExchange64) - #pragma intrinsic(_InterlockedCompareExchange64) + #pragma intrinsic(_InterlockedIncrement64) + #pragma intrinsic(_InterlockedDecrement64) + #pragma intrinsic(_InterlockedExchangeAdd64) + #pragma intrinsic(_InterlockedExchange64) + #pragma intrinsic(_InterlockedCompareExchange64) -static inline intptr_t AtomicIncrement(TAtomic& a) { - return _InterlockedIncrement64((volatile __int64*)&a); +static inline intptr_t AtomicIncrement(TAtomic& a) { + return _InterlockedIncrement64((volatile __int64*)&a); } static inline intptr_t AtomicGetAndIncrement(TAtomic& a) { return _InterlockedIncrement64((volatile __int64*)&a) - 1; } -static inline intptr_t AtomicDecrement(TAtomic& a) { - return _InterlockedDecrement64((volatile __int64*)&a); +static inline intptr_t AtomicDecrement(TAtomic& a) { + return _InterlockedDecrement64((volatile __int64*)&a); } static inline intptr_t AtomicGetAndDecrement(TAtomic& a) { return _InterlockedDecrement64((volatile __int64*)&a) + 1; } -static inline intptr_t AtomicAdd(TAtomic& a, intptr_t b) { - return _InterlockedExchangeAdd64((volatile __int64*)&a, b) + b; +static inline intptr_t AtomicAdd(TAtomic& a, intptr_t b) { + return _InterlockedExchangeAdd64((volatile __int64*)&a, b) + b; } static inline intptr_t AtomicGetAndAdd(TAtomic& a, intptr_t b) { @@ -84,8 +84,8 @@ static inline intptr_t AtomicSwap(TAtomic* a, intptr_t b) { return _InterlockedExchange64((volatile __int64*)a, b); } -static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { - return _InterlockedCompareExchange64((volatile __int64*)a, exchange, compare) == compare; +static inline bool AtomicCas(TAtomic* a, intptr_t exchange, intptr_t compare) { + return _InterlockedCompareExchange64((volatile __int64*)a, exchange, compare) == compare; } static inline intptr_t AtomicGetAndCas(TAtomic* a, intptr_t exchange, intptr_t compare) { @@ -105,10 +105,10 @@ static inline intptr_t AtomicXor(TAtomic& a, intptr_t b) { } #endif // _x86_ - -//TODO -static inline void AtomicBarrier() { - TAtomic val = 0; - + +//TODO +static inline void AtomicBarrier() { + TAtomic val = 0; + AtomicSwap(&val, 0); -} +} diff --git a/util/system/backtrace.cpp b/util/system/backtrace.cpp index b77fe58fb1..c324a0080d 100644 --- a/util/system/backtrace.cpp +++ b/util/system/backtrace.cpp @@ -1,248 +1,248 @@ -#include "dynlib.h" +#include "dynlib.h" #include "demangle_impl.h" -#include "platform.h" -#include "backtrace.h" - +#include "platform.h" +#include "backtrace.h" + #include <util/stream/output.h> #include <util/stream/format.h> #include <util/generic/array_ref.h> #include <util/generic/string.h> - + #ifdef _win_ - #include "mutex.h" - - #ifndef OPTIONAL - #define OPTIONAL - #endif - #include <dbghelp.h> -#endif - -#if defined(_bionic_) -//TODO -#else - #if !defined(HAVE_BACKTRACE) && defined(_cygwin_) - #define CaptureStackBackTrace RtlCaptureStackBackTrace -extern "C" __stdcall unsigned short CaptureStackBackTrace(unsigned long FramesToSkip, unsigned long FramesToCapture, void** BackTrace, unsigned long* BackTraceHash); - - #define USE_WIN_BACKTRACE - #define HAVE_BACKTRACE - #endif - - #if !defined(HAVE_BACKTRACE) && defined(__IOS__) - #define USE_GLIBC_BACKTRACE - #define HAVE_BACKTRACE - #endif + #include "mutex.h" - #if !defined(HAVE_BACKTRACE) && defined(__GNUC__) - #define USE_GCC_BACKTRACE - #define HAVE_BACKTRACE - #endif - - #if !defined(HAVE_BACKTRACE) && defined(_win_) - #define USE_WIN_BACKTRACE - #define HAVE_BACKTRACE - #endif - - #if !defined(HAVE_BACKTRACE) && defined(_glibc_) - #define USE_GLIBC_BACKTRACE - #define HAVE_BACKTRACE - #endif -#endif - -#if defined(USE_GLIBC_BACKTRACE) - #include <execinfo.h> - -size_t BackTrace(void** p, size_t len) { - return (size_t)backtrace(p, len); -} + #ifndef OPTIONAL + #define OPTIONAL + #endif + #include <dbghelp.h> #endif -#if defined(USE_GCC_BACKTRACE) - #include <cxxabi.h> - #include <unwind.h> - -namespace { - namespace NGCCBacktrace { - struct TBackTraceContext { - void** sym; - size_t cnt; - size_t size; - }; - - static _Unwind_Reason_Code Helper(struct _Unwind_Context* c, void* h) { - TBackTraceContext* bt = (TBackTraceContext*)h; - - if (bt->cnt != 0) { +#if defined(_bionic_) +//TODO +#else + #if !defined(HAVE_BACKTRACE) && defined(_cygwin_) + #define CaptureStackBackTrace RtlCaptureStackBackTrace +extern "C" __stdcall unsigned short CaptureStackBackTrace(unsigned long FramesToSkip, unsigned long FramesToCapture, void** BackTrace, unsigned long* BackTraceHash); + + #define USE_WIN_BACKTRACE + #define HAVE_BACKTRACE + #endif + + #if !defined(HAVE_BACKTRACE) && defined(__IOS__) + #define USE_GLIBC_BACKTRACE + #define HAVE_BACKTRACE + #endif + + #if !defined(HAVE_BACKTRACE) && defined(__GNUC__) + #define USE_GCC_BACKTRACE + #define HAVE_BACKTRACE + #endif + + #if !defined(HAVE_BACKTRACE) && defined(_win_) + #define USE_WIN_BACKTRACE + #define HAVE_BACKTRACE + #endif + + #if !defined(HAVE_BACKTRACE) && defined(_glibc_) + #define USE_GLIBC_BACKTRACE + #define HAVE_BACKTRACE + #endif +#endif + +#if defined(USE_GLIBC_BACKTRACE) + #include <execinfo.h> + +size_t BackTrace(void** p, size_t len) { + return (size_t)backtrace(p, len); +} +#endif + +#if defined(USE_GCC_BACKTRACE) + #include <cxxabi.h> + #include <unwind.h> + +namespace { + namespace NGCCBacktrace { + struct TBackTraceContext { + void** sym; + size_t cnt; + size_t size; + }; + + static _Unwind_Reason_Code Helper(struct _Unwind_Context* c, void* h) { + TBackTraceContext* bt = (TBackTraceContext*)h; + + if (bt->cnt != 0) { bt->sym[bt->cnt - 1] = (void*)_Unwind_GetIP(c); - } - - if (bt->cnt == bt->size) { - return _URC_END_OF_STACK; - } - - ++bt->cnt; - - return _URC_NO_REASON; - } - - static inline size_t BackTrace(void** p, size_t len) { - if (len >= 1) { - TBackTraceContext bt = {p, 0, len}; - - _Unwind_Backtrace(Helper, &bt); - - return bt.cnt - 1; - } - - return 0; - } - } -} - -size_t BackTrace(void** p, size_t len) { - return NGCCBacktrace::BackTrace(p, len); -} -#endif - + } + + if (bt->cnt == bt->size) { + return _URC_END_OF_STACK; + } + + ++bt->cnt; + + return _URC_NO_REASON; + } + + static inline size_t BackTrace(void** p, size_t len) { + if (len >= 1) { + TBackTraceContext bt = {p, 0, len}; + + _Unwind_Backtrace(Helper, &bt); + + return bt.cnt - 1; + } + + return 0; + } + } +} + +size_t BackTrace(void** p, size_t len) { + return NGCCBacktrace::BackTrace(p, len); +} +#endif + #if defined(USE_WIN_BACKTRACE) size_t BackTrace(void** p, size_t len) { return CaptureStackBackTrace(0, len, p, nullptr); } #endif -#if !defined(HAVE_BACKTRACE) -size_t BackTrace(void**, size_t) { - return 0; -} -#endif - -#if defined(_unix_) && !defined(_cygwin_) - #include <util/generic/strfcpy.h> - - #include <dlfcn.h> - - #if defined(_darwin_) - #include <execinfo.h> - #endif - -static inline const char* CopyTo(const char* from, char* buf, size_t len) { - strfcpy(buf, from, len); - - return buf; -} - -TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len) { - TResolvedSymbol ret = { - "??", - sym, - }; - - Dl_info dli; - - Zero(dli); - - if (dladdr(sym, &dli) && dli.dli_sname) { +#if !defined(HAVE_BACKTRACE) +size_t BackTrace(void**, size_t) { + return 0; +} +#endif + +#if defined(_unix_) && !defined(_cygwin_) + #include <util/generic/strfcpy.h> + + #include <dlfcn.h> + + #if defined(_darwin_) + #include <execinfo.h> + #endif + +static inline const char* CopyTo(const char* from, char* buf, size_t len) { + strfcpy(buf, from, len); + + return buf; +} + +TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len) { + TResolvedSymbol ret = { + "??", + sym, + }; + + Dl_info dli; + + Zero(dli); + + if (dladdr(sym, &dli) && dli.dli_sname) { ret.Name = CopyTo(NPrivate::TCppDemangler().Demangle(dli.dli_sname), buf, len); - ret.NearestSymbol = dli.dli_saddr; - } - - return ret; -} + ret.NearestSymbol = dli.dli_saddr; + } + + return ret; +} #elif defined(_win_) #include <util/generic/singleton.h> namespace { - struct TWinSymbolResolverImpl { - typedef BOOL(WINAPI* TSymInitializeFunc)(HANDLE, PCSTR, BOOL); - typedef BOOL(WINAPI* TSymCleanupFunc)(HANDLE); - typedef BOOL(WINAPI* TSymFromAddrFunc)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); - - TWinSymbolResolverImpl() - : InitOk(FALSE) - { - Library = LoadLibraryA("Dbghelp.dll"); - if (!Library) { - return; - } - - SymInitializeFunc = (TSymInitializeFunc)GetProcAddress(Library, "SymInitialize"); - SymCleanupFunc = (TSymCleanupFunc)GetProcAddress(Library, "SymCleanup"); - SymFromAddrFunc = (TSymFromAddrFunc)GetProcAddress(Library, "SymFromAddr"); - if (SymInitializeFunc && SymCleanupFunc && SymFromAddrFunc) { - InitOk = SymInitializeFunc(GetCurrentProcess(), nullptr, TRUE); - } + struct TWinSymbolResolverImpl { + typedef BOOL(WINAPI* TSymInitializeFunc)(HANDLE, PCSTR, BOOL); + typedef BOOL(WINAPI* TSymCleanupFunc)(HANDLE); + typedef BOOL(WINAPI* TSymFromAddrFunc)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); + + TWinSymbolResolverImpl() + : InitOk(FALSE) + { + Library = LoadLibraryA("Dbghelp.dll"); + if (!Library) { + return; + } + + SymInitializeFunc = (TSymInitializeFunc)GetProcAddress(Library, "SymInitialize"); + SymCleanupFunc = (TSymCleanupFunc)GetProcAddress(Library, "SymCleanup"); + SymFromAddrFunc = (TSymFromAddrFunc)GetProcAddress(Library, "SymFromAddr"); + if (SymInitializeFunc && SymCleanupFunc && SymFromAddrFunc) { + InitOk = SymInitializeFunc(GetCurrentProcess(), nullptr, TRUE); + } } - ~TWinSymbolResolverImpl() { - if (InitOk) { - SymCleanupFunc(GetCurrentProcess()); - } + ~TWinSymbolResolverImpl() { + if (InitOk) { + SymCleanupFunc(GetCurrentProcess()); + } - if (Library) { - FreeLibrary(Library); - } + if (Library) { + FreeLibrary(Library); + } } - TResolvedSymbol Resolve(void* sym, char* buf, size_t len) { - TGuard<TMutex> guard(Mutex); + TResolvedSymbol Resolve(void* sym, char* buf, size_t len) { + TGuard<TMutex> guard(Mutex); - TResolvedSymbol ret = { - "??", - sym}; + TResolvedSymbol ret = { + "??", + sym}; - if (!InitOk || (len <= 1 + sizeof(SYMBOL_INFO))) { - return ret; - } + if (!InitOk || (len <= 1 + sizeof(SYMBOL_INFO))) { + return ret; + } - SYMBOL_INFO* symbol = (SYMBOL_INFO*)buf; - Zero(*symbol); + SYMBOL_INFO* symbol = (SYMBOL_INFO*)buf; + Zero(*symbol); - symbol->MaxNameLen = len - sizeof(SYMBOL_INFO) - 1; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = len - sizeof(SYMBOL_INFO) - 1; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - DWORD64 displacement = 0; - BOOL res = SymFromAddrFunc(GetCurrentProcess(), (DWORD64)sym, &displacement, symbol); - if (res) { - ret.NearestSymbol = (void*)symbol->Address; - ret.Name = symbol->Name; - } + DWORD64 displacement = 0; + BOOL res = SymFromAddrFunc(GetCurrentProcess(), (DWORD64)sym, &displacement, symbol); + if (res) { + ret.NearestSymbol = (void*)symbol->Address; + ret.Name = symbol->Name; + } - return ret; + return ret; } - TMutex Mutex; - HMODULE Library; - TSymInitializeFunc SymInitializeFunc; - TSymCleanupFunc SymCleanupFunc; - TSymFromAddrFunc SymFromAddrFunc; - BOOL InitOk; - }; + TMutex Mutex; + HMODULE Library; + TSymInitializeFunc SymInitializeFunc; + TSymCleanupFunc SymCleanupFunc; + TSymFromAddrFunc SymFromAddrFunc; + BOOL InitOk; + }; } TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len) { return Singleton<TWinSymbolResolverImpl>()->Resolve(sym, buf, len); } -#else -TResolvedSymbol ResolveSymbol(void* sym, char*, size_t) { - TResolvedSymbol ret = { - "??", - sym, - }; - - return ret; -} -#endif - +#else +TResolvedSymbol ResolveSymbol(void* sym, char*, size_t) { + TResolvedSymbol ret = { + "??", + sym, + }; + + return ret; +} +#endif + void FormatBackTrace(IOutputStream* out, void* const* backtrace, size_t backtraceSize) { - char tmpBuf[1024]; - + char tmpBuf[1024]; + for (size_t i = 0; i < backtraceSize; ++i) { TResolvedSymbol rs = ResolveSymbol(backtrace[i], tmpBuf, sizeof(tmpBuf)); - + *out << rs.Name << "+" << ((ptrdiff_t)backtrace[i] - (ptrdiff_t)rs.NearestSymbol) << " (" << Hex((ptrdiff_t)backtrace[i], HF_ADDX) << ')' << '\n'; - } -} - + } +} + TFormatBackTraceFn FormatBackTraceFn = FormatBackTrace; TFormatBackTraceFn SetFormatBackTraceFn(TFormatBackTraceFn f) { @@ -261,14 +261,14 @@ TFormatBackTraceFn GetFormatBackTraceFn() { return FormatBackTraceFn; } -void PrintBackTrace() { - FormatBackTrace(&Cerr); -} +void PrintBackTrace() { + FormatBackTrace(&Cerr); +} TBackTrace::TBackTrace() : Size(0) -{ -} +{ +} void TBackTrace::Capture() { Size = BackTrace(Data, CAPACITY); diff --git a/util/system/backtrace.h b/util/system/backtrace.h index 2fce7585c3..1abeadc8e2 100644 --- a/util/system/backtrace.h +++ b/util/system/backtrace.h @@ -1,22 +1,22 @@ #pragma once - + #include <util/generic/fwd.h> #include <util/system/defaults.h> - + class IOutputStream; - -size_t BackTrace(void** p, size_t len); - -struct TResolvedSymbol { - const char* Name; - void* NearestSymbol; -}; - -TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len); - + +size_t BackTrace(void** p, size_t len); + +struct TResolvedSymbol { + const char* Name; + void* NearestSymbol; +}; + +TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len); + void FormatBackTrace(IOutputStream* out, void* const* backtrace, size_t backtraceSize); void FormatBackTrace(IOutputStream* out); -void PrintBackTrace(); +void PrintBackTrace(); using TFormatBackTraceFn = void (*)(IOutputStream*, void* const* backtrace, size_t backtraceSize); @@ -30,7 +30,7 @@ private: static constexpr size_t CAPACITY = 300; void* Data[CAPACITY]; size_t Size; - + public: TBackTrace(); void Capture(); diff --git a/util/system/backtrace_ut.cpp b/util/system/backtrace_ut.cpp index 9b5ead71bc..4f5e143a1e 100644 --- a/util/system/backtrace_ut.cpp +++ b/util/system/backtrace_ut.cpp @@ -1,10 +1,10 @@ -#include "backtrace.h" - +#include "backtrace.h" + #include <util/generic/array_ref.h> #include <library/cpp/testing/unittest/registar.h> #include <util/stream/output.h> - + using PFunc = int (*)(void**, size_t); int Dbg1(void** buf, size_t len) { @@ -17,35 +17,35 @@ int Dbg2(void** buf, size_t len) { return ret; } -void FormatBackTraceReplacement(IOutputStream* out, void* const*, size_t) { +void FormatBackTraceReplacement(IOutputStream* out, void* const*, size_t) { *out << "WorksLikeACharm" << Endl; } -void SomeMethod() { - TStringStream out; - - FormatBackTrace(&out); - -#if defined(_musl_) - // musl dladdr broken for us now - return; -#endif - +void SomeMethod() { + TStringStream out; + + FormatBackTrace(&out); + +#if defined(_musl_) + // musl dladdr broken for us now + return; +#endif + UNIT_ASSERT(out.Empty() || out.Str().find("SomeMethod") != TString::npos); -} - -class TBackTraceTest: public TTestBase { +} + +class TBackTraceTest: public TTestBase { UNIT_TEST_SUITE(TBackTraceTest); - UNIT_TEST(TestBackTrace) + UNIT_TEST(TestBackTrace) UNIT_TEST(TestBackTraceView) - UNIT_TEST(TestPrintBackTrace) + UNIT_TEST(TestPrintBackTrace) UNIT_TEST(TestSetFormatBackTraceFn) UNIT_TEST_SUITE_END(); - void TestPrintBackTrace() { - SomeMethod(); - } - + void TestPrintBackTrace() { + SomeMethod(); + } + void TestSetFormatBackTraceFn() { TFormatBackTraceFn prevFn = SetFormatBackTraceFn(FormatBackTraceReplacement); TStringStream out; @@ -56,7 +56,7 @@ class TBackTraceTest: public TTestBase { } void TestBackTrace() { - //PrintBackTrace(); + //PrintBackTrace(); void* buf1[100]; size_t ret1; diff --git a/util/system/benchmark/rdtsc/main.cpp b/util/system/benchmark/rdtsc/main.cpp index 8189d10f06..2d09e445ef 100644 --- a/util/system/benchmark/rdtsc/main.cpp +++ b/util/system/benchmark/rdtsc/main.cpp @@ -1,61 +1,61 @@ #include <library/cpp/testing/benchmark/bench.h> - -#include <util/system/datetime.h> -#include <util/generic/xrange.h> - -Y_FORCE_INLINE ui64 GetCycleCountLinux() { - unsigned hi, lo; - __asm__ __volatile__("lfence\n" - "rdtsc" - : "=a"(lo), "=d"(hi)); - return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); -} - -Y_FORCE_INLINE ui64 GetCycleCountAgri1() { - unsigned hi, lo; - - __asm__ __volatile__("rdtscp\n" - : "=a"(lo), "=d"(hi)::"%rbx", "%rcx"); - - return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); -} - -Y_FORCE_INLINE ui64 GetCycleCountAgri2() { - unsigned hi, lo; - __asm__ __volatile__("rdtscp\n" - : "=a"(lo), "=d"(hi)::"%rbx", "%rcx"); - /* call cpuid to prevent out of order execution */ - __asm__ __volatile__("mov $0, %%eax\n" - "cpuid\n" :: - : "%eax"); - - return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); -} - -Y_CPU_BENCHMARK(RdtscUtil, iface) { - for (const auto i : xrange(iface.Iterations())) { - Y_UNUSED(i); - Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCount()); - } -} - -Y_CPU_BENCHMARK(RdtscLinux, iface) { - for (const auto i : xrange(iface.Iterations())) { - Y_UNUSED(i); - Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountLinux()); - } -} - -Y_CPU_BENCHMARK(RdtscAgri1, iface) { - for (const auto i : xrange(iface.Iterations())) { - Y_UNUSED(i); - Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountAgri1()); - } -} - -Y_CPU_BENCHMARK(RdtscAgri2, iface) { - for (const auto i : xrange(iface.Iterations())) { - Y_UNUSED(i); - Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountAgri2()); - } -} + +#include <util/system/datetime.h> +#include <util/generic/xrange.h> + +Y_FORCE_INLINE ui64 GetCycleCountLinux() { + unsigned hi, lo; + __asm__ __volatile__("lfence\n" + "rdtsc" + : "=a"(lo), "=d"(hi)); + return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); +} + +Y_FORCE_INLINE ui64 GetCycleCountAgri1() { + unsigned hi, lo; + + __asm__ __volatile__("rdtscp\n" + : "=a"(lo), "=d"(hi)::"%rbx", "%rcx"); + + return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); +} + +Y_FORCE_INLINE ui64 GetCycleCountAgri2() { + unsigned hi, lo; + __asm__ __volatile__("rdtscp\n" + : "=a"(lo), "=d"(hi)::"%rbx", "%rcx"); + /* call cpuid to prevent out of order execution */ + __asm__ __volatile__("mov $0, %%eax\n" + "cpuid\n" :: + : "%eax"); + + return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); +} + +Y_CPU_BENCHMARK(RdtscUtil, iface) { + for (const auto i : xrange(iface.Iterations())) { + Y_UNUSED(i); + Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCount()); + } +} + +Y_CPU_BENCHMARK(RdtscLinux, iface) { + for (const auto i : xrange(iface.Iterations())) { + Y_UNUSED(i); + Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountLinux()); + } +} + +Y_CPU_BENCHMARK(RdtscAgri1, iface) { + for (const auto i : xrange(iface.Iterations())) { + Y_UNUSED(i); + Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountAgri1()); + } +} + +Y_CPU_BENCHMARK(RdtscAgri2, iface) { + for (const auto i : xrange(iface.Iterations())) { + Y_UNUSED(i); + Y_DO_NOT_OPTIMIZE_AWAY(GetCycleCountAgri2()); + } +} diff --git a/util/system/benchmark/rdtsc/ya.make b/util/system/benchmark/rdtsc/ya.make index 7059abc3a4..bd830bbe1d 100644 --- a/util/system/benchmark/rdtsc/ya.make +++ b/util/system/benchmark/rdtsc/ya.make @@ -1,10 +1,10 @@ Y_BENCHMARK() - + OWNER(g:util) SUBSCRIBER(g:util-subscribers) - -SRCS( - main.cpp -) - -END() + +SRCS( + main.cpp +) + +END() diff --git a/util/system/benchmark/ya.make b/util/system/benchmark/ya.make index 12fa9af9d6..97f9fcd361 100644 --- a/util/system/benchmark/ya.make +++ b/util/system/benchmark/ya.make @@ -10,9 +10,9 @@ RECURSE( create_destroy_thread create_destroy_thread/metrics ) - -IF (NOT OS_WINDOWS) - RECURSE( - rdtsc - ) -ENDIF() + +IF (NOT OS_WINDOWS) + RECURSE( + rdtsc + ) +ENDIF() diff --git a/util/system/byteorder.cpp b/util/system/byteorder.cpp index 5db3d30297..9bb56a33a1 100644 --- a/util/system/byteorder.cpp +++ b/util/system/byteorder.cpp @@ -1 +1 @@ -#include "byteorder.h" +#include "byteorder.h" diff --git a/util/system/byteorder.h b/util/system/byteorder.h index 94b9fea515..747f5f7788 100644 --- a/util/system/byteorder.h +++ b/util/system/byteorder.h @@ -1,141 +1,141 @@ #pragma once - + #include "defaults.h" - -//#define USE_GENERIC_ENDIAN_CVT - -#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT) - #include <byteswap.h> -#elif defined(_darwin_) - #if defined(_arm_) || defined(__IOS__) - #include <architecture/byte_order.h> - #else - #include <machine/byte_order.h> - #endif + +//#define USE_GENERIC_ENDIAN_CVT + +#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT) + #include <byteswap.h> +#elif defined(_darwin_) + #if defined(_arm_) || defined(__IOS__) + #include <architecture/byte_order.h> + #else + #include <machine/byte_order.h> + #endif #else - #include <util/generic/utility.h> + #include <util/generic/utility.h> #endif - -#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT) - #define SwapBytes16 bswap_16 - #define SwapBytes32 bswap_32 - #define SwapBytes64 bswap_64 -#elif defined(_darwin_) - #ifdef _arm_ - #define SwapBytes16 _OSSwapInt16 - #define SwapBytes32 _OSSwapInt32 - #define SwapBytes64 _OSSwapInt64 - #else - #define SwapBytes16 OSSwapInt16 - #define SwapBytes32 OSSwapInt32 - #define SwapBytes64 OSSwapInt64 - #endif + +#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT) + #define SwapBytes16 bswap_16 + #define SwapBytes32 bswap_32 + #define SwapBytes64 bswap_64 +#elif defined(_darwin_) + #ifdef _arm_ + #define SwapBytes16 _OSSwapInt16 + #define SwapBytes32 _OSSwapInt32 + #define SwapBytes64 _OSSwapInt64 + #else + #define SwapBytes16 OSSwapInt16 + #define SwapBytes32 OSSwapInt32 + #define SwapBytes64 OSSwapInt64 + #endif #endif - + #ifndef SwapBytes16 inline ui16 SwapBytes16(ui16 val) noexcept { #define byte_n(__val, __n) ((((unsigned char*)(&__val))[__n])) - DoSwap(byte_n(val, 0), byte_n(val, 1)); - return val; + DoSwap(byte_n(val, 0), byte_n(val, 1)); + return val; #undef byte_n -} +} #endif - + #ifndef SwapBytes32 inline ui32 SwapBytes32(ui32 val) noexcept { #define byte_n(__val, __n) ((((unsigned char*)(&__val))[__n])) - DoSwap(byte_n(val, 0), byte_n(val, 3)); - DoSwap(byte_n(val, 1), byte_n(val, 2)); - return val; + DoSwap(byte_n(val, 0), byte_n(val, 3)); + DoSwap(byte_n(val, 1), byte_n(val, 2)); + return val; #undef byte_n -} +} #endif - + #ifndef SwapBytes64 inline ui64 SwapBytes64(ui64 val) noexcept { - union { - ui64 val; - ui32 p[2]; - } tmp, ret; - - tmp.val = val; - ret.p[0] = SwapBytes32(tmp.p[1]); - ret.p[1] = SwapBytes32(tmp.p[0]); - - return ret.val; -} -#endif - + union { + ui64 val; + ui32 p[2]; + } tmp, ret; + + tmp.val = val; + ret.p[0] = SwapBytes32(tmp.p[1]); + ret.p[1] = SwapBytes32(tmp.p[0]); + + return ret.val; +} +#endif + //for convenience static inline ui8 SwapBytes8(ui8 v) noexcept { - return v; -} - -namespace NSwapBytes { - template <unsigned N> - struct TSwapBytesHelper { - }; - -#define DEF_SB(X) \ - template <> \ - struct TSwapBytesHelper<X> { \ - template <class T> \ - static inline T Swap(T t) noexcept { \ - return (T)SwapBytes##X((ui##X)t); \ - } \ - }; - - DEF_SB(8) - DEF_SB(16) - DEF_SB(32) - DEF_SB(64) - -#undef DEF_SB -} - -template <class T> + return v; +} + +namespace NSwapBytes { + template <unsigned N> + struct TSwapBytesHelper { + }; + +#define DEF_SB(X) \ + template <> \ + struct TSwapBytesHelper<X> { \ + template <class T> \ + static inline T Swap(T t) noexcept { \ + return (T)SwapBytes##X((ui##X)t); \ + } \ + }; + + DEF_SB(8) + DEF_SB(16) + DEF_SB(32) + DEF_SB(64) + +#undef DEF_SB +} + +template <class T> inline T SwapBytes(T val) noexcept { - return NSwapBytes::TSwapBytesHelper<sizeof(T) * 8>::Swap(val); -} - -template <class T> + return NSwapBytes::TSwapBytesHelper<sizeof(T) * 8>::Swap(val); +} + +template <class T> inline T LittleToBig(T val) noexcept { - return SwapBytes(val); -} - -template <class T> + return SwapBytes(val); +} + +template <class T> inline T BigToLittle(T val) noexcept { - return LittleToBig(val); -} - -template <class T> + return LittleToBig(val); +} + +template <class T> inline T HostToInet(T val) noexcept { -#if defined(_big_endian_) - return val; -#elif defined(_little_endian_) - return LittleToBig(val); -#else - #error todo -#endif -} - -template <class T> +#if defined(_big_endian_) + return val; +#elif defined(_little_endian_) + return LittleToBig(val); +#else + #error todo +#endif +} + +template <class T> inline T InetToHost(T val) noexcept { - return HostToInet(val); -} - -template <class T> + return HostToInet(val); +} + +template <class T> inline T HostToLittle(T val) noexcept { -#if defined(_big_endian_) - return BigToLittle(val); -#elif defined(_little_endian_) - return val; -#else - #error todo -#endif -} - -template <class T> +#if defined(_big_endian_) + return BigToLittle(val); +#elif defined(_little_endian_) + return val; +#else + #error todo +#endif +} + +template <class T> inline T LittleToHost(T val) noexcept { - return HostToLittle(val); -} + return HostToLittle(val); +} diff --git a/util/system/byteorder_ut.cpp b/util/system/byteorder_ut.cpp index 39b8603d3f..3d75d9cfdd 100644 --- a/util/system/byteorder_ut.cpp +++ b/util/system/byteorder_ut.cpp @@ -1,26 +1,26 @@ -#include "byteorder.h" - +#include "byteorder.h" + #include <library/cpp/testing/unittest/registar.h> class TByteOrderTest: public TTestBase { - UNIT_TEST_SUITE(TByteOrderTest); - UNIT_TEST(TestSwap16) - UNIT_TEST(TestSwap32) - UNIT_TEST(TestSwap64) - UNIT_TEST_SUITE_END(); - -private: - inline void TestSwap16() { - UNIT_ASSERT_EQUAL((ui16)0x1234, SwapBytes((ui16)0x3412)); - } - - inline void TestSwap32() { - UNIT_ASSERT_EQUAL(0x12345678, SwapBytes(0x78563412)); - } - - inline void TestSwap64() { - UNIT_ASSERT_EQUAL(0x1234567890abcdefULL, SwapBytes((ui64)ULL(0xefcdab9078563412))); - } + UNIT_TEST_SUITE(TByteOrderTest); + UNIT_TEST(TestSwap16) + UNIT_TEST(TestSwap32) + UNIT_TEST(TestSwap64) + UNIT_TEST_SUITE_END(); + +private: + inline void TestSwap16() { + UNIT_ASSERT_EQUAL((ui16)0x1234, SwapBytes((ui16)0x3412)); + } + + inline void TestSwap32() { + UNIT_ASSERT_EQUAL(0x12345678, SwapBytes(0x78563412)); + } + + inline void TestSwap64() { + UNIT_ASSERT_EQUAL(0x1234567890abcdefULL, SwapBytes((ui64)ULL(0xefcdab9078563412))); + } }; UNIT_TEST_SUITE_REGISTRATION(TByteOrderTest); diff --git a/util/system/compat.cpp b/util/system/compat.cpp index 18fbfa296a..8342e76983 100644 --- a/util/system/compat.cpp +++ b/util/system/compat.cpp @@ -1,26 +1,26 @@ -#include "compat.h" -#include "defaults.h" -#include "progname.h" - +#include "compat.h" +#include "defaults.h" +#include "progname.h" + #include <cctype> #include <cerrno> #include <cstdio> -#include <cstring> +#include <cstring> #include <cstdarg> #include <cstdlib> #include <util/generic/string.h> #ifdef _win_ - #include "winint.h" - #include <io.h> + #include "winint.h" + #include <io.h> #endif #ifndef HAVE_NATIVE_GETPROGNAME const char* getprogname() { return GetProgramName().data(); } -#endif +#endif #ifdef _win_ @@ -32,11 +32,11 @@ void usleep(i64 len) { Sleep((unsigned long)len / 1000); } - #include <fcntl.h> -int ftruncate(int fd, i64 length) { + #include <fcntl.h> +int ftruncate(int fd, i64 length) { return _chsize_s(fd, length); } -int truncate(const char* name, i64 length) { +int truncate(const char* name, i64 length) { int fd = ::_open(name, _O_WRONLY); int ret = ftruncate(fd, length); ::close(fd); diff --git a/util/system/compat.h b/util/system/compat.h index c53dbcca17..01ec1b0b7d 100644 --- a/util/system/compat.h +++ b/util/system/compat.h @@ -1,84 +1,84 @@ #pragma once -#include "defaults.h" - -#include <cstdarg> - +#include "defaults.h" + +#include <cstdarg> + #include <csignal> -#if defined(_unix_) - #include <unistd.h> -#endif - -#if defined(_win_) - #include <process.h> +#if defined(_unix_) + #include <unistd.h> +#endif + +#if defined(_win_) + #include <process.h> #endif extern "C" { -#if defined(_win_) - using pid_t = int; - - inline unsigned int alarm(unsigned int /*seconds*/) { - return 0; // no alarm is currently set :) - } - - #define SIGQUIT SIGBREAK // instead of 3 - #define SIGKILL SIGTERM // instead of 9 - #define SIGPIPE 13 //will not receive under win? - #define SIGALRM 14 //will not receive under win? -#endif - +#if defined(_win_) + using pid_t = int; + + inline unsigned int alarm(unsigned int /*seconds*/) { + return 0; // no alarm is currently set :) + } + + #define SIGQUIT SIGBREAK // instead of 3 + #define SIGKILL SIGTERM // instead of 9 + #define SIGPIPE 13 //will not receive under win? + #define SIGALRM 14 //will not receive under win? +#endif + #if defined(__FreeBSD__) || defined(_darwin_) - #define HAVE_NATIVE_GETPROGNAME + #define HAVE_NATIVE_GETPROGNAME #endif #ifndef HAVE_NATIVE_GETPROGNAME - const char* getprogname(); + const char* getprogname(); #endif -#if defined(_MSC_VER) - void err(int e, const char* m, ...); - void errx(int e, const char* m, ...); - void warn(const char* m, ...); - void warnx(const char* m, ...); - void vwarnx(const char* format, va_list ap); - void vwarn(const char* format, va_list ap); - void verrx(int status, const char* format, va_list ap); +#if defined(_MSC_VER) + void err(int e, const char* m, ...); + void errx(int e, const char* m, ...); + void warn(const char* m, ...); + void warnx(const char* m, ...); + void vwarnx(const char* format, va_list ap); + void vwarn(const char* format, va_list ap); + void verrx(int status, const char* format, va_list ap); #else - #include <err.h> + #include <err.h> #endif -} +} #ifdef _MSC_VER - #define popen _popen - #define pclose _pclose + #define popen _popen + #define pclose _pclose #endif #ifdef _win_ - #define NAME_MAX FILENAME_MAX + #define NAME_MAX FILENAME_MAX #endif #ifdef _sun_ - #define NAME_MAX PATH_MAX + #define NAME_MAX PATH_MAX #endif #ifdef _win_ - #ifdef sleep // may be defined by perl - #undef sleep - #endif + #ifdef sleep // may be defined by perl + #undef sleep + #endif void sleep(i64 len); void usleep(i64 len); -#endif +#endif #ifdef _win_ int ftruncate(int fd, i64 length); int truncate(const char* name, i64 length); #endif -#if defined(GNUC) - #ifndef va_copy - #define va_copy __va_copy - #endif -#endif +#if defined(GNUC) + #ifndef va_copy + #define va_copy __va_copy + #endif +#endif diff --git a/util/system/compat_ut.cpp b/util/system/compat_ut.cpp index dbd9289c17..9ef15e015f 100644 --- a/util/system/compat_ut.cpp +++ b/util/system/compat_ut.cpp @@ -1,5 +1,5 @@ -#include "compat.h" - +#include "compat.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/folder/dirut.h> diff --git a/util/system/compiler.cpp b/util/system/compiler.cpp index d4b3cca0af..c76ef7ff37 100644 --- a/util/system/compiler.cpp +++ b/util/system/compiler.cpp @@ -1,4 +1,4 @@ -#include "compiler.h" +#include "compiler.h" #include <cstdlib> [[noreturn]] Y_HIDDEN void _YandexAbort() { diff --git a/util/system/compiler.h b/util/system/compiler.h index b373edcc46..4b70b8f452 100644 --- a/util/system/compiler.h +++ b/util/system/compiler.h @@ -1,11 +1,11 @@ -#pragma once - +#pragma once + #if defined(_MSC_VER) - #include <intrin.h> + #include <intrin.h> #endif -// useful cross-platfrom definitions for compilers - +// useful cross-platfrom definitions for compilers + /** * @def Y_FUNC_SIGNATURE * @@ -29,29 +29,29 @@ * @endcode */ #if defined(__GNUC__) - #define Y_FUNC_SIGNATURE __PRETTY_FUNCTION__ + #define Y_FUNC_SIGNATURE __PRETTY_FUNCTION__ #elif defined(_MSC_VER) - #define Y_FUNC_SIGNATURE __FUNCSIG__ + #define Y_FUNC_SIGNATURE __FUNCSIG__ #else - #define Y_FUNC_SIGNATURE "" -#endif - -#ifdef __GNUC__ - #define Y_PRINTF_FORMAT(n, m) __attribute__((__format__(__printf__, n, m))) -#endif - -#ifndef Y_PRINTF_FORMAT - #define Y_PRINTF_FORMAT(n, m) -#endif - -#if defined(__clang__) - #define Y_NO_SANITIZE(...) __attribute__((no_sanitize(__VA_ARGS__))) -#endif - -#if !defined(Y_NO_SANITIZE) - #define Y_NO_SANITIZE(...) -#endif - + #define Y_FUNC_SIGNATURE "" +#endif + +#ifdef __GNUC__ + #define Y_PRINTF_FORMAT(n, m) __attribute__((__format__(__printf__, n, m))) +#endif + +#ifndef Y_PRINTF_FORMAT + #define Y_PRINTF_FORMAT(n, m) +#endif + +#if defined(__clang__) + #define Y_NO_SANITIZE(...) __attribute__((no_sanitize(__VA_ARGS__))) +#endif + +#if !defined(Y_NO_SANITIZE) + #define Y_NO_SANITIZE(...) +#endif + /** * @def Y_DECLARE_UNUSED * @@ -68,21 +68,21 @@ * } * @endcode */ -#ifdef __GNUC__ - #define Y_DECLARE_UNUSED __attribute__((unused)) -#endif - +#ifdef __GNUC__ + #define Y_DECLARE_UNUSED __attribute__((unused)) +#endif + #ifndef Y_DECLARE_UNUSED - #define Y_DECLARE_UNUSED -#endif - + #define Y_DECLARE_UNUSED +#endif + #if defined(__GNUC__) - #define Y_LIKELY(Cond) __builtin_expect(!!(Cond), 1) - #define Y_UNLIKELY(Cond) __builtin_expect(!!(Cond), 0) - #define Y_PREFETCH_READ(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 0, Priority) - #define Y_PREFETCH_WRITE(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 1, Priority) -#endif - + #define Y_LIKELY(Cond) __builtin_expect(!!(Cond), 1) + #define Y_UNLIKELY(Cond) __builtin_expect(!!(Cond), 0) + #define Y_PREFETCH_READ(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 0, Priority) + #define Y_PREFETCH_WRITE(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 1, Priority) +#endif + /** * @def Y_FORCE_INLINE * @@ -90,113 +90,113 @@ * it to be inlined. */ #if !defined(Y_FORCE_INLINE) - #if defined(CLANG_COVERAGE) - #/* excessive __always_inline__ might significantly slow down compilation of an instrumented unit */ - #define Y_FORCE_INLINE inline - #elif defined(_MSC_VER) - #define Y_FORCE_INLINE __forceinline - #elif defined(__GNUC__) - #/* Clang also defines __GNUC__ (as 4) */ - #define Y_FORCE_INLINE inline __attribute__((__always_inline__)) - #else - #define Y_FORCE_INLINE inline - #endif + #if defined(CLANG_COVERAGE) + #/* excessive __always_inline__ might significantly slow down compilation of an instrumented unit */ + #define Y_FORCE_INLINE inline + #elif defined(_MSC_VER) + #define Y_FORCE_INLINE __forceinline + #elif defined(__GNUC__) + #/* Clang also defines __GNUC__ (as 4) */ + #define Y_FORCE_INLINE inline __attribute__((__always_inline__)) + #else + #define Y_FORCE_INLINE inline + #endif #endif /** - * @def Y_NO_INLINE + * @def Y_NO_INLINE * * Macro to use in place of 'inline' in function declaration/definition to * prevent it from being inlined. */ -#if !defined(Y_NO_INLINE) - #if defined(_MSC_VER) - #define Y_NO_INLINE __declspec(noinline) - #elif defined(__GNUC__) || defined(__INTEL_COMPILER) - #/* Clang also defines __GNUC__ (as 4) */ - #define Y_NO_INLINE __attribute__((__noinline__)) - #else - #define Y_NO_INLINE - #endif -#endif - -//to cheat compiler about strict aliasing or similar problems -#if defined(__GNUC__) - #define Y_FAKE_READ(X) \ - do { \ - __asm__ __volatile__("" \ - : \ - : "m"(X)); \ - } while (0) - - #define Y_FAKE_WRITE(X) \ - do { \ - __asm__ __volatile__("" \ - : "=m"(X)); \ - } while (0) -#endif - -#if !defined(Y_FAKE_READ) - #define Y_FAKE_READ(X) -#endif - -#if !defined(Y_FAKE_WRITE) - #define Y_FAKE_WRITE(X) -#endif - -#ifndef Y_PREFETCH_READ - #define Y_PREFETCH_READ(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority -#endif - -#ifndef Y_PREFETCH_WRITE - #define Y_PREFETCH_WRITE(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority -#endif - +#if !defined(Y_NO_INLINE) + #if defined(_MSC_VER) + #define Y_NO_INLINE __declspec(noinline) + #elif defined(__GNUC__) || defined(__INTEL_COMPILER) + #/* Clang also defines __GNUC__ (as 4) */ + #define Y_NO_INLINE __attribute__((__noinline__)) + #else + #define Y_NO_INLINE + #endif +#endif + +//to cheat compiler about strict aliasing or similar problems +#if defined(__GNUC__) + #define Y_FAKE_READ(X) \ + do { \ + __asm__ __volatile__("" \ + : \ + : "m"(X)); \ + } while (0) + + #define Y_FAKE_WRITE(X) \ + do { \ + __asm__ __volatile__("" \ + : "=m"(X)); \ + } while (0) +#endif + +#if !defined(Y_FAKE_READ) + #define Y_FAKE_READ(X) +#endif + +#if !defined(Y_FAKE_WRITE) + #define Y_FAKE_WRITE(X) +#endif + +#ifndef Y_PREFETCH_READ + #define Y_PREFETCH_READ(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority +#endif + +#ifndef Y_PREFETCH_WRITE + #define Y_PREFETCH_WRITE(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority +#endif + #ifndef Y_LIKELY - #define Y_LIKELY(Cond) (Cond) - #define Y_UNLIKELY(Cond) (Cond) -#endif - -#ifdef __GNUC__ + #define Y_LIKELY(Cond) (Cond) + #define Y_UNLIKELY(Cond) (Cond) +#endif + +#ifdef __GNUC__ #define Y_PACKED __attribute__((packed)) -#else +#else #define Y_PACKED -#endif - +#endif + #if defined(__GNUC__) - #define Y_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#endif - -#ifndef Y_WARN_UNUSED_RESULT - #define Y_WARN_UNUSED_RESULT -#endif - + #define Y_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#endif + +#ifndef Y_WARN_UNUSED_RESULT + #define Y_WARN_UNUSED_RESULT +#endif + +#if defined(__GNUC__) + #define Y_HIDDEN __attribute__((visibility("hidden"))) +#endif + +#if !defined(Y_HIDDEN) + #define Y_HIDDEN +#endif + #if defined(__GNUC__) - #define Y_HIDDEN __attribute__((visibility("hidden"))) -#endif - -#if !defined(Y_HIDDEN) - #define Y_HIDDEN -#endif - -#if defined(__GNUC__) - #define Y_PUBLIC __attribute__((visibility("default"))) + #define Y_PUBLIC __attribute__((visibility("default"))) #endif #if !defined(Y_PUBLIC) - #define Y_PUBLIC + #define Y_PUBLIC #endif #if !defined(Y_UNUSED) && !defined(__cplusplus) - #define Y_UNUSED(var) (void)(var) -#endif + #define Y_UNUSED(var) (void)(var) +#endif #if !defined(Y_UNUSED) && defined(__cplusplus) -template <class... Types> -constexpr Y_FORCE_INLINE int Y_UNUSED(Types&&...) { - return 0; -}; +template <class... Types> +constexpr Y_FORCE_INLINE int Y_UNUSED(Types&&...) { + return 0; +}; #endif - + /** * @def Y_ASSUME * @@ -230,18 +230,18 @@ constexpr Y_FORCE_INLINE int Y_UNUSED(Types&&...) { * @endcode */ #if defined(__GNUC__) - #define Y_ASSUME(condition) ((condition) ? (void)0 : __builtin_unreachable()) + #define Y_ASSUME(condition) ((condition) ? (void)0 : __builtin_unreachable()) #elif defined(_MSC_VER) - #define Y_ASSUME(condition) __assume(condition) + #define Y_ASSUME(condition) __assume(condition) #else - #define Y_ASSUME(condition) Y_UNUSED(condition) + #define Y_ASSUME(condition) Y_UNUSED(condition) #endif #ifdef __cplusplus [[noreturn]] #endif -Y_HIDDEN void -_YandexAbort(); +Y_HIDDEN void +_YandexAbort(); /** * @def Y_UNREACHABLE @@ -263,78 +263,78 @@ _YandexAbort(); * @endcode */ #if defined(__GNUC__) - #define Y_UNREACHABLE() __builtin_unreachable() -#elif defined(_MSC_VER) - #define Y_UNREACHABLE() __assume(false) + #define Y_UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) + #define Y_UNREACHABLE() __assume(false) #else - #define Y_UNREACHABLE() _YandexAbort() + #define Y_UNREACHABLE() _YandexAbort() #endif -#if defined(undefined_sanitizer_enabled) - #define _ubsan_enabled_ -#endif +#if defined(undefined_sanitizer_enabled) + #define _ubsan_enabled_ +#endif #ifdef __clang__ - #if __has_feature(thread_sanitizer) - #define _tsan_enabled_ - #endif - #if __has_feature(memory_sanitizer) - #define _msan_enabled_ - #endif - #if __has_feature(address_sanitizer) - #define _asan_enabled_ - #endif - + #if __has_feature(thread_sanitizer) + #define _tsan_enabled_ + #endif + #if __has_feature(memory_sanitizer) + #define _msan_enabled_ + #endif + #if __has_feature(address_sanitizer) + #define _asan_enabled_ + #endif + #else - #if defined(thread_sanitizer_enabled) || defined(__SANITIZE_THREAD__) - #define _tsan_enabled_ - #endif - #if defined(memory_sanitizer_enabled) - #define _msan_enabled_ - #endif - #if defined(address_sanitizer_enabled) || defined(__SANITIZE_ADDRESS__) - #define _asan_enabled_ - #endif - -#endif - -#if defined(_asan_enabled_) || defined(_msan_enabled_) || defined(_tsan_enabled_) || defined(_ubsan_enabled_) - #define _san_enabled_ -#endif - -#if defined(_MSC_VER) - #define __PRETTY_FUNCTION__ __FUNCSIG__ -#endif + #if defined(thread_sanitizer_enabled) || defined(__SANITIZE_THREAD__) + #define _tsan_enabled_ + #endif + #if defined(memory_sanitizer_enabled) + #define _msan_enabled_ + #endif + #if defined(address_sanitizer_enabled) || defined(__SANITIZE_ADDRESS__) + #define _asan_enabled_ + #endif + +#endif + +#if defined(_asan_enabled_) || defined(_msan_enabled_) || defined(_tsan_enabled_) || defined(_ubsan_enabled_) + #define _san_enabled_ +#endif + +#if defined(_MSC_VER) + #define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif #if defined(__GNUC__) - #define Y_WEAK __attribute__((weak)) + #define Y_WEAK __attribute__((weak)) #else - #define Y_WEAK + #define Y_WEAK #endif #if defined(__CUDACC_VER_MAJOR__) - #define Y_CUDA_AT_LEAST(x, y) (__CUDACC_VER_MAJOR__ > x || (__CUDACC_VER_MAJOR__ == x && __CUDACC_VER_MINOR__ >= y)) + #define Y_CUDA_AT_LEAST(x, y) (__CUDACC_VER_MAJOR__ > x || (__CUDACC_VER_MAJOR__ == x && __CUDACC_VER_MINOR__ >= y)) #else - #define Y_CUDA_AT_LEAST(x, y) 0 + #define Y_CUDA_AT_LEAST(x, y) 0 #endif // NVidia CUDA C++ Compiler did not know about noexcept keyword until version 9.0 #if !Y_CUDA_AT_LEAST(9, 0) - #if defined(__CUDACC__) && !defined(noexcept) - #define noexcept throw() - #endif + #if defined(__CUDACC__) && !defined(noexcept) + #define noexcept throw() + #endif #endif #if defined(__GNUC__) - #define Y_COLD __attribute__((cold)) - #define Y_LEAF __attribute__((leaf)) - #define Y_WRAPPER __attribute__((artificial)) + #define Y_COLD __attribute__((cold)) + #define Y_LEAF __attribute__((leaf)) + #define Y_WRAPPER __attribute__((artificial)) #else - #define Y_COLD - #define Y_LEAF - #define Y_WRAPPER + #define Y_COLD + #define Y_LEAF + #define Y_WRAPPER #endif /** @@ -356,11 +356,11 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA(x) _Pragma(x) -#elif defined(_MSC_VER) - #define Y_PRAGMA(x) __pragma(x) + #define Y_PRAGMA(x) _Pragma(x) +#elif defined(_MSC_VER) + #define Y_PRAGMA(x) __pragma(x) #else - #define Y_PRAGMA(x) + #define Y_PRAGMA(x) #endif /** @@ -378,13 +378,13 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_DIAGNOSTIC_PUSH \ - Y_PRAGMA("GCC diagnostic push") + #define Y_PRAGMA_DIAGNOSTIC_PUSH \ + Y_PRAGMA("GCC diagnostic push") #elif defined(_MSC_VER) - #define Y_PRAGMA_DIAGNOSTIC_PUSH \ - Y_PRAGMA(warning(push)) + #define Y_PRAGMA_DIAGNOSTIC_PUSH \ + Y_PRAGMA(warning(push)) #else - #define Y_PRAGMA_DIAGNOSTIC_PUSH + #define Y_PRAGMA_DIAGNOSTIC_PUSH #endif /** @@ -402,13 +402,13 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_DIAGNOSTIC_POP \ - Y_PRAGMA("GCC diagnostic pop") + #define Y_PRAGMA_DIAGNOSTIC_POP \ + Y_PRAGMA("GCC diagnostic pop") #elif defined(_MSC_VER) - #define Y_PRAGMA_DIAGNOSTIC_POP \ - Y_PRAGMA(warning(pop)) + #define Y_PRAGMA_DIAGNOSTIC_POP \ + Y_PRAGMA(warning(pop)) #else - #define Y_PRAGMA_DIAGNOSTIC_POP + #define Y_PRAGMA_DIAGNOSTIC_POP #endif /** @@ -434,13 +434,13 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_NO_WSHADOW \ - Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"") + #define Y_PRAGMA_NO_WSHADOW \ + Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"") #elif defined(_MSC_VER) - #define Y_PRAGMA_NO_WSHADOW \ - Y_PRAGMA(warning(disable : 4456 4457)) + #define Y_PRAGMA_NO_WSHADOW \ + Y_PRAGMA(warning(disable : 4456 4457)) #else - #define Y_PRAGMA_NO_WSHADOW + #define Y_PRAGMA_NO_WSHADOW #endif /** @@ -470,12 +470,12 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_NO_UNUSED_FUNCTION \ - Y_PRAGMA("GCC diagnostic ignored \"-Wunused-function\"") + #define Y_PRAGMA_NO_UNUSED_FUNCTION \ + Y_PRAGMA("GCC diagnostic ignored \"-Wunused-function\"") #else - #define Y_PRAGMA_NO_UNUSED_FUNCTION + #define Y_PRAGMA_NO_UNUSED_FUNCTION #endif - + /** * @ def Y_PRAGMA_NO_UNUSED_PARAMETER * @@ -504,14 +504,14 @@ _YandexAbort(); * Y_PRAGMA_DIAGNOSTIC_POP * @endcode */ -#if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_NO_UNUSED_PARAMETER \ - Y_PRAGMA("GCC diagnostic ignored \"-Wunused-parameter\"") +#if defined(__clang__) || defined(__GNUC__) + #define Y_PRAGMA_NO_UNUSED_PARAMETER \ + Y_PRAGMA("GCC diagnostic ignored \"-Wunused-parameter\"") #elif defined(_MSC_VER) - #define Y_PRAGMA_NO_UNUSED_PARAMETER \ - Y_PRAGMA(warning(disable : 4100)) + #define Y_PRAGMA_NO_UNUSED_PARAMETER \ + Y_PRAGMA(warning(disable : 4100)) #else - #define Y_PRAGMA_NO_UNUSED_PARAMETER + #define Y_PRAGMA_NO_UNUSED_PARAMETER #endif /** @@ -541,18 +541,18 @@ _YandexAbort(); * @endcode */ #if defined(__clang__) || defined(__GNUC__) - #define Y_PRAGMA_NO_DEPRECATED \ - Y_PRAGMA("GCC diagnostic ignored \"-Wdeprecated\"") + #define Y_PRAGMA_NO_DEPRECATED \ + Y_PRAGMA("GCC diagnostic ignored \"-Wdeprecated\"") #elif defined(_MSC_VER) - #define Y_PRAGMA_NO_DEPRECATED \ - Y_PRAGMA(warning(disable : 4996)) + #define Y_PRAGMA_NO_DEPRECATED \ + Y_PRAGMA(warning(disable : 4996)) #else - #define Y_PRAGMA_NO_DEPRECATED + #define Y_PRAGMA_NO_DEPRECATED #endif // Memory sanitizer sometimes doesn't correctly set parameter shadow of constant functions. #if (defined(__clang__) || defined(__GNUC__)) && !defined(_msan_enabled_) - /** + /** * @def Y_CONST_FUNCTION methods and functions, marked with this method are promised to: 1. do not have side effects @@ -562,15 +562,15 @@ _YandexAbort(); NOTE: in common case this attribute can't be set if method have pointer-arguments NOTE: as result there no any reason to discard result of such method */ - #define Y_CONST_FUNCTION [[gnu::const]] -#endif - -#if !defined(Y_CONST_FUNCTION) - #define Y_CONST_FUNCTION -#endif - -#if defined(__clang__) || defined(__GNUC__) - /** + #define Y_CONST_FUNCTION [[gnu::const]] +#endif + +#if !defined(Y_CONST_FUNCTION) + #define Y_CONST_FUNCTION +#endif + +#if defined(__clang__) || defined(__GNUC__) + /** * @def Y_PURE_FUNCTION methods and functions, marked with this method are promised to: 1. do not have side effects @@ -578,12 +578,12 @@ _YandexAbort(); this allow compilers to do hard optimization of that functions NOTE: as result there no any reason to discard result of such method */ - #define Y_PURE_FUNCTION [[gnu::pure]] -#endif - -#if !defined(Y_PURE_FUNCTION) - #define Y_PURE_FUNCTION -#endif + #define Y_PURE_FUNCTION [[gnu::pure]] +#endif + +#if !defined(Y_PURE_FUNCTION) + #define Y_PURE_FUNCTION +#endif /** * @ def Y_HAVE_INT128 @@ -599,7 +599,7 @@ _YandexAbort(); * @endcode */ #if defined(__SIZEOF_INT128__) - #define Y_HAVE_INT128 1 + #define Y_HAVE_INT128 1 #endif /** @@ -609,19 +609,19 @@ _YandexAbort(); * for compilers that doesn't support XRay. */ #if defined(XRAY) && defined(__cplusplus) - #include <xray/xray_interface.h> - #define Y_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] - #define Y_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] - #define Y_XRAY_CUSTOM_EVENT(__string, __length) \ - do { \ - __xray_customevent(__string, __length); \ - } while (0) + #include <xray/xray_interface.h> + #define Y_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] + #define Y_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] + #define Y_XRAY_CUSTOM_EVENT(__string, __length) \ + do { \ + __xray_customevent(__string, __length); \ + } while (0) #else - #define Y_XRAY_ALWAYS_INSTRUMENT - #define Y_XRAY_NEVER_INSTRUMENT - #define Y_XRAY_CUSTOM_EVENT(__string, __length) \ - do { \ - } while (0) + #define Y_XRAY_ALWAYS_INSTRUMENT + #define Y_XRAY_NEVER_INSTRUMENT + #define Y_XRAY_CUSTOM_EVENT(__string, __length) \ + do { \ + } while (0) #endif #ifdef __cplusplus @@ -630,21 +630,21 @@ void UseCharPointerImpl(volatile const char*); template <typename T> Y_FORCE_INLINE void DoNotOptimizeAway(T&& datum) { - #if defined(_MSC_VER) + #if defined(_MSC_VER) UseCharPointerImpl(&reinterpret_cast<volatile const char&>(datum)); _ReadWriteBarrier(); - #elif defined(__GNUC__) && defined(_x86_) + #elif defined(__GNUC__) && defined(_x86_) asm volatile("" : : "X"(datum)); - #else + #else Y_FAKE_READ(datum); - #endif + #endif } - /** + /** * Use this macro to prevent unused variables elimination. */ - #define Y_DO_NOT_OPTIMIZE_AWAY(X) ::DoNotOptimizeAway(X) + #define Y_DO_NOT_OPTIMIZE_AWAY(X) ::DoNotOptimizeAway(X) #endif diff --git a/util/system/condvar.cpp b/util/system/condvar.cpp index 62f3d22356..bb99fa2c3e 100644 --- a/util/system/condvar.cpp +++ b/util/system/condvar.cpp @@ -1,147 +1,147 @@ -#include "event.h" -#include "mutex.h" -#include "yassert.h" -#include "condvar.h" -#include "datetime.h" -#include "spinlock.h" - -#include <util/generic/ylimits.h> -#include <util/generic/intrlist.h> -#include <util/generic/yexception.h> - -#include <cstdlib> - -#if defined(_unix_) - #include <sys/time.h> - #include <pthread.h> - #include <cerrno> +#include "event.h" +#include "mutex.h" +#include "yassert.h" +#include "condvar.h" +#include "datetime.h" +#include "spinlock.h" + +#include <util/generic/ylimits.h> +#include <util/generic/intrlist.h> +#include <util/generic/yexception.h> + +#include <cstdlib> + +#if defined(_unix_) + #include <sys/time.h> + #include <pthread.h> + #include <cerrno> #endif -namespace { - class TCondVarImpl { +namespace { + class TCondVarImpl { using TLock = TAdaptiveLock; - + struct TWaitEvent: public TIntrusiveListItem<TWaitEvent>, public TSystemEvent { - }; - + }; + using TWaitEvents = TIntrusiveList<TWaitEvent>; - - public: + + public: inline ~TCondVarImpl() { Y_ASSERT(Events_.Empty()); - } - + } + inline void Signal() noexcept { - with_lock (Lock_) { - if (!Events_.Empty()) { - Events_.PopFront()->Signal(); - } - } - } - + with_lock (Lock_) { + if (!Events_.Empty()) { + Events_.PopFront()->Signal(); + } + } + } + inline void BroadCast() noexcept { - with_lock (Lock_) { - //TODO - while (!Events_.Empty()) { - Events_.PopFront()->Signal(); - } - } - } - + with_lock (Lock_) { + //TODO + while (!Events_.Empty()) { + Events_.PopFront()->Signal(); + } + } + } + inline bool WaitD(TMutex& m, TInstant deadLine) noexcept { - TWaitEvent event; - - with_lock (Lock_) { - Events_.PushBack(&event); - } - - m.Release(); - - const bool signalled = event.WaitD(deadLine); - - m.Acquire(); - - with_lock (Lock_) { - event.Unlink(); - } - - return signalled; - } - - private: - TWaitEvents Events_; - TLock Lock_; - }; -} - -#if defined(_win_) -class TCondVar::TImpl: public TCondVarImpl { -}; -#else -class TCondVar::TImpl { -public: - inline TImpl() { + TWaitEvent event; + + with_lock (Lock_) { + Events_.PushBack(&event); + } + + m.Release(); + + const bool signalled = event.WaitD(deadLine); + + m.Acquire(); + + with_lock (Lock_) { + event.Unlink(); + } + + return signalled; + } + + private: + TWaitEvents Events_; + TLock Lock_; + }; +} + +#if defined(_win_) +class TCondVar::TImpl: public TCondVarImpl { +}; +#else +class TCondVar::TImpl { +public: + inline TImpl() { if (pthread_cond_init(&Cond_, nullptr)) { - ythrow yexception() << "can not create condvar(" << LastSystemErrorText() << ")"; - } - } + ythrow yexception() << "can not create condvar(" << LastSystemErrorText() << ")"; + } + } inline ~TImpl() { - int ret = pthread_cond_destroy(&Cond_); + int ret = pthread_cond_destroy(&Cond_); Y_VERIFY(ret == 0, "pthread_cond_destroy failed: %s", LastSystemErrorText(ret)); - } + } inline void Signal() noexcept { - int ret = pthread_cond_signal(&Cond_); + int ret = pthread_cond_signal(&Cond_); Y_VERIFY(ret == 0, "pthread_cond_signal failed: %s", LastSystemErrorText(ret)); - } + } inline bool WaitD(TMutex& lock, TInstant deadLine) noexcept { - if (deadLine == TInstant::Max()) { - int ret = pthread_cond_wait(&Cond_, (pthread_mutex_t*)lock.Handle()); + if (deadLine == TInstant::Max()) { + int ret = pthread_cond_wait(&Cond_, (pthread_mutex_t*)lock.Handle()); Y_VERIFY(ret == 0, "pthread_cond_wait failed: %s", LastSystemErrorText(ret)); - return true; - } else { - struct timespec spec; - - Zero(spec); - - spec.tv_sec = deadLine.Seconds(); - spec.tv_nsec = deadLine.NanoSecondsOfSecond(); - - int ret = pthread_cond_timedwait(&Cond_, (pthread_mutex_t*)lock.Handle(), &spec); + return true; + } else { + struct timespec spec; + + Zero(spec); + + spec.tv_sec = deadLine.Seconds(); + spec.tv_nsec = deadLine.NanoSecondsOfSecond(); + + int ret = pthread_cond_timedwait(&Cond_, (pthread_mutex_t*)lock.Handle(), &spec); Y_VERIFY(ret == 0 || ret == ETIMEDOUT, "pthread_cond_timedwait failed: %s", LastSystemErrorText(ret)); - return ret == 0; - } - } + return ret == 0; + } + } inline void BroadCast() noexcept { - int ret = pthread_cond_broadcast(&Cond_); + int ret = pthread_cond_broadcast(&Cond_); Y_VERIFY(ret == 0, "pthread_cond_broadcast failed: %s", LastSystemErrorText(ret)); - } + } -private: - pthread_cond_t Cond_; -}; -#endif +private: + pthread_cond_t Cond_; +}; +#endif -TCondVar::TCondVar() - : Impl_(new TImpl) -{ +TCondVar::TCondVar() + : Impl_(new TImpl) +{ } TCondVar::~TCondVar() = default; void TCondVar::BroadCast() noexcept { - Impl_->BroadCast(); -} - + Impl_->BroadCast(); +} + void TCondVar::Signal() noexcept { - Impl_->Signal(); + Impl_->Signal(); } bool TCondVar::WaitD(TMutex& mutex, TInstant deadLine) noexcept { - return Impl_->WaitD(mutex, deadLine); + return Impl_->WaitD(mutex, deadLine); } diff --git a/util/system/condvar.h b/util/system/condvar.h index 569162717c..82d6ca3d20 100644 --- a/util/system/condvar.h +++ b/util/system/condvar.h @@ -1,26 +1,26 @@ #pragma once -#include "mutex.h" - +#include "mutex.h" + #include <util/generic/ptr.h> #include <util/generic/noncopyable.h> #include <util/datetime/base.h> #include <utility> -class TCondVar { -public: - TCondVar(); +class TCondVar { +public: + TCondVar(); ~TCondVar(); void BroadCast() noexcept; void Signal() noexcept; - /* - * returns false if failed by timeout - */ + /* + * returns false if failed by timeout + */ bool WaitD(TMutex& m, TInstant deadline) noexcept; - + template <typename P> inline bool WaitD(TMutex& m, TInstant deadline, P pred) noexcept { while (!pred()) { @@ -31,41 +31,41 @@ public: return true; } - /* - * returns false if failed by timeout - */ + /* + * returns false if failed by timeout + */ inline bool WaitT(TMutex& m, TDuration timeout) noexcept { return WaitD(m, timeout.ToDeadLine()); - } - + } + template <typename P> inline bool WaitT(TMutex& m, TDuration timeout, P pred) noexcept { return WaitD(m, timeout.ToDeadLine(), std::move(pred)); } - /* - * infinite wait - */ + /* + * infinite wait + */ inline void WaitI(TMutex& m) noexcept { - WaitD(m, TInstant::Max()); - } - + WaitD(m, TInstant::Max()); + } + template <typename P> inline void WaitI(TMutex& m, P pred) noexcept { WaitD(m, TInstant::Max(), std::move(pred)); } - //deprecated + //deprecated inline void Wait(TMutex& m) noexcept { - WaitI(m); - } - + WaitI(m); + } + template <typename P> inline void Wait(TMutex& m, P pred) noexcept { WaitI(m, std::move(pred)); } -private: - class TImpl; - THolder<TImpl> Impl_; -}; +private: + class TImpl; + THolder<TImpl> Impl_; +}; diff --git a/util/system/condvar_ut.cpp b/util/system/condvar_ut.cpp index 5130a18d32..bfc226c39f 100644 --- a/util/system/condvar_ut.cpp +++ b/util/system/condvar_ut.cpp @@ -1,17 +1,17 @@ -#include "mutex.h" -#include "guard.h" -#include "condvar.h" - +#include "mutex.h" +#include "guard.h" +#include "condvar.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/system/atomic.h> #include <util/system/atomic_ops.h> #include <util/thread/pool.h> -class TCondVarTest: public TTestBase { +class TCondVarTest: public TTestBase { UNIT_TEST_SUITE(TCondVarTest); - UNIT_TEST(TestBasics) - UNIT_TEST(TestSyncronize) + UNIT_TEST(TestBasics) + UNIT_TEST(TestSyncronize) UNIT_TEST_SUITE_END(); struct TSharedData { @@ -23,7 +23,7 @@ class TCondVarTest: public TTestBase { , failed(false) { } - + TMutex mutex; TCondVar condVar1; TCondVar condVar2; @@ -38,47 +38,47 @@ class TCondVarTest: public TTestBase { bool failed; }; - class TThreadTask: public IObjectInQueue { - public: + class TThreadTask: public IObjectInQueue { + public: using PFunc = void (TThreadTask::*)(void); - TThreadTask(PFunc func, size_t id, size_t totalIds, TSharedData& data) - : Func_(func) - , Id_(id) - , TotalIds_(totalIds) - , Data_(data) - { - } + TThreadTask(PFunc func, size_t id, size_t totalIds, TSharedData& data) + : Func_(func) + , Id_(id) + , TotalIds_(totalIds) + , Data_(data) + { + } void Process(void*) override { - THolder<TThreadTask> This(this); - - (this->*Func_)(); - } - -#define FAIL_ASSERT(cond) \ - if (!(cond)) { \ - Data_.failed = true; \ + THolder<TThreadTask> This(this); + + (this->*Func_)(); + } + +#define FAIL_ASSERT(cond) \ + if (!(cond)) { \ + Data_.failed = true; \ } - void RunBasics() { + void RunBasics() { Y_ASSERT(TotalIds_ == 3); - if (Id_ < 2) { - TGuard<TMutex> guard(Data_.mutex); + if (Id_ < 2) { + TGuard<TMutex> guard(Data_.mutex); while (!AtomicGet(Data_.stopWaiting)) { bool res = Data_.condVar1.WaitT(Data_.mutex, TDuration::Seconds(1)); - FAIL_ASSERT(res == true); - } - } else { - usleep(100000); + FAIL_ASSERT(res == true); + } + } else { + usleep(100000); AtomicSet(Data_.stopWaiting, true); - - TGuard<TMutex> guard(Data_.mutex); - Data_.condVar1.Signal(); - Data_.condVar1.Signal(); - } - } - + + TGuard<TMutex> guard(Data_.mutex); + Data_.condVar1.Signal(); + Data_.condVar1.Signal(); + } + } + void RunBasicsWithPredicate() { Y_ASSERT(TotalIds_ == 3); @@ -98,14 +98,14 @@ class TCondVarTest: public TTestBase { } } - void RunSyncronize() { - for (size_t i = 0; i < 10; ++i) { - TGuard<TMutex> guard(Data_.mutex); + void RunSyncronize() { + for (size_t i = 0; i < 10; ++i) { + TGuard<TMutex> guard(Data_.mutex); AtomicIncrement(Data_.in); if (AtomicGet(Data_.in) == TotalIds_) { AtomicSet(Data_.out, 0); - Data_.condVar1.BroadCast(); - } else { + Data_.condVar1.BroadCast(); + } else { AtomicIncrement(Data_.waited); while (AtomicGet(Data_.in) < TotalIds_) { bool res = Data_.condVar1.WaitT(Data_.mutex, TDuration::Seconds(1)); @@ -116,14 +116,14 @@ class TCondVarTest: public TTestBase { AtomicIncrement(Data_.out); if (AtomicGet(Data_.out) == TotalIds_) { AtomicSet(Data_.in, 0); - Data_.condVar2.BroadCast(); - } else { + Data_.condVar2.BroadCast(); + } else { while (AtomicGet(Data_.out) < TotalIds_) { bool res = Data_.condVar2.WaitT(Data_.mutex, TDuration::Seconds(1)); - FAIL_ASSERT(res == true); + FAIL_ASSERT(res == true); } } - } + } FAIL_ASSERT(AtomicGet(Data_.waited) == (TotalIds_ - 1) * 10); } @@ -155,45 +155,45 @@ class TCondVarTest: public TTestBase { } } - FAIL_ASSERT(Data_.waited == (TotalIds_ - 1) * 10); - } + FAIL_ASSERT(Data_.waited == (TotalIds_ - 1) * 10); + } #undef FAIL_ASSERT - private: - PFunc Func_; - size_t Id_; + private: + PFunc Func_; + size_t Id_; TAtomicBase TotalIds_; - TSharedData& Data_; + TSharedData& Data_; }; -private: -#define RUN_CYCLE(what, count) \ - Q_.Start(count); \ - for (size_t i = 0; i < count; ++i) { \ - UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, i, count, Data_))); \ - } \ - Q_.Stop(); \ - bool b = Data_.failed; \ - Data_.failed = false; \ - UNIT_ASSERT(!b); - - inline void TestBasics() { - RUN_CYCLE(RunBasics, 3); - } +private: +#define RUN_CYCLE(what, count) \ + Q_.Start(count); \ + for (size_t i = 0; i < count; ++i) { \ + UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, i, count, Data_))); \ + } \ + Q_.Stop(); \ + bool b = Data_.failed; \ + Data_.failed = false; \ + UNIT_ASSERT(!b); + + inline void TestBasics() { + RUN_CYCLE(RunBasics, 3); + } inline void TestBasicsWithPredicate() { RUN_CYCLE(RunBasicsWithPredicate, 3); } - inline void TestSyncronize() { - RUN_CYCLE(RunSyncronize, 6); - } + inline void TestSyncronize() { + RUN_CYCLE(RunSyncronize, 6); + } inline void TestSyncronizeWithPredicate() { RUN_CYCLE(RunSyncronizeWithPredicate, 6); } -#undef RUN_CYCLE - TSharedData Data_; +#undef RUN_CYCLE + TSharedData Data_; TThreadPool Q_; }; diff --git a/util/system/context.cpp b/util/system/context.cpp index ad99309088..5b095be8a0 100644 --- a/util/system/context.cpp +++ b/util/system/context.cpp @@ -1,336 +1,336 @@ #include "compiler.h" -#include "defaults.h" -#include "event.h" -#include "thread.h" - -#include <cstdlib> //for abort() - -#if defined(_win_) - #include "winint.h" -#endif - -#if defined(_unix_) - #include <cxxabi.h> - - #if !defined(Y_CXA_EH_GLOBALS_COMPLETE) -namespace __cxxabiv1 { - struct __cxa_eh_globals { - void* caughtExceptions; - unsigned int uncaughtExceptions; - }; - - extern "C" __cxa_eh_globals* __cxa_get_globals(); -} - #endif -#endif - +#include "defaults.h" +#include "event.h" +#include "thread.h" + +#include <cstdlib> //for abort() + +#if defined(_win_) + #include "winint.h" +#endif + +#if defined(_unix_) + #include <cxxabi.h> + + #if !defined(Y_CXA_EH_GLOBALS_COMPLETE) +namespace __cxxabiv1 { + struct __cxa_eh_globals { + void* caughtExceptions; + unsigned int uncaughtExceptions; + }; + + extern "C" __cxa_eh_globals* __cxa_get_globals(); +} + #endif +#endif + #include <util/stream/output.h> #include <util/generic/yexception.h> - -#define FROM_CONTEXT_IMPL -#include "context.h" - -void ITrampoLine::DoRun() { -} - -void ITrampoLine::DoRunNaked() { - try { - DoRun(); - } catch (...) { + +#define FROM_CONTEXT_IMPL +#include "context.h" + +void ITrampoLine::DoRun() { +} + +void ITrampoLine::DoRunNaked() { + try { + DoRun(); + } catch (...) { Cerr << "Uncaught exception in coroutine: " << CurrentExceptionMessage() << "\n"; - } - - abort(); -} - -static inline void Run(void* arg) { - ((ITrampoLine*)arg)->DoRunNaked(); -} - -#if defined(USE_JUMP_CONT) -extern "C" void __mylongjmp(__myjmp_buf env, int val) __attribute__((__noreturn__)); -extern "C" int __mysetjmp(__myjmp_buf env) __attribute__((__returns_twice__)); - -namespace { + } + + abort(); +} + +static inline void Run(void* arg) { + ((ITrampoLine*)arg)->DoRunNaked(); +} + +#if defined(USE_JUMP_CONT) +extern "C" void __mylongjmp(__myjmp_buf env, int val) __attribute__((__noreturn__)); +extern "C" int __mysetjmp(__myjmp_buf env) __attribute__((__returns_twice__)); + +namespace { class TStackType { - public: + public: inline TStackType(TArrayRef<char> range) noexcept - #if defined(STACK_GROW_DOWN) + #if defined(STACK_GROW_DOWN) : Data_(range.data() + range.size()) - #else + #else : Data_(range.data() + STACK_ALIGN) - #endif - { - ReAlign(); - } - + #endif + { + ReAlign(); + } + inline ~TStackType() = default; - + inline void ReAlign() noexcept { - Data_ = AlignStackPtr(Data_); - } - - template <class T> + Data_ = AlignStackPtr(Data_); + } + + template <class T> inline void Push(T t) noexcept { - #if defined(STACK_GROW_DOWN) - Data_ -= sizeof(T); - *((T*)Data_) = t; - #else - *((T*)Data_) = t; - Data_ += sizeof(T); - #endif - } - + #if defined(STACK_GROW_DOWN) + Data_ -= sizeof(T); + *((T*)Data_) = t; + #else + *((T*)Data_) = t; + Data_ += sizeof(T); + #endif + } + inline char* StackPtr() noexcept { - return Data_; - } - - private: + return Data_; + } + + private: static inline char* AlignStackPtr(char* ptr) noexcept { - #if defined(STACK_GROW_DOWN) - return AlignDown(ptr, STACK_ALIGN); - #else - return AlignUp(ptr, STACK_ALIGN); - #endif - } - - private: - char* Data_; - }; - + #if defined(STACK_GROW_DOWN) + return AlignDown(ptr, STACK_ALIGN); + #else + return AlignUp(ptr, STACK_ALIGN); + #endif + } + + private: + char* Data_; + }; + static inline void*& JmpBufReg(__myjmp_buf& buf, size_t n) noexcept { - return (((void**)(void*)(buf))[n]); - } - + return (((void**)(void*)(buf))[n]); + } + static inline void*& JmpBufStackReg(__myjmp_buf& buf) noexcept { - return JmpBufReg(buf, STACK_CNT); - } - + return JmpBufReg(buf, STACK_CNT); + } + static inline void*& JmpBufProgrReg(__myjmp_buf& buf) noexcept { - return JmpBufReg(buf, PROGR_CNT); - } - + return JmpBufReg(buf, PROGR_CNT); + } + static inline void*& JmpBufFrameReg(__myjmp_buf& buf) noexcept { return JmpBufReg(buf, FRAME_CNT); } - #if defined(_x86_64_) + #if defined(_x86_64_) // not sure if Y_NO_SANITIZE is needed - Y_NO_SANITIZE("address") - Y_NO_SANITIZE("memory") extern "C" void ContextTrampoLine(void*, void*, void*, void*, void*, void*, // register arguments, no defined value - /* first argument passed through the stack */ void* t1, - /* second argument passed through the stack */ void* t2) { + Y_NO_SANITIZE("address") + Y_NO_SANITIZE("memory") extern "C" void ContextTrampoLine(void*, void*, void*, void*, void*, void*, // register arguments, no defined value + /* first argument passed through the stack */ void* t1, + /* second argument passed through the stack */ void* t2) { Y_ASSERT(t1 == t2); Run(t1); } - #else + #else Y_NO_SANITIZE("address") - Y_NO_SANITIZE("memory") static void ContextTrampoLine() { - void** argPtr = (void**)((char*)AlignUp(&argPtr + EXTRA_PUSH_ARGS, STACK_ALIGN) + STACK_ALIGN); + Y_NO_SANITIZE("memory") static void ContextTrampoLine() { + void** argPtr = (void**)((char*)AlignUp(&argPtr + EXTRA_PUSH_ARGS, STACK_ALIGN) + STACK_ALIGN); Y_ASSERT(*(argPtr - 1) == *(argPtr - 2)); - - Run(*(argPtr - 1)); - } - #endif -} - -TContMachineContext::TSan::TSan() noexcept - : TL(nullptr) -{ -} - -TContMachineContext::TSan::TSan(const TContClosure& c) noexcept + + Run(*(argPtr - 1)); + } + #endif +} + +TContMachineContext::TSan::TSan() noexcept + : TL(nullptr) +{ +} + +TContMachineContext::TSan::TSan(const TContClosure& c) noexcept : NSan::TFiberContext(c.Stack.data(), c.Stack.size(), c.ContName) - , TL(c.TrampoLine) -{ -} - + , TL(c.TrampoLine) +{ +} + void TContMachineContext::TSan::DoRunNaked() { - AfterSwitch(); + AfterSwitch(); TL->DoRunNaked(); - BeforeFinish(); -} - -TContMachineContext::TContMachineContext(const TContClosure& c) - #if defined(_asan_enabled_) || defined(_tsan_enabled_) - : San_(c) - #endif -{ + BeforeFinish(); +} + +TContMachineContext::TContMachineContext(const TContClosure& c) + #if defined(_asan_enabled_) || defined(_tsan_enabled_) + : San_(c) + #endif +{ TStackType stack(c.Stack); - - /* - * arg, and align data - */ - - #if defined(_asan_enabled_) - auto trampoline = &San_; - #else - auto trampoline = c.TrampoLine; - #endif - - #if defined(_x86_64_) + + /* + * arg, and align data + */ + + #if defined(_asan_enabled_) + auto trampoline = &San_; + #else + auto trampoline = c.TrampoLine; + #endif + + #if defined(_x86_64_) stack.ReAlign(); // push twice to preserve alignment by 16 stack.Push(trampoline); // second stack argument stack.Push(trampoline); // first stack argument stack.Push(nullptr); // fake return address - #else - stack.Push(trampoline); - stack.Push(trampoline); - stack.ReAlign(); - /* - * fake return address - */ - for (size_t i = 0; i < EXTRA_PUSH_ARGS; ++i) { + #else + stack.Push(trampoline); + stack.Push(trampoline); + stack.ReAlign(); + /* + * fake return address + */ + for (size_t i = 0; i < EXTRA_PUSH_ARGS; ++i) { stack.Push(nullptr); - } - #endif - - __mysetjmp(Buf_); - + } + #endif + + __mysetjmp(Buf_); + JmpBufProgrReg(Buf_) = reinterpret_cast<void*>(ContextTrampoLine); - JmpBufStackReg(Buf_) = stack.StackPtr(); + JmpBufStackReg(Buf_) = stack.StackPtr(); JmpBufFrameReg(Buf_) = nullptr; -} - +} + void TContMachineContext::SwitchTo(TContMachineContext* next) noexcept { if (Y_LIKELY(__mysetjmp(Buf_) == 0)) { - #if defined(_asan_enabled_) || defined(_tsan_enabled_) + #if defined(_asan_enabled_) || defined(_tsan_enabled_) next->San_.BeforeSwitch(&San_); - #endif - __mylongjmp(next->Buf_, 1); - } else { - #if defined(_asan_enabled_) - San_.AfterSwitch(); - #endif - } -} + #endif + __mylongjmp(next->Buf_, 1); + } else { + #if defined(_asan_enabled_) + San_.AfterSwitch(); + #endif + } +} #elif defined(_win_) && defined(_32_) void __stdcall ContextTrampoLine(void* arg) { Run(arg); } -#else -void ContextTrampoLine(void* arg) { - Run(arg); -} -#endif - -#if defined(USE_FIBER_CONT) +#else +void ContextTrampoLine(void* arg) { + Run(arg); +} +#endif + +#if defined(USE_FIBER_CONT) TContMachineContext::TContMachineContext() - : Fiber_(ConvertThreadToFiber(this)) - , MainFiber_(true) + : Fiber_(ConvertThreadToFiber(this)) + , MainFiber_(true) { Y_ENSURE(Fiber_, TStringBuf("fiber error")); } -TContMachineContext::TContMachineContext(const TContClosure& c) +TContMachineContext::TContMachineContext(const TContClosure& c) : Fiber_(CreateFiber(c.Stack.size(), (LPFIBER_START_ROUTINE)ContextTrampoLine, (LPVOID)c.TrampoLine)) - , MainFiber_(false) + , MainFiber_(false) { Y_ENSURE(Fiber_, TStringBuf("fiber error")); -} - +} + TContMachineContext::~TContMachineContext() { - if (MainFiber_) { - ConvertFiberToThread(); - } else { - DeleteFiber(Fiber_); - } -} - + if (MainFiber_) { + ConvertFiberToThread(); + } else { + DeleteFiber(Fiber_); + } +} + void TContMachineContext::SwitchTo(TContMachineContext* next) noexcept { - SwitchToFiber(next->Fiber_); -} -#endif - -#if defined(USE_GENERIC_CONT) - #include <pthread.h> - -struct TContMachineContext::TImpl { - inline TImpl() + SwitchToFiber(next->Fiber_); +} +#endif + +#if defined(USE_GENERIC_CONT) + #include <pthread.h> + +struct TContMachineContext::TImpl { + inline TImpl() : TL(nullptr) - , Finish(false) - { - } - - inline TImpl(const TContClosure& c) - : TL(c.TrampoLine) - , Finish(false) - { + , Finish(false) + { + } + + inline TImpl(const TContClosure& c) + : TL(c.TrampoLine) + , Finish(false) + { Thread.Reset(new TThread(TThread::TParams(Run, this).SetStackSize(c.Stack.size()).SetStackPointer((void*)c.Stack.data()))); - Thread->Start(); - } - + Thread->Start(); + } + inline ~TImpl() { - if (Thread) { - Finish = true; - Signal(); - Thread->Join(); - } - } - + if (Thread) { + Finish = true; + Signal(); + Thread->Join(); + } + } + inline void SwitchTo(TImpl* next) noexcept { - next->Signal(); - Wait(); - } - - static void* Run(void* self) { - ((TImpl*)self)->DoRun(); - - return nullptr; - } - - inline void DoRun() { - Wait(); - TL->DoRun(); - } - + next->Signal(); + Wait(); + } + + static void* Run(void* self) { + ((TImpl*)self)->DoRun(); + + return nullptr; + } + + inline void DoRun() { + Wait(); + TL->DoRun(); + } + inline void Signal() noexcept { - Event.Signal(); - } - + Event.Signal(); + } + inline void Wait() noexcept { - Event.Wait(); - - if (Finish) { - // TODO - need proper TThread::Exit(), have some troubles in win32 now - pthread_exit(0); - } - } - - TAutoEvent Event; - THolder<TThread> Thread; - ITrampoLine* TL; - bool Finish; -}; - -TContMachineContext::TContMachineContext() - : Impl_(new TImpl()) -{ -} - -TContMachineContext::TContMachineContext(const TContClosure& c) - : Impl_(new TImpl(c)) -{ -} - + Event.Wait(); + + if (Finish) { + // TODO - need proper TThread::Exit(), have some troubles in win32 now + pthread_exit(0); + } + } + + TAutoEvent Event; + THolder<TThread> Thread; + ITrampoLine* TL; + bool Finish; +}; + +TContMachineContext::TContMachineContext() + : Impl_(new TImpl()) +{ +} + +TContMachineContext::TContMachineContext(const TContClosure& c) + : Impl_(new TImpl(c)) +{ +} + TContMachineContext::~TContMachineContext() { -} - +} + void TContMachineContext::SwitchTo(TContMachineContext* next) noexcept { - Impl_->SwitchTo(next->Impl_.Get()); -} -#endif - -void TExceptionSafeContext::SwitchTo(TExceptionSafeContext* to) noexcept { -#if defined(_unix_) - static_assert(sizeof(__cxxabiv1::__cxa_eh_globals) == sizeof(Buf_), "size mismatch of __cxa_eh_globals structure"); - - auto* eh = __cxxabiv1::__cxa_get_globals(); - ::memcpy(Buf_, eh, sizeof(Buf_)); - ::memcpy(eh, to->Buf_, sizeof(Buf_)); -#endif - - TContMachineContext::SwitchTo(to); -} + Impl_->SwitchTo(next->Impl_.Get()); +} +#endif + +void TExceptionSafeContext::SwitchTo(TExceptionSafeContext* to) noexcept { +#if defined(_unix_) + static_assert(sizeof(__cxxabiv1::__cxa_eh_globals) == sizeof(Buf_), "size mismatch of __cxa_eh_globals structure"); + + auto* eh = __cxxabiv1::__cxa_get_globals(); + ::memcpy(Buf_, eh, sizeof(Buf_)); + ::memcpy(eh, to->Buf_, sizeof(Buf_)); +#endif + + TContMachineContext::SwitchTo(to); +} diff --git a/util/system/context.h b/util/system/context.h index d2a349bfc5..7f27c0dc22 100644 --- a/util/system/context.h +++ b/util/system/context.h @@ -1,181 +1,181 @@ #pragma once - -#include "align.h" -#include "defaults.h" + +#include "align.h" +#include "defaults.h" #include "compiler.h" -#include "sanitizers.h" - +#include "sanitizers.h" + #include <util/generic/array_ref.h> -#include <util/generic/utility.h> +#include <util/generic/utility.h> #include <util/generic/yexception.h> -#define STACK_ALIGN (8 * PLATFORM_DATA_ALIGN) - +#define STACK_ALIGN (8 * PLATFORM_DATA_ALIGN) + #if defined(_x86_64_) || defined(_i386_) || defined(_arm_) || defined(_ppc64_) - #define STACK_GROW_DOWN 1 -#else - #error todo -#endif - -/* - * switch method - */ + #define STACK_GROW_DOWN 1 +#else + #error todo +#endif + +/* + * switch method + */ #if defined(_bionic_) || defined(__IOS__) - #define USE_GENERIC_CONT -#elif defined(_cygwin_) - #define USE_UCONTEXT_CONT -#elif defined(_win_) - #define USE_FIBER_CONT + #define USE_GENERIC_CONT +#elif defined(_cygwin_) + #define USE_UCONTEXT_CONT +#elif defined(_win_) + #define USE_FIBER_CONT #elif (defined(_i386_) || defined(_x86_64_) || defined(_arm64_)) && !defined(_k1om_) - #define USE_JUMP_CONT -#else - #define USE_UCONTEXT_CONT -#endif - -#if defined(USE_JUMP_CONT) - #if defined(_arm64_) - #include "context_aarch64.h" - #else - #include "context_x86.h" - #endif -#endif - -#if defined(USE_UCONTEXT_CONT) - #include <ucontext.h> -#endif - -struct ITrampoLine { + #define USE_JUMP_CONT +#else + #define USE_UCONTEXT_CONT +#endif + +#if defined(USE_JUMP_CONT) + #if defined(_arm64_) + #include "context_aarch64.h" + #else + #include "context_x86.h" + #endif +#endif + +#if defined(USE_UCONTEXT_CONT) + #include <ucontext.h> +#endif + +struct ITrampoLine { virtual ~ITrampoLine() = default; - - virtual void DoRun(); - virtual void DoRunNaked(); -}; - -struct TContClosure { - ITrampoLine* TrampoLine; + + virtual void DoRun(); + virtual void DoRunNaked(); +}; + +struct TContClosure { + ITrampoLine* TrampoLine; TArrayRef<char> Stack; const char* ContName = nullptr; -}; - -#if defined(USE_UCONTEXT_CONT) -class TContMachineContext { - typedef void (*ucontext_func_t)(void); - -public: - inline TContMachineContext() { - getcontext(&Ctx_); - } - - inline TContMachineContext(const TContClosure& c) { - getcontext(&Ctx_); - - Ctx_.uc_link = 0; +}; + +#if defined(USE_UCONTEXT_CONT) +class TContMachineContext { + typedef void (*ucontext_func_t)(void); + +public: + inline TContMachineContext() { + getcontext(&Ctx_); + } + + inline TContMachineContext(const TContClosure& c) { + getcontext(&Ctx_); + + Ctx_.uc_link = 0; Ctx_.uc_stack.ss_sp = (void*)c.Stack.data(); Ctx_.uc_stack.ss_size = c.Stack.size(); - Ctx_.uc_stack.ss_flags = 0; - - extern void ContextTrampoLine(void* arg); - makecontext(&Ctx_, (ucontext_func_t)ContextTrampoLine, 1, c.TrampoLine); - } - + Ctx_.uc_stack.ss_flags = 0; + + extern void ContextTrampoLine(void* arg); + makecontext(&Ctx_, (ucontext_func_t)ContextTrampoLine, 1, c.TrampoLine); + } + inline ~TContMachineContext() { - } - + } + inline void SwitchTo(TContMachineContext* next) noexcept { - swapcontext(&Ctx_, &next->Ctx_); - } - -private: - ucontext_t Ctx_; -}; -#endif - -#if defined(USE_GENERIC_CONT) -class TContMachineContext { - struct TImpl; - -public: - TContMachineContext(); - TContMachineContext(const TContClosure& c); - + swapcontext(&Ctx_, &next->Ctx_); + } + +private: + ucontext_t Ctx_; +}; +#endif + +#if defined(USE_GENERIC_CONT) +class TContMachineContext { + struct TImpl; + +public: + TContMachineContext(); + TContMachineContext(const TContClosure& c); + ~TContMachineContext(); - + void SwitchTo(TContMachineContext* next) noexcept; - -private: - THolder<TImpl> Impl_; -}; -#endif - -#if defined(USE_FIBER_CONT) -class TContMachineContext { -public: - TContMachineContext(); - TContMachineContext(const TContClosure& c); + +private: + THolder<TImpl> Impl_; +}; +#endif + +#if defined(USE_FIBER_CONT) +class TContMachineContext { +public: + TContMachineContext(); + TContMachineContext(const TContClosure& c); ~TContMachineContext(); - + void SwitchTo(TContMachineContext* next) noexcept; - -private: - void* Fiber_; - bool MainFiber_; -}; -#endif - -#if defined(USE_JUMP_CONT) -class TContMachineContext { -public: - inline TContMachineContext() { - Zero(Buf_); - } - - TContMachineContext(const TContClosure& c); - + +private: + void* Fiber_; + bool MainFiber_; +}; +#endif + +#if defined(USE_JUMP_CONT) +class TContMachineContext { +public: + inline TContMachineContext() { + Zero(Buf_); + } + + TContMachineContext(const TContClosure& c); + inline ~TContMachineContext() = default; - + void SwitchTo(TContMachineContext* next) noexcept; - -private: - __myjmp_buf Buf_; - - struct TSan: public ITrampoLine, public ::NSan::TFiberContext { - TSan() noexcept; - TSan(const TContClosure& c) noexcept; - + +private: + __myjmp_buf Buf_; + + struct TSan: public ITrampoLine, public ::NSan::TFiberContext { + TSan() noexcept; + TSan(const TContClosure& c) noexcept; + void DoRunNaked() override; - - ITrampoLine* TL; - }; - - #if defined(_asan_enabled_) || defined(_tsan_enabled_) - TSan San_; - #endif -}; -#endif - + + ITrampoLine* TL; + }; + + #if defined(_asan_enabled_) || defined(_tsan_enabled_) + TSan San_; + #endif +}; +#endif + static inline size_t MachineContextSize() noexcept { - return sizeof(TContMachineContext); -} - -/* - * be polite - */ -#if !defined(FROM_CONTEXT_IMPL) - #undef USE_JUMP_CONT - #undef USE_FIBER_CONT - #undef USE_GENERIC_CONT - #undef USE_UCONTEXT_CONT - #undef PROGR_CNT - #undef STACK_CNT - #undef EXTRA_PUSH_ARGS -#endif - -struct TExceptionSafeContext: public TContMachineContext { - using TContMachineContext::TContMachineContext; - - void SwitchTo(TExceptionSafeContext* to) noexcept; - -#if defined(_unix_) + return sizeof(TContMachineContext); +} + +/* + * be polite + */ +#if !defined(FROM_CONTEXT_IMPL) + #undef USE_JUMP_CONT + #undef USE_FIBER_CONT + #undef USE_GENERIC_CONT + #undef USE_UCONTEXT_CONT + #undef PROGR_CNT + #undef STACK_CNT + #undef EXTRA_PUSH_ARGS +#endif + +struct TExceptionSafeContext: public TContMachineContext { + using TContMachineContext::TContMachineContext; + + void SwitchTo(TExceptionSafeContext* to) noexcept; + +#if defined(_unix_) void* Buf_[2] = {nullptr, nullptr}; -#endif -}; +#endif +}; diff --git a/util/system/context_aarch64.S b/util/system/context_aarch64.S index 0b2ef4e4a6..c3189e4732 100644 --- a/util/system/context_aarch64.S +++ b/util/system/context_aarch64.S @@ -1,52 +1,52 @@ -.p2align 2 +.p2align 2 #if !(defined __darwin__) && !(defined __arm64__) -.global __mysetjmp -.type __mysetjmp,@function +.global __mysetjmp +.type __mysetjmp,@function __mysetjmp: #else .global ___mysetjmp ___mysetjmp: #endif - // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers - stp x19, x20, [x0,#0] - stp x21, x22, [x0,#16] - stp x23, x24, [x0,#32] - stp x25, x26, [x0,#48] - stp x27, x28, [x0,#64] - stp x29, x30, [x0,#80] - mov x2, sp - str x2, [x0,#104] - stp d8, d9, [x0,#112] - stp d10, d11, [x0,#128] - stp d12, d13, [x0,#144] - stp d14, d15, [x0,#160] - mov x0, #0 - ret - -.p2align 2 + // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0,#104] + stp d8, d9, [x0,#112] + stp d10, d11, [x0,#128] + stp d12, d13, [x0,#144] + stp d14, d15, [x0,#160] + mov x0, #0 + ret + +.p2align 2 #if !(defined __darwin__) && !(defined __arm64__) -.global __mylongjmp -.type __mylongjump,@function +.global __mylongjmp +.type __mylongjump,@function __mylongjmp: #else .global ___mylongjmp ___mylongjmp: #endif - // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers - ldp x19, x20, [x0,#0] - ldp x21, x22, [x0,#16] - ldp x23, x24, [x0,#32] - ldp x25, x26, [x0,#48] - ldp x27, x28, [x0,#64] - ldp x29, x30, [x0,#80] - ldr x2, [x0,#104] - mov sp, x2 - ldp d8 , d9, [x0,#112] - ldp d10, d11, [x0,#128] - ldp d12, d13, [x0,#144] - ldp d14, d15, [x0,#160] - - mov x0, x1 - cbnz x1, 1f - mov x0, #1 -1: br x30 + // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#104] + mov sp, x2 + ldp d8 , d9, [x0,#112] + ldp d10, d11, [x0,#128] + ldp d12, d13, [x0,#144] + ldp d14, d15, [x0,#160] + + mov x0, x1 + cbnz x1, 1f + mov x0, #1 +1: br x30 diff --git a/util/system/context_aarch64.h b/util/system/context_aarch64.h index 589521d8ae..0bcb6241e2 100644 --- a/util/system/context_aarch64.h +++ b/util/system/context_aarch64.h @@ -1,8 +1,8 @@ -#pragma once - -typedef unsigned long __myjmp_buf[22]; - +#pragma once + +typedef unsigned long __myjmp_buf[22]; + #define FRAME_CNT 10 -#define PROGR_CNT 11 -#define STACK_CNT 13 -#define EXTRA_PUSH_ARGS 2 +#define PROGR_CNT 11 +#define STACK_CNT 13 +#define EXTRA_PUSH_ARGS 2 diff --git a/util/system/context_i686.asm b/util/system/context_i686.asm index 11f8cecc8e..d5691bfbc5 100644 --- a/util/system/context_i686.asm +++ b/util/system/context_i686.asm @@ -12,13 +12,13 @@ %define LINKAGE 4 %define PCOFF 0 %define PTR_SIZE 4 - + %define PARMS LINKAGE %define JMPBUF PARMS %define JBUF PARMS %define VAL JBUF + PTR_SIZE -EXPORT __mylongjmp +EXPORT __mylongjmp mov ecx, [esp + JBUF] mov eax, [esp + VAL] mov edx, [ecx + MJB_PC*4] @@ -29,7 +29,7 @@ EXPORT __mylongjmp mov esp, [ecx + MJB_SP*4] jmp edx -EXPORT __mysetjmp +EXPORT __mysetjmp mov eax, [esp + JMPBUF] mov [eax + MJB_BX*4], ebx mov [eax + MJB_SI*4], esi diff --git a/util/system/context_i686.h b/util/system/context_i686.h index 1abfd5dada..0f586896fe 100644 --- a/util/system/context_i686.h +++ b/util/system/context_i686.h @@ -1,9 +1,9 @@ #pragma once - + #define MJB_BP 3 -#define MJB_SP 4 -#define MJB_PC 5 +#define MJB_SP 4 +#define MJB_PC 5 #define MJB_RBP MJB_BP -#define MJB_RSP MJB_SP - -typedef int __myjmp_buf[6]; +#define MJB_RSP MJB_SP + +typedef int __myjmp_buf[6]; diff --git a/util/system/context_ut.cpp b/util/system/context_ut.cpp index 45cb0249f7..8c0eb2cbaa 100644 --- a/util/system/context_ut.cpp +++ b/util/system/context_ut.cpp @@ -1,71 +1,71 @@ -#include "context.h" - +#include "context.h" + #include <library/cpp/testing/unittest/registar.h> - -#include <util/generic/deque.h> + +#include <util/generic/deque.h> #include <util/generic/yexception.h> - + Y_UNIT_TEST_SUITE(TestContext) { - template <class F> - static TContClosure Wrap(F& f) { - struct TW: public ITrampoLine { - inline TW(F* ff) noexcept - : F_(ff) - { - } - - void DoRun() override { - (*F_)(); - } - - F* F_; - char Buf[1000000]; - }; - + template <class F> + static TContClosure Wrap(F& f) { + struct TW: public ITrampoLine { + inline TW(F* ff) noexcept + : F_(ff) + { + } + + void DoRun() override { + (*F_)(); + } + + F* F_; + char Buf[1000000]; + }; + static TDeque<TW> w; - - auto& tw = w.emplace_back(&f); - + + auto& tw = w.emplace_back(&f); + return {&tw, TArrayRef(tw.Buf, sizeof(tw.Buf))}; - } - + } + Y_UNIT_TEST(TestExceptionSafety) { - TExceptionSafeContext main; - TExceptionSafeContext* volatile nextPtr = nullptr; - + TExceptionSafeContext main; + TExceptionSafeContext* volatile nextPtr = nullptr; + bool hasUncaught = true; - + auto func = [&]() { hasUncaught = UncaughtException(); - nextPtr->SwitchTo(&main); - }; - - auto closure = Wrap(func); - - TExceptionSafeContext next(closure); - - nextPtr = &next; - - struct THelper { - inline ~THelper() { - M->SwitchTo(N); - } - - TExceptionSafeContext* M; - TExceptionSafeContext* N; - }; - - bool throwed = false; - - try { - THelper helper{&main, &next}; - - throw 1; - } catch (...) { - throwed = true; - } - - UNIT_ASSERT(throwed); + nextPtr->SwitchTo(&main); + }; + + auto closure = Wrap(func); + + TExceptionSafeContext next(closure); + + nextPtr = &next; + + struct THelper { + inline ~THelper() { + M->SwitchTo(N); + } + + TExceptionSafeContext* M; + TExceptionSafeContext* N; + }; + + bool throwed = false; + + try { + THelper helper{&main, &next}; + + throw 1; + } catch (...) { + throwed = true; + } + + UNIT_ASSERT(throwed); UNIT_ASSERT(!hasUncaught); - } -} + } +} diff --git a/util/system/context_x86.asm b/util/system/context_x86.asm index e825d5d087..079fc21269 100644 --- a/util/system/context_x86.asm +++ b/util/system/context_x86.asm @@ -1,15 +1,15 @@ -%macro EXPORT 1 - %ifdef DARWIN - global _%1 - _%1: - %else - global %1 - %1: - %endif -%endmacro - -%ifdef _x86_64_ - %include "context_x86_64.asm" -%else - %include "context_i686.asm" -%endif +%macro EXPORT 1 + %ifdef DARWIN + global _%1 + _%1: + %else + global %1 + %1: + %endif +%endmacro + +%ifdef _x86_64_ + %include "context_x86_64.asm" +%else + %include "context_i686.asm" +%endif diff --git a/util/system/context_x86.h b/util/system/context_x86.h index 6ea066ff88..d67817061f 100644 --- a/util/system/context_x86.h +++ b/util/system/context_x86.h @@ -1,12 +1,12 @@ #pragma once - -#if defined(_x86_64_) - #include "context_x86_64.h" -#elif defined(_i386_) - #include "context_i686.h" -#endif - -#define PROGR_CNT MJB_PC -#define STACK_CNT MJB_RSP + +#if defined(_x86_64_) + #include "context_x86_64.h" +#elif defined(_i386_) + #include "context_i686.h" +#endif + +#define PROGR_CNT MJB_PC +#define STACK_CNT MJB_RSP #define FRAME_CNT MJB_RBP -#define EXTRA_PUSH_ARGS 1 +#define EXTRA_PUSH_ARGS 1 diff --git a/util/system/context_x86_64.asm b/util/system/context_x86_64.asm index 8bcc01e4fc..10ed1f6db4 100644 --- a/util/system/context_x86_64.asm +++ b/util/system/context_x86_64.asm @@ -1,5 +1,5 @@ - [bits 64] - + [bits 64] + %define MJB_RBX 0 %define MJB_RBP 1 %define MJB_R12 2 @@ -8,33 +8,33 @@ %define MJB_R15 5 %define MJB_RSP 6 %define MJB_PC 7 - %define MJB_SIZE (8*8) - -EXPORT __mylongjmp - mov rbx, [rdi + MJB_RBX * 8] - mov rbp, [rdi + MJB_RBP * 8] - mov r12, [rdi + MJB_R12 * 8] - mov r13, [rdi + MJB_R13 * 8] - mov r14, [rdi + MJB_R14 * 8] - mov r15, [rdi + MJB_R15 * 8] - test esi, esi - mov eax, 1 - cmove esi, eax - mov eax, esi - mov rdx, [rdi + MJB_PC * 8] - mov rsp, [rdi + MJB_RSP * 8] - jmp rdx - -EXPORT __mysetjmp - mov [rdi + MJB_RBX * 8], rbx - mov [rdi + MJB_RBP * 8], rbp - mov [rdi + MJB_R12 * 8], r12 - mov [rdi + MJB_R13 * 8], r13 - mov [rdi + MJB_R14 * 8], r14 - mov [rdi + MJB_R15 * 8], r15 - lea rdx, [rsp + 8] - mov [rdi + MJB_RSP * 8], rdx - mov rax, [rsp] - mov [rdi + MJB_PC * 8], rax - mov eax, 0 - ret + %define MJB_SIZE (8*8) + +EXPORT __mylongjmp + mov rbx, [rdi + MJB_RBX * 8] + mov rbp, [rdi + MJB_RBP * 8] + mov r12, [rdi + MJB_R12 * 8] + mov r13, [rdi + MJB_R13 * 8] + mov r14, [rdi + MJB_R14 * 8] + mov r15, [rdi + MJB_R15 * 8] + test esi, esi + mov eax, 1 + cmove esi, eax + mov eax, esi + mov rdx, [rdi + MJB_PC * 8] + mov rsp, [rdi + MJB_RSP * 8] + jmp rdx + +EXPORT __mysetjmp + mov [rdi + MJB_RBX * 8], rbx + mov [rdi + MJB_RBP * 8], rbp + mov [rdi + MJB_R12 * 8], r12 + mov [rdi + MJB_R13 * 8], r13 + mov [rdi + MJB_R14 * 8], r14 + mov [rdi + MJB_R15 * 8], r15 + lea rdx, [rsp + 8] + mov [rdi + MJB_RSP * 8], rdx + mov rax, [rsp] + mov [rdi + MJB_PC * 8], rax + mov eax, 0 + ret diff --git a/util/system/context_x86_64.h b/util/system/context_x86_64.h index 94e4f37eb3..302ccbae64 100644 --- a/util/system/context_x86_64.h +++ b/util/system/context_x86_64.h @@ -1,7 +1,7 @@ #pragma once - + #define MJB_RBP 1 -#define MJB_RSP 6 -#define MJB_PC 7 - -typedef long int __myjmp_buf[8]; +#define MJB_RSP 6 +#define MJB_PC 7 + +typedef long int __myjmp_buf[8]; diff --git a/util/system/cpu_id.cpp b/util/system/cpu_id.cpp index 598c71f4d9..a13ebbc018 100644 --- a/util/system/cpu_id.cpp +++ b/util/system/cpu_id.cpp @@ -1,38 +1,38 @@ -#include "cpu_id.h" -#include "types.h" -#include "platform.h" - -#include <util/generic/singleton.h> +#include "cpu_id.h" +#include "types.h" +#include "platform.h" +#include <util/generic/singleton.h> + #if defined(_win_) - #include <intrin.h> - #include <immintrin.h> + #include <intrin.h> + #include <immintrin.h> #elif defined(_x86_) - #include <cpuid.h> + #include <cpuid.h> #endif -#include <string.h> +#include <string.h> #if defined(_x86_) && !defined(_win_) static ui64 _xgetbv(ui32 xcr) { ui32 eax; ui32 edx; - __asm__ volatile( - "xgetbv" - : "=a"(eax), "=d"(edx) - : "c"(xcr)); + __asm__ volatile( + "xgetbv" + : "=a"(eax), "=d"(edx) + : "c"(xcr)); return (static_cast<ui64>(edx) << 32) | eax; } #endif bool NX86::CpuId(ui32 op, ui32 subOp, ui32* res) noexcept { #if defined(_x86_) - #if defined(_MSC_VER) + #if defined(_MSC_VER) static_assert(sizeof(int) == sizeof(ui32), "ups, something wrong here"); __cpuidex((int*)res, op, subOp); - #else + #else __cpuid_count(op, subOp, res[0], res[1], res[2], res[3]); - #endif + #endif return true; #else (void)op; @@ -45,77 +45,77 @@ bool NX86::CpuId(ui32 op, ui32 subOp, ui32* res) noexcept { } bool NX86::CpuId(ui32 op, ui32* res) noexcept { -#if defined(_x86_) - #if defined(_MSC_VER) - static_assert(sizeof(int) == sizeof(ui32), "ups, something wrong here"); - __cpuid((int*)res, op); - #else +#if defined(_x86_) + #if defined(_MSC_VER) + static_assert(sizeof(int) == sizeof(ui32), "ups, something wrong here"); + __cpuid((int*)res, op); + #else __cpuid(op, res[0], res[1], res[2], res[3]); - #endif - return true; -#else - (void)op; - - memset(res, 0, 4 * sizeof(ui32)); - - return false; -#endif -} - -namespace { - union TX86CpuInfo { - ui32 Info[4]; - - struct { - ui32 EAX; - ui32 EBX; - ui32 ECX; - ui32 EDX; - }; - + #endif + return true; +#else + (void)op; + + memset(res, 0, 4 * sizeof(ui32)); + + return false; +#endif +} + +namespace { + union TX86CpuInfo { + ui32 Info[4]; + + struct { + ui32 EAX; + ui32 EBX; + ui32 ECX; + ui32 EDX; + }; + inline TX86CpuInfo(ui32 op) noexcept { - NX86::CpuId(op, Info); - } + NX86::CpuId(op, Info); + } inline TX86CpuInfo(ui32 op, ui32 subOp) noexcept { NX86::CpuId(op, subOp, Info); } }; - static_assert(sizeof(TX86CpuInfo) == 16, "please, fix me"); -} - -// https://en.wikipedia.org/wiki/CPUID -bool NX86::HaveRDTSCP() noexcept { - return (TX86CpuInfo(0x80000001).EDX >> 27) & 1u; + static_assert(sizeof(TX86CpuInfo) == 16, "please, fix me"); } +// https://en.wikipedia.org/wiki/CPUID +bool NX86::HaveRDTSCP() noexcept { + return (TX86CpuInfo(0x80000001).EDX >> 27) & 1u; +} + bool NX86::HaveSSE() noexcept { - return (TX86CpuInfo(0x1).EDX >> 25) & 1u; -} - + return (TX86CpuInfo(0x1).EDX >> 25) & 1u; +} + bool NX86::HaveSSE2() noexcept { - return (TX86CpuInfo(0x1).EDX >> 26) & 1u; + return (TX86CpuInfo(0x1).EDX >> 26) & 1u; } bool NX86::HaveSSE3() noexcept { - return TX86CpuInfo(0x1).ECX & 1u; -} - + return TX86CpuInfo(0x1).ECX & 1u; +} + bool NX86::HavePCLMUL() noexcept { return (TX86CpuInfo(0x1).ECX >> 1) & 1u; } bool NX86::HaveSSSE3() noexcept { - return (TX86CpuInfo(0x1).ECX >> 9) & 1u; -} - + return (TX86CpuInfo(0x1).ECX >> 9) & 1u; +} + bool NX86::HaveSSE41() noexcept { - return (TX86CpuInfo(0x1).ECX >> 19) & 1u; -} - + return (TX86CpuInfo(0x1).ECX >> 19) & 1u; +} + bool NX86::HaveSSE42() noexcept { - return (TX86CpuInfo(0x1).ECX >> 20) & 1u; + return (TX86CpuInfo(0x1).ECX >> 20) & 1u; } bool NX86::HaveF16C() noexcept { @@ -123,13 +123,13 @@ bool NX86::HaveF16C() noexcept { } bool NX86::HavePOPCNT() noexcept { - return (TX86CpuInfo(0x1).ECX >> 23) & 1u; -} - + return (TX86CpuInfo(0x1).ECX >> 23) & 1u; +} + bool NX86::HaveAES() noexcept { - return (TX86CpuInfo(0x1).ECX >> 25) & 1u; -} - + return (TX86CpuInfo(0x1).ECX >> 25) & 1u; +} + bool NX86::HaveXSAVE() noexcept { return (TX86CpuInfo(0x1).ECX >> 26) & 1u; } @@ -142,14 +142,14 @@ bool NX86::HaveAVX() noexcept { #if defined(_x86_) // http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf // https://bugs.chromium.org/p/chromium/issues/detail?id=375968 - return HaveOSXSAVE() // implies HaveXSAVE() - && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS - && ((TX86CpuInfo(0x1).ECX >> 28) & 1u); // AVX bit + return HaveOSXSAVE() // implies HaveXSAVE() + && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS + && ((TX86CpuInfo(0x1).ECX >> 28) & 1u); // AVX bit #else return false; #endif -} - +} + bool NX86::HaveFMA() noexcept { return HaveAVX() && ((TX86CpuInfo(0x1).ECX >> 12) & 1u); } @@ -169,11 +169,11 @@ bool NX86::HaveBMI2() noexcept { bool NX86::HaveAVX512F() noexcept { #if defined(_x86_) // https://software.intel.com/en-us/articles/how-to-detect-knl-instruction-support - return HaveOSXSAVE() // implies HaveXSAVE() - && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS - && ((_xgetbv(0) >> 5) & 7u) == 7u // ZMM state is enabled by OS - && TX86CpuInfo(0x0).EAX >= 0x7 // leaf 7 is present - && ((TX86CpuInfo(0x7).EBX >> 16) & 1u); // AVX512F bit + return HaveOSXSAVE() // implies HaveXSAVE() + && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS + && ((_xgetbv(0) >> 5) & 7u) == 7u // ZMM state is enabled by OS + && TX86CpuInfo(0x0).EAX >= 0x7 // leaf 7 is present + && ((TX86CpuInfo(0x7).EBX >> 16) & 1u); // AVX512F bit #else return false; #endif @@ -241,23 +241,23 @@ bool NX86::HaveAVX512VBMI() noexcept { bool NX86::HaveRDRAND() noexcept { return TX86CpuInfo(0x0).EAX >= 0x7 && ((TX86CpuInfo(0x1).ECX >> 30) & 1u); -} - +} + const char* CpuBrand(ui32* store) noexcept { - memset(store, 0, 12 * sizeof(*store)); - -#if defined(_x86_) - NX86::CpuId(0x80000002, store); - NX86::CpuId(0x80000003, store + 4); - NX86::CpuId(0x80000004, store + 8); -#endif - - return (const char*)store; -} - -#define Y_DEF_NAME(X) \ - bool NX86::CachedHave##X() noexcept { \ - return SingletonWithPriority<TFlagsCache, 0>()->Have##X##_; \ - } + memset(store, 0, 12 * sizeof(*store)); + +#if defined(_x86_) + NX86::CpuId(0x80000002, store); + NX86::CpuId(0x80000003, store + 4); + NX86::CpuId(0x80000004, store + 8); +#endif + + return (const char*)store; +} + +#define Y_DEF_NAME(X) \ + bool NX86::CachedHave##X() noexcept { \ + return SingletonWithPriority<TFlagsCache, 0>()->Have##X##_; \ + } Y_CPU_ID_ENUMERATE_OUTLINED_CACHED_DEFINE(Y_DEF_NAME) -#undef Y_DEF_NAME +#undef Y_DEF_NAME diff --git a/util/system/cpu_id.h b/util/system/cpu_id.h index 3c49e728a7..75637d68b7 100644 --- a/util/system/cpu_id.h +++ b/util/system/cpu_id.h @@ -1,154 +1,154 @@ -#pragma once - -#include "types.h" +#pragma once + +#include "types.h" #include "compiler.h" #include <util/generic/singleton.h> - -#define Y_CPU_ID_ENUMERATE(F) \ - F(SSE) \ - F(SSE2) \ - F(SSE3) \ - F(SSSE3) \ - F(SSE41) \ - F(SSE42) \ + +#define Y_CPU_ID_ENUMERATE(F) \ + F(SSE) \ + F(SSE2) \ + F(SSE3) \ + F(SSSE3) \ + F(SSE41) \ + F(SSE42) \ F(F16C) \ - F(POPCNT) \ - F(BMI1) \ + F(POPCNT) \ + F(BMI1) \ F(BMI2) \ F(PCLMUL) \ - F(AES) \ - F(AVX) \ - F(FMA) \ - F(AVX2) \ - F(AVX512F) \ - F(AVX512DQ) \ - F(AVX512IFMA) \ - F(AVX512PF) \ - F(AVX512ER) \ - F(AVX512CD) \ - F(AVX512BW) \ - F(AVX512VL) \ - F(AVX512VBMI) \ - F(PREFETCHWT1) \ - F(SHA) \ - F(ADX) \ - F(RDRAND) \ - F(RDSEED) \ - F(PCOMMIT) \ - F(RDTSCP) \ - F(CLFLUSHOPT) \ - F(CLWB) \ - F(XSAVE) \ - F(OSXSAVE) - + F(AES) \ + F(AVX) \ + F(FMA) \ + F(AVX2) \ + F(AVX512F) \ + F(AVX512DQ) \ + F(AVX512IFMA) \ + F(AVX512PF) \ + F(AVX512ER) \ + F(AVX512CD) \ + F(AVX512BW) \ + F(AVX512VL) \ + F(AVX512VBMI) \ + F(PREFETCHWT1) \ + F(SHA) \ + F(ADX) \ + F(RDRAND) \ + F(RDSEED) \ + F(PCOMMIT) \ + F(RDTSCP) \ + F(CLFLUSHOPT) \ + F(CLWB) \ + F(XSAVE) \ + F(OSXSAVE) + #define Y_CPU_ID_ENUMERATE_OUTLINED_CACHED_DEFINE(F) \ - F(F16C) \ - F(BMI1) \ - F(BMI2) \ - F(PCLMUL) \ - F(AES) \ - F(AVX) \ - F(FMA) \ - F(AVX2) \ - F(AVX512F) \ - F(AVX512DQ) \ - F(AVX512IFMA) \ - F(AVX512PF) \ - F(AVX512ER) \ - F(AVX512CD) \ - F(AVX512BW) \ - F(AVX512VL) \ - F(AVX512VBMI) \ - F(PREFETCHWT1) \ - F(SHA) \ - F(ADX) \ - F(RDRAND) \ - F(RDSEED) \ - F(PCOMMIT) \ - F(RDTSCP) \ - F(CLFLUSHOPT) \ - F(CLWB) \ - F(XSAVE) \ + F(F16C) \ + F(BMI1) \ + F(BMI2) \ + F(PCLMUL) \ + F(AES) \ + F(AVX) \ + F(FMA) \ + F(AVX2) \ + F(AVX512F) \ + F(AVX512DQ) \ + F(AVX512IFMA) \ + F(AVX512PF) \ + F(AVX512ER) \ + F(AVX512CD) \ + F(AVX512BW) \ + F(AVX512VL) \ + F(AVX512VBMI) \ + F(PREFETCHWT1) \ + F(SHA) \ + F(ADX) \ + F(RDRAND) \ + F(RDSEED) \ + F(PCOMMIT) \ + F(RDTSCP) \ + F(CLFLUSHOPT) \ + F(CLWB) \ + F(XSAVE) \ F(OSXSAVE) -namespace NX86 { - /** - * returns false on non-x86 platforms - */ +namespace NX86 { + /** + * returns false on non-x86 platforms + */ bool CpuId(ui32 op, ui32 res[4]) noexcept; bool CpuId(ui32 op, ui32 subOp, ui32 res[4]) noexcept; #define Y_DEF_NAME(X) Y_CONST_FUNCTION bool Have##X() noexcept; - Y_CPU_ID_ENUMERATE(Y_DEF_NAME) -#undef Y_DEF_NAME + Y_CPU_ID_ENUMERATE(Y_DEF_NAME) +#undef Y_DEF_NAME #define Y_DEF_NAME(X) Y_CONST_FUNCTION bool CachedHave##X() noexcept; Y_CPU_ID_ENUMERATE_OUTLINED_CACHED_DEFINE(Y_DEF_NAME) #undef Y_DEF_NAME - struct TFlagsCache { + struct TFlagsCache { #define Y_DEF_NAME(X) const bool Have##X##_ = NX86::Have##X(); - Y_CPU_ID_ENUMERATE(Y_DEF_NAME) -#undef Y_DEF_NAME - }; + Y_CPU_ID_ENUMERATE(Y_DEF_NAME) +#undef Y_DEF_NAME + }; #define Y_LOOKUP_CPU_ID_IMPL(X) return SingletonWithPriority<TFlagsCache, 0>()->Have##X##_; - inline bool CachedHaveSSE() noexcept { + inline bool CachedHaveSSE() noexcept { #ifdef _sse_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSE) + Y_LOOKUP_CPU_ID_IMPL(SSE) #endif - } - - inline bool CachedHaveSSE2() noexcept { + } + + inline bool CachedHaveSSE2() noexcept { #ifdef _sse2_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSE2) + Y_LOOKUP_CPU_ID_IMPL(SSE2) #endif - } + } - inline bool CachedHaveSSE3() noexcept { + inline bool CachedHaveSSE3() noexcept { #ifdef _sse3_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSE3) + Y_LOOKUP_CPU_ID_IMPL(SSE3) #endif - } + } - inline bool CachedHaveSSSE3() noexcept { + inline bool CachedHaveSSSE3() noexcept { #ifdef _ssse3_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSSE3) + Y_LOOKUP_CPU_ID_IMPL(SSSE3) #endif - } + } - inline bool CachedHaveSSE41() noexcept { + inline bool CachedHaveSSE41() noexcept { #ifdef _sse4_1_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSE41) + Y_LOOKUP_CPU_ID_IMPL(SSE41) #endif - } + } - inline bool CachedHaveSSE42() noexcept { + inline bool CachedHaveSSE42() noexcept { #ifdef _sse4_2_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(SSE42) + Y_LOOKUP_CPU_ID_IMPL(SSE42) #endif - } + } - inline bool CachedHavePOPCNT() noexcept { + inline bool CachedHavePOPCNT() noexcept { #ifdef _popcnt_ - return true; + return true; #else - Y_LOOKUP_CPU_ID_IMPL(POPCNT) + Y_LOOKUP_CPU_ID_IMPL(POPCNT) #endif - } + } #undef Y_LOOKUP_CPU_ID_IMPL diff --git a/util/system/cpu_id_ut.cpp b/util/system/cpu_id_ut.cpp index 68f1f8aac7..150c72330d 100644 --- a/util/system/cpu_id_ut.cpp +++ b/util/system/cpu_id_ut.cpp @@ -1,9 +1,9 @@ -#include "cpu_id.h" - +#include "cpu_id.h" + #include "platform.h" #include <library/cpp/testing/unittest/registar.h> - + // There are no tests yet for instructions that use 512-bit wide registers because they are not // supported by some compilers yet. // Relevant review in LLVM https://reviews.llvm.org/D16757, we should wait untill it will be in our @@ -46,92 +46,92 @@ static void ExecutePCOMMITInstruction(); static void ExecuteCLFLUSHOPTInstruction(); static void ExecuteCLWBInstruction(); -static void ExecuteFMAInstruction() { -} - -static void ExecuteRDTSCPInstruction() { -} - -static void ExecuteXSAVEInstruction() { -} - -static void ExecuteOSXSAVEInstruction() { -} - +static void ExecuteFMAInstruction() { +} + +static void ExecuteRDTSCPInstruction() { +} + +static void ExecuteXSAVEInstruction() { +} + +static void ExecuteOSXSAVEInstruction() { +} + Y_UNIT_TEST_SUITE(TestCpuId) { #define DECLARE_TEST_HAVE_INSTRUCTION(name) \ - Y_UNIT_TEST(Test##Have##name) { \ + Y_UNIT_TEST(Test##Have##name) { \ if (NX86::Have##name()) { \ Execute##name##Instruction(); \ } \ - } - - Y_CPU_ID_ENUMERATE(DECLARE_TEST_HAVE_INSTRUCTION) + } + + Y_CPU_ID_ENUMERATE(DECLARE_TEST_HAVE_INSTRUCTION) #undef DECLARE_TEST_HAVE_INSTRUCTION Y_UNIT_TEST(TestSSE2) { -#if defined(_x86_64_) - UNIT_ASSERT(NX86::HaveSSE2()); -#endif - } - +#if defined(_x86_64_) + UNIT_ASSERT(NX86::HaveSSE2()); +#endif + } + Y_UNIT_TEST(TestCpuBrand) { - ui32 store[12]; - - //Cout << CpuBrand(store) << Endl;; - - UNIT_ASSERT(strlen(CpuBrand(store)) > 0); - } + ui32 store[12]; + + //Cout << CpuBrand(store) << Endl;; + + UNIT_ASSERT(strlen(CpuBrand(store)) > 0); + } Y_UNIT_TEST(TestCachedAndNoncached) { -#define Y_DEF_NAME(X) UNIT_ASSERT_VALUES_EQUAL(NX86::Have##X(), NX86::CachedHave##X()); - Y_CPU_ID_ENUMERATE(Y_DEF_NAME) -#undef Y_DEF_NAME +#define Y_DEF_NAME(X) UNIT_ASSERT_VALUES_EQUAL(NX86::Have##X(), NX86::CachedHave##X()); + Y_CPU_ID_ENUMERATE(Y_DEF_NAME) +#undef Y_DEF_NAME } -} +} #if defined(_x86_64_) - #if defined(__GNUC__) + #if defined(__GNUC__) void ExecuteSSEInstruction() { - __asm__ __volatile__("xorps %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("xorps %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteSSE2Instruction() { - __asm__ __volatile__("psrldq $0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("psrldq $0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteSSE3Instruction() { - __asm__ __volatile__("addsubpd %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("addsubpd %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteSSSE3Instruction() { - __asm__ __volatile__("psignb %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("psignb %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteSSE41Instruction() { - __asm__ __volatile__("pmuldq %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("pmuldq %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteSSE42Instruction() { - __asm__ __volatile__("crc32 %%eax, %%eax\n" - : - : - : "eax"); + __asm__ __volatile__("crc32 %%eax, %%eax\n" + : + : + : "eax"); } void ExecuteF16CInstruction() { @@ -142,30 +142,30 @@ void ExecuteF16CInstruction() { } void ExecuteAVXInstruction() { - __asm__ __volatile__("vzeroupper\n" - : - : - : "xmm0"); + __asm__ __volatile__("vzeroupper\n" + : + : + : "xmm0"); } void ExecuteAVX2Instruction() { - __asm__ __volatile__("vpunpcklbw %%ymm0, %%ymm0, %%ymm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("vpunpcklbw %%ymm0, %%ymm0, %%ymm0\n" + : + : + : "xmm0"); } void ExecutePOPCNTInstruction() { - __asm__ __volatile__("popcnt %%eax, %%eax\n" - : - : - : "eax"); + __asm__ __volatile__("popcnt %%eax, %%eax\n" + : + : + : "eax"); } void ExecuteBMI1Instruction() { __asm__ __volatile__("tzcnt %%eax, %%eax\n" - : - : + : + : : "eax"); } @@ -184,10 +184,10 @@ void ExecutePCLMULInstruction() { } void ExecuteAESInstruction() { - __asm__ __volatile__("aesimc %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("aesimc %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteAVX512FInstruction() { @@ -221,31 +221,31 @@ void ExecutePREFETCHWT1Instruction() { } void ExecuteSHAInstruction() { - __asm__ __volatile__("sha1msg1 %%xmm0, %%xmm0\n" - : - : - : "xmm0"); + __asm__ __volatile__("sha1msg1 %%xmm0, %%xmm0\n" + : + : + : "xmm0"); } void ExecuteADXInstruction() { - __asm__ __volatile__("adcx %%eax, %%eax\n" - : - : - : "eax"); + __asm__ __volatile__("adcx %%eax, %%eax\n" + : + : + : "eax"); } void ExecuteRDRANDInstruction() { - __asm__ __volatile__("rdrand %%eax" - : - : - : "eax"); + __asm__ __volatile__("rdrand %%eax" + : + : + : "eax"); } void ExecuteRDSEEDInstruction() { - __asm__ __volatile__("rdseed %%eax" - : - : - : "eax"); + __asm__ __volatile__("rdseed %%eax" + : + : + : "eax"); } void ExecutePCOMMITInstruction() { @@ -257,7 +257,7 @@ void ExecuteCLFLUSHOPTInstruction() { void ExecuteCLWBInstruction() { } - #elif defined(_MSC_VER) + #elif defined(_MSC_VER) void ExecuteSSEInstruction() { } @@ -351,9 +351,9 @@ void ExecuteCLFLUSHOPTInstruction() { void ExecuteCLWBInstruction() { } - #else - #error "unknown compiler" - #endif + #else + #error "unknown compiler" + #endif #else void ExecuteSSEInstruction() { } diff --git a/util/system/daemon.cpp b/util/system/daemon.cpp index 130e6c8f45..e05091b26e 100644 --- a/util/system/daemon.cpp +++ b/util/system/daemon.cpp @@ -1,26 +1,26 @@ -#include <util/generic/yexception.h> - +#include <util/generic/yexception.h> + #include <cerrno> #include <cstdlib> #include <util/system/info.h> - + #if defined(_win_) - #include <io.h> + #include <io.h> #else - #include <sys/wait.h> - #include <unistd.h> - #include <fcntl.h> + #include <sys/wait.h> + #include <unistd.h> + #include <fcntl.h> #endif -#include "daemon.h" +#include "daemon.h" #ifdef _unix_ -using namespace NDaemonMaker; +using namespace NDaemonMaker; static bool Fork(EParent parent) { pid_t pid = fork(); - if (pid > 0) { + if (pid > 0) { int status = 0; while (waitpid(pid, &status, 0) < 0 && errno == EINTR) { } @@ -29,83 +29,83 @@ static bool Fork(EParent parent) { } else { return true; } - } else if (pid < 0) { + } else if (pid < 0) { ythrow TSystemError() << "Cannot fork"; - } + } - if (setsid() < 0) { + if (setsid() < 0) { ythrow TSystemError() << "Cannot setsid"; - } + } - pid = fork(); + pid = fork(); - if (pid > 0) { + if (pid > 0) { _exit(0); - } else if (pid < 0) { + } else if (pid < 0) { ythrow TSystemError() << "Cannot second fork"; - } + } return false; -} +} #endif -static void CloseFromToExcept(int from, int to, const int* except) { - (void)from; - (void)to; - (void)except; - +static void CloseFromToExcept(int from, int to, const int* except) { + (void)from; + (void)to; + (void)except; + #ifdef _unix_ int mfd = NSystemInfo::MaxOpenFiles(); for (int s = from; s < mfd && (to == -1 || s < to); s++) { - for (const int* ex = except; *ex >= 0; ++ex) { - if (s == *ex) { + for (const int* ex = except; *ex >= 0; ++ex) { + if (s == *ex) { goto dontclose; - } - } + } + } while (close(s) == -1) { - if (errno == EBADF) { + if (errno == EBADF) { break; - } - if (errno != EINTR) { - ythrow TSystemError() << "close(" << s << ") failed"; - } + } + if (errno != EINTR) { + ythrow TSystemError() << "close(" << s << ") failed"; + } } - dontclose:; + dontclose:; } #endif /* _unix_ */ } bool NDaemonMaker::MakeMeDaemon(ECloseDescriptors cd, EStdIoDescriptors iod, EChDir chd, EParent parent) { - (void)cd; - (void)iod; - (void)chd; - + (void)cd; + (void)iod; + (void)chd; + #ifdef _unix_ if (Fork(parent)) { return true; } if (chd == chdirRoot) { - if (chdir("/")) { + if (chdir("/")) { ythrow TSystemError() << "chdir(\"/\") failed"; - } + } } - int fd[4] = {-1, -1, -1, -1}; - switch (iod) { + int fd[4] = {-1, -1, -1, -1}; + switch (iod) { case openYandexStd: fd[0] = open("yandex.stdin", O_RDONLY); - if (fd[0] < 0) { + if (fd[0] < 0) { ythrow TSystemError() << "Cannot open 'yandex.stdin'"; - } + } fd[1] = open("yandex.stdout", O_WRONLY | O_APPEND | O_CREAT, 660); - if (fd[1] < 0) { + if (fd[1] < 0) { ythrow TSystemError() << "Cannot open 'yandex.stdout'"; - } + } fd[2] = open("yandex.stderr", O_WRONLY | O_APPEND | O_CREAT, 660); - if (fd[2] < 0) { + if (fd[2] < 0) { ythrow TSystemError() << "Cannot open 'yandex.stderr'"; - } + } break; case openDevNull: fd[0] = open("/dev/null", O_RDWR, 0); @@ -120,38 +120,38 @@ bool NDaemonMaker::MakeMeDaemon(ECloseDescriptors cd, EStdIoDescriptors iod, ECh fd[0], fd[1], fd[2], - -1}; - if (closeAll == cd) { + -1}; + if (closeAll == cd) { CloseFromToExcept(0, -1, except); - } else if (closeStdIoOnly == cd) { + } else if (closeStdIoOnly == cd) { CloseFromToExcept(0, 3, except); - } else { + } else { ythrow yexception() << "Unknown close descriptors mode: " << (int)cd; - } + } - switch (iod) { + switch (iod) { case openYandexStd: /* Assuming that open(2) acquires fds in order. */ dup2(fd[0], STDIN_FILENO); - if (fd[0] > 2) { + if (fd[0] > 2) { close(fd[0]); - } + } dup2(fd[1], STDOUT_FILENO); - if (fd[1] > 2) { + if (fd[1] > 2) { close(fd[1]); - } + } dup2(fd[2], STDERR_FILENO); - if (fd[2] > 2) { + if (fd[2] > 2) { close(fd[2]); - } + } break; case openDevNull: dup2(fd[0], STDIN_FILENO); dup2(fd[0], STDOUT_FILENO); dup2(fd[0], STDERR_FILENO); - if (fd[0] > 2) { + if (fd[0] > 2) { close(fd[0]); - } + } break; default: break; @@ -163,6 +163,6 @@ bool NDaemonMaker::MakeMeDaemon(ECloseDescriptors cd, EStdIoDescriptors iod, ECh } void NDaemonMaker::CloseFrom(int fd) { - static const int except[1] = {-1}; + static const int except[1] = {-1}; CloseFromToExcept(fd, -1, except); } diff --git a/util/system/daemon.h b/util/system/daemon.h index b00793b9c9..3ef8b9dabc 100644 --- a/util/system/daemon.h +++ b/util/system/daemon.h @@ -1,17 +1,17 @@ #pragma once -namespace NDaemonMaker { - enum ECloseDescriptors { - closeAll = 0, - closeStdIoOnly - }; - - enum EStdIoDescriptors { - openNone = 0, - openDevNull, - openYandexStd - }; +namespace NDaemonMaker { + enum ECloseDescriptors { + closeAll = 0, + closeStdIoOnly + }; + enum EStdIoDescriptors { + openNone = 0, + openDevNull, + openYandexStd + }; + enum EChDir { chdirNone = 0, chdirRoot @@ -24,4 +24,4 @@ namespace NDaemonMaker { bool MakeMeDaemon(ECloseDescriptors cd = closeAll, EStdIoDescriptors iod = openDevNull, EChDir chd = chdirRoot, EParent parent = callExitFromParent); void CloseFrom(int fd); -} +} diff --git a/util/system/daemon_ut.cpp b/util/system/daemon_ut.cpp index f93b9a9645..82a4be1428 100644 --- a/util/system/daemon_ut.cpp +++ b/util/system/daemon_ut.cpp @@ -9,7 +9,7 @@ Y_UNIT_TEST_SUITE(TDaemonTest) { #ifdef _unix_ template <typename Func> - static bool ProcessBuffer(Func&& func, void* bufin, size_t size) { + static bool ProcessBuffer(Func&& func, void* bufin, size_t size) { char* buf = (char*)bufin; do { const ssize_t bytesDone = func(buf, size); diff --git a/util/system/datetime.cpp b/util/system/datetime.cpp index b07b50679a..c5839a6340 100644 --- a/util/system/datetime.cpp +++ b/util/system/datetime.cpp @@ -1,27 +1,27 @@ -#include "datetime.h" -#include "yassert.h" -#include "platform.h" -#include "cpu_id.h" - -#include <util/datetime/systime.h> - +#include "datetime.h" +#include "yassert.h" +#include "platform.h" +#include "cpu_id.h" + +#include <util/datetime/systime.h> + #include <ctime> #include <cerrno> #ifdef _darwin_ - #include <AvailabilityMacros.h> - #if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 - #define Y_HAS_CLOCK_GETTIME - #endif + #include <AvailabilityMacros.h> + #if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 + #define Y_HAS_CLOCK_GETTIME + #endif #elif defined(_linux_) || defined(_freebsd_) || defined(_cygwin_) - #define Y_HAS_CLOCK_GETTIME + #define Y_HAS_CLOCK_GETTIME #endif static ui64 ToMicroSeconds(const struct timeval& tv) { - return (ui64)tv.tv_sec * 1000000 + (ui64)tv.tv_usec; + return (ui64)tv.tv_sec * 1000000 + (ui64)tv.tv_usec; } -#if defined(_win_) +#if defined(_win_) static ui64 ToMicroSeconds(const FILETIME& ft) { return (((ui64)ft.dwHighDateTime << 32) + (ui64)ft.dwLowDateTime) / (ui64)10; } @@ -38,8 +38,8 @@ ui64 MicroSeconds() noexcept { return ToMicroSeconds(tv); } -ui64 ThreadCPUUserTime() noexcept { -#if defined(_win_) +ui64 ThreadCPUUserTime() noexcept { +#if defined(_win_) FILETIME creationTime, exitTime, kernelTime, userTime; GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime); return ToMicroSeconds(userTime); @@ -49,7 +49,7 @@ ui64 ThreadCPUUserTime() noexcept { } ui64 ThreadCPUSystemTime() noexcept { -#if defined(_win_) +#if defined(_win_) FILETIME creationTime, exitTime, kernelTime, userTime; GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime); return ToMicroSeconds(kernelTime); @@ -59,7 +59,7 @@ ui64 ThreadCPUSystemTime() noexcept { } ui64 ThreadCPUTime() noexcept { -#if defined(_win_) +#if defined(_win_) FILETIME creationTime, exitTime, kernelTime, userTime; GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime); return ToMicroSeconds(userTime) + ToMicroSeconds(kernelTime); @@ -79,7 +79,7 @@ ui32 Seconds() noexcept { } void NanoSleep(ui64 ns) noexcept { -#if defined(_win_) +#if defined(_win_) Sleep(ns / 1000000); #else const ui64 NS = 1000 * 1000 * 1000; @@ -93,11 +93,11 @@ void NanoSleep(ui64 ns) noexcept { } #endif } - + #if defined(_x86_) -extern const bool HaveRdtscp = NX86::HaveRDTSCP(); -#endif +extern const bool HaveRdtscp = NX86::HaveRDTSCP(); +#endif #ifdef Y_HAS_CLOCK_GETTIME - #undef Y_HAS_CLOCK_GETTIME + #undef Y_HAS_CLOCK_GETTIME #endif diff --git a/util/system/datetime.h b/util/system/datetime.h index aa009974e0..3868d8dcb7 100644 --- a/util/system/datetime.h +++ b/util/system/datetime.h @@ -1,15 +1,15 @@ #pragma once -#include "defaults.h" -#include "platform.h" +#include "defaults.h" +#include "platform.h" -#if defined(_win_) - #include <intrin.h> - #pragma intrinsic(__rdtsc) +#if defined(_win_) + #include <intrin.h> + #pragma intrinsic(__rdtsc) #endif // _win_ #if defined(_darwin_) && !defined(_x86_) - #include <mach/mach_time.h> + #include <mach/mach_time.h> #endif /// util/system/datetime.h contains only system time providers @@ -42,7 +42,7 @@ void NanoSleep(ui64 ns) noexcept; // PERFORMANCE: rdtsc - 15 cycles per call , rdtscp - 19 cycles per call // WARNING: following instruction can be executed out-of-order Y_FORCE_INLINE ui64 GetCycleCount() noexcept { -#if defined(_MSC_VER) +#if defined(_MSC_VER) // Generates the rdtscp instruction, which returns the processor time stamp. // The processor time stamp records the number of clock cycles since the last reset. extern const bool HaveRdtscp; @@ -53,24 +53,24 @@ Y_FORCE_INLINE ui64 GetCycleCount() noexcept { } else { return __rdtsc(); } -#elif defined(_x86_64_) +#elif defined(_x86_64_) + extern const bool HaveRdtscp; + + unsigned hi, lo; + + if (HaveRdtscp) { + __asm__ __volatile__("rdtscp" + : "=a"(lo), "=d"(hi)::"%rcx"); + } else { + __asm__ __volatile__("rdtsc" + : "=a"(lo), "=d"(hi)); + } + + return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); +#elif defined(_i386_) extern const bool HaveRdtscp; - unsigned hi, lo; - - if (HaveRdtscp) { - __asm__ __volatile__("rdtscp" - : "=a"(lo), "=d"(hi)::"%rcx"); - } else { - __asm__ __volatile__("rdtsc" - : "=a"(lo), "=d"(hi)); - } - - return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); -#elif defined(_i386_) - extern const bool HaveRdtscp; - - ui64 x; + ui64 x; if (HaveRdtscp) { __asm__ volatile("rdtscp\n\t" : "=A"(x)::"%ecx"); @@ -78,21 +78,21 @@ Y_FORCE_INLINE ui64 GetCycleCount() noexcept { __asm__ volatile("rdtsc\n\t" : "=A"(x)); } - return x; + return x; #elif defined(_darwin_) return mach_absolute_time(); #elif defined(__clang__) && !defined(_arm_) return __builtin_readcyclecounter(); -#elif defined(_arm32_) - return MicroSeconds(); -#elif defined(_arm64_) - ui64 x; - - __asm__ __volatile__("isb; mrs %0, cntvct_el0" - : "=r"(x)); - - return x; -#else - #error "unsupported arch" +#elif defined(_arm32_) + return MicroSeconds(); +#elif defined(_arm64_) + ui64 x; + + __asm__ __volatile__("isb; mrs %0, cntvct_el0" + : "=r"(x)); + + return x; +#else + #error "unsupported arch" #endif } diff --git a/util/system/defaults.c b/util/system/defaults.c index 75710009ac..4daa4984c1 100644 --- a/util/system/defaults.c +++ b/util/system/defaults.c @@ -1,2 +1,2 @@ -//test for C-compiler compileability -#include "defaults.h" +//test for C-compiler compileability +#include "defaults.h" diff --git a/util/system/defaults.h b/util/system/defaults.h index dcd7abea38..d1889519cd 100644 --- a/util/system/defaults.h +++ b/util/system/defaults.h @@ -3,91 +3,91 @@ #include "platform.h" #if defined _unix_ - #define LOCSLASH_C '/' - #define LOCSLASH_S "/" + #define LOCSLASH_C '/' + #define LOCSLASH_S "/" #else - #define LOCSLASH_C '\\' - #define LOCSLASH_S "\\" + #define LOCSLASH_C '\\' + #define LOCSLASH_S "\\" #endif // _unix_ -#if defined(__INTEL_COMPILER) && defined(__cplusplus) - #include <new> -#endif - +#if defined(__INTEL_COMPILER) && defined(__cplusplus) + #include <new> +#endif + // low and high parts of integers #if !defined(_win_) - #include <sys/param.h> + #include <sys/param.h> #endif - + #if defined(BSD) || defined(_android_) - #if defined(BSD) - #include <machine/endian.h> - #endif + #if defined(BSD) + #include <machine/endian.h> + #endif - #if defined(_android_) - #include <endian.h> - #endif + #if defined(_android_) + #include <endian.h> + #endif - #if (BYTE_ORDER == LITTLE_ENDIAN) - #define _little_endian_ - #elif (BYTE_ORDER == BIG_ENDIAN) - #define _big_endian_ - #else - #error unknown endian not supported - #endif + #if (BYTE_ORDER == LITTLE_ENDIAN) + #define _little_endian_ + #elif (BYTE_ORDER == BIG_ENDIAN) + #define _big_endian_ + #else + #error unknown endian not supported + #endif -#elif (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(WHATEVER_THAT_HAS_BIG_ENDIAN) - #define _big_endian_ -#else - #define _little_endian_ -#endif +#elif (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(WHATEVER_THAT_HAS_BIG_ENDIAN) + #define _big_endian_ +#else + #define _little_endian_ +#endif // alignment -#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_QUADS) - #define _must_align8_ +#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_QUADS) + #define _must_align8_ #endif -#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_LONGS) - #define _must_align4_ +#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_LONGS) + #define _must_align4_ #endif -#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_SHORTS) - #define _must_align2_ +#if (defined(_sun_) && !defined(__i386__)) || defined(_hpux_) || defined(__alpha__) || defined(__ia64__) || defined(WHATEVER_THAT_NEEDS_ALIGNING_SHORTS) + #define _must_align2_ #endif #if defined(__GNUC__) - #define alias_hack __attribute__((__may_alias__)) + #define alias_hack __attribute__((__may_alias__)) #endif #ifndef alias_hack - #define alias_hack + #define alias_hack #endif -#include "types.h" - +#include "types.h" + #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #define PRAGMA(x) _Pragma(#x) - #define RCSID(idstr) PRAGMA(comment(exestr, idstr)) + #define PRAGMA(x) _Pragma(#x) + #define RCSID(idstr) PRAGMA(comment(exestr, idstr)) #else - #define RCSID(idstr) static const char rcsid[] = idstr + #define RCSID(idstr) static const char rcsid[] = idstr #endif -#include "compiler.h" +#include "compiler.h" #ifdef _win_ - #include <malloc.h> + #include <malloc.h> #elif defined(_sun_) - #include <alloca.h> + #include <alloca.h> #endif #ifdef NDEBUG - #define Y_IF_DEBUG(X) + #define Y_IF_DEBUG(X) #ifdef __cplusplus constexpr bool Y_IS_DEBUG_BUILD = false; #endif #else - #define Y_IF_DEBUG(X) X + #define Y_IF_DEBUG(X) X #ifdef __cplusplus constexpr bool Y_IS_DEBUG_BUILD = true; #endif @@ -120,14 +120,14 @@ constexpr bool Y_IS_DEBUG_BUILD = true; * Since all of our code is expected to work on a 64 bit platform where pointers are 8 bytes we may * falsefully accept pointers to types of sizes that are divisors of 8 (1, 2, 4 and 8). */ -#if defined(__cplusplus) - #include <util/generic/array_size.h> -#else - #undef Y_ARRAY_SIZE - #define Y_ARRAY_SIZE(arr) \ - ((sizeof(arr) / sizeof((arr)[0])) / static_cast<size_t>(!(sizeof(arr) % sizeof((arr)[0])))) -#endif - +#if defined(__cplusplus) + #include <util/generic/array_size.h> +#else + #undef Y_ARRAY_SIZE + #define Y_ARRAY_SIZE(arr) \ + ((sizeof(arr) / sizeof((arr)[0])) / static_cast<size_t>(!(sizeof(arr) % sizeof((arr)[0])))) +#endif + #undef Y_ARRAY_BEGIN #define Y_ARRAY_BEGIN(arr) (arr) @@ -144,12 +144,12 @@ constexpr bool Y_IS_DEBUG_BUILD = true; #define Y_STRINGIZE(X) UTIL_PRIVATE_STRINGIZE_AUX(X) #define UTIL_PRIVATE_STRINGIZE_AUX(X) #X -#if defined(__COUNTER__) - #define Y_GENERATE_UNIQUE_ID(N) Y_CAT(N, __COUNTER__) -#endif - +#if defined(__COUNTER__) + #define Y_GENERATE_UNIQUE_ID(N) Y_CAT(N, __COUNTER__) +#endif + #if !defined(Y_GENERATE_UNIQUE_ID) - #define Y_GENERATE_UNIQUE_ID(N) Y_CAT(N, __LINE__) -#endif + #define Y_GENERATE_UNIQUE_ID(N) Y_CAT(N, __LINE__) +#endif #define NPOS ((size_t)-1) diff --git a/util/system/direct_io.cpp b/util/system/direct_io.cpp index f59c54b0cb..38b5e7ba28 100644 --- a/util/system/direct_io.cpp +++ b/util/system/direct_io.cpp @@ -3,42 +3,42 @@ #include <util/generic/singleton.h> #include <util/generic/yexception.h> #include <util/system/info.h> -#include "align.h" +#include "align.h" #ifdef _linux_ - #include <util/string/cast.h> - #include <linux/version.h> - #include <sys/utsname.h> + #include <util/string/cast.h> + #include <linux/version.h> + #include <sys/utsname.h> #endif - + namespace { - struct TAlignmentCalcer { - inline TAlignmentCalcer() + struct TAlignmentCalcer { + inline TAlignmentCalcer() : Alignment(0) { #ifdef _linux_ utsname sysInfo; - + Y_VERIFY(!uname(&sysInfo), "Error while call uname: %s", LastSystemErrorText()); - + TStringBuf release(sysInfo.release); release = release.substr(0, release.find_first_not_of(".0123456789")); - + int v1 = FromString<int>(release.NextTok('.')); int v2 = FromString<int>(release.NextTok('.')); int v3 = FromString<int>(release.NextTok('.')); int linuxVersionCode = KERNEL_VERSION(v1, v2, v3); - - if (linuxVersionCode < KERNEL_VERSION(2, 4, 10)) { + + if (linuxVersionCode < KERNEL_VERSION(2, 4, 10)) { Alignment = 0; - } else if (linuxVersionCode < KERNEL_VERSION(2, 6, 0)) { + } else if (linuxVersionCode < KERNEL_VERSION(2, 6, 0)) { Alignment = NSystemInfo::GetPageSize(); - } else { + } else { // Default alignment used to be 512, but most modern devices rely on 4k physical blocks. // 4k alignment works well for both 512 and 4k blocks and doesn't require 512e support in the kernel. // See IGNIETFERRO-946. Alignment = 4096; - } + } #endif } @@ -59,7 +59,7 @@ TDirectIOBufferedFile::TDirectIOBufferedFile(const TString& path, EOpenMode oMod } if (oMode & Direct) { - Alignment = Singleton<TAlignmentCalcer>()->Alignment; + Alignment = Singleton<TAlignmentCalcer>()->Alignment; SetDirectIO(true); } @@ -75,16 +75,16 @@ TDirectIOBufferedFile::TDirectIOBufferedFile(const TString& path, EOpenMode oMod void TDirectIOBufferedFile::SetDirectIO(bool value) { #ifdef _linux_ - if (DirectIO == value) { + if (DirectIO == value) { return; - } - - if (!!Alignment && value) { + } + + if (!!Alignment && value) { (void)fcntl(File.GetHandle(), F_SETFL, fcntl(File.GetHandle(), F_GETFL) | DIRECT_IO_FLAGS); - } else { + } else { (void)fcntl(File.GetHandle(), F_SETFL, fcntl(File.GetHandle(), F_GETFL) & ~DIRECT_IO_FLAGS); - } - + } + DirectIO = value; #else DirectIO = value; @@ -103,7 +103,7 @@ void TDirectIOBufferedFile::FlushData() { DataLen = 0; File.FlushData(); } - + void TDirectIOBufferedFile::Finish() { FlushData(); File.Flush(); @@ -118,15 +118,15 @@ void TDirectIOBufferedFile::Write(const void* buffer, size_t byteCount) { void TDirectIOBufferedFile::WriteToBuffer(const void* buf, size_t len, ui64 position) { while (len > 0) { size_t writeLen = Min<size_t>(BufLen - position, len); - + if (writeLen > 0) { memcpy((char*)Buffer + position, buf, writeLen); buf = (char*)buf + writeLen; len -= writeLen; - DataLen = (size_t)Max(position + writeLen, (ui64)DataLen); + DataLen = (size_t)Max(position + writeLen, (ui64)DataLen); position += writeLen; } - + if (DataLen == BufLen) { WriteToFile(Buffer, DataLen, FlushedBytes); DataLen = 0; @@ -138,9 +138,9 @@ void TDirectIOBufferedFile::WriteToBuffer(const void* buf, size_t len, ui64 posi void TDirectIOBufferedFile::WriteToFile(const void* buf, size_t len, ui64 position) { if (!!len) { SetDirectIO(IsAligned(buf) && IsAligned(len) && IsAligned(position)); - + File.Pwrite(buf, len, position); - + FlushedBytes = Max(FlushedBytes, position + len); FlushedToDisk = Min(FlushedToDisk, position); } @@ -157,11 +157,11 @@ size_t TDirectIOBufferedFile::PreadSafe(void* buffer, size_t byteCount, ui64 off do { bytesRead = pread(File.GetHandle(), buffer, byteCount, offset); } while (bytesRead == -1 && errno == EINTR); - + if (bytesRead < 0) { ythrow yexception() << "error while pread file: " << LastSystemError() << "(" << LastSystemErrorText() << ")"; - } - + } + return bytesRead; #else return File.Pread(buffer, byteCount, offset); @@ -186,29 +186,29 @@ size_t TDirectIOBufferedFile::ReadFromFile(void* buffer, size_t byteCount, ui64 } else { break; } - } + } if (!byteCount) { return bytesRead; } - + ui64 bufSize = AlignUp(Min<size_t>(BufferStorage.Size(), byteCount + (Alignment << 1)), Alignment); TBuffer readBufferStorage(bufSize + Alignment); char* readBuffer = AlignUp((char*)readBufferStorage.Data(), Alignment); - + while (byteCount) { - ui64 begin = AlignDown(offset, (ui64)Alignment); - ui64 end = AlignUp(offset + byteCount, (ui64)Alignment); + ui64 begin = AlignDown(offset, (ui64)Alignment); + ui64 end = AlignUp(offset + byteCount, (ui64)Alignment); ui64 toRead = Min(end - begin, bufSize); ui64 fromFile = PreadSafe(readBuffer, toRead, begin); - - if (!fromFile) { + + if (!fromFile) { break; - } - + } + ui64 delta = offset - begin; ui64 count = Min<ui64>(fromFile - delta, byteCount); - + memcpy(buffer, readBuffer + delta, count); buffer = (char*)buffer + count; byteCount -= count; @@ -225,23 +225,23 @@ size_t TDirectIOBufferedFile::Read(void* buffer, size_t byteCount) { } size_t TDirectIOBufferedFile::Pread(void* buffer, size_t byteCount, ui64 offset) { - if (!byteCount) { + if (!byteCount) { return 0; - } - + } + size_t readFromFile = 0; if (offset < FlushedBytes) { readFromFile = Min<ui64>(byteCount, FlushedBytes - offset); size_t bytesRead = ReadFromFile(buffer, readFromFile, offset); if (bytesRead != readFromFile || readFromFile == byteCount) { return bytesRead; - } + } } ui64 start = offset > FlushedBytes ? offset - FlushedBytes : 0; ui64 count = Min<ui64>(DataLen - start, byteCount - readFromFile); - if (count) { + if (count) { memcpy((char*)buffer + readFromFile, (const char*)Buffer + start, count); - } + } return count + readFromFile; } @@ -249,16 +249,16 @@ void TDirectIOBufferedFile::Pwrite(const void* buffer, size_t byteCount, ui64 of if (offset > WritePosition) { ythrow yexception() << "cannot frite to position" << offset; } - + size_t writeToBufer = byteCount; size_t writeToFile = 0; - + if (FlushedBytes > offset) { writeToFile = Min<ui64>(byteCount, FlushedBytes - offset); WriteToFile(buffer, writeToFile, offset); writeToBufer -= writeToFile; } - + if (writeToBufer > 0) { ui64 bufferOffset = offset + writeToFile - FlushedBytes; WriteToBuffer((const char*)buffer + writeToFile, writeToBufer, bufferOffset); diff --git a/util/system/direct_io.h b/util/system/direct_io.h index 6a3325a960..b228af2105 100644 --- a/util/system/direct_io.h +++ b/util/system/direct_io.h @@ -1,8 +1,8 @@ #pragma once -#include "align.h" - -#include "file.h" +#include "align.h" + +#include "file.h" #include <util/generic/buffer.h> // Supports Linux Direct-IO: @@ -13,7 +13,7 @@ class TDirectIOBufferedFile { public: TDirectIOBufferedFile(const TString& path, EOpenMode oMode, size_t buflen = 1 << 17); ~TDirectIOBufferedFile(); - + void FlushData(); void Finish(); size_t Read(void* buffer, size_t byteCount); @@ -49,7 +49,7 @@ private: inline bool IsAligned(i64 value) { return Alignment ? value == AlignDown<i64>(value, Alignment) : true; } - + inline bool IsAligned(const void* value) { return Alignment ? value == AlignDown(value, Alignment) : true; } @@ -60,7 +60,7 @@ private: void WriteToBuffer(const void* buf, size_t len, ui64 position); void SetDirectIO(bool value); -private: +private: TFile File; size_t Alignment; size_t BufLen; diff --git a/util/system/direct_io_ut.cpp b/util/system/direct_io_ut.cpp index 839c3de7ca..c6691a8f72 100644 --- a/util/system/direct_io_ut.cpp +++ b/util/system/direct_io_ut.cpp @@ -5,7 +5,7 @@ #include <util/system/tempfile.h> #include <util/random/random.h> -#include "direct_io.h" +#include "direct_io.h" static const char* FileName_("./test.file"); @@ -14,43 +14,43 @@ Y_UNIT_TEST_SUITE(TDirectIoTestSuite) { TDirectIOBufferedFile file(FileName_, RdWr | Direct | Seq | CreateAlways, 1 << 15); TVector<ui64> data((1 << 15) + 1); TVector<ui64> readResult(data.size()); - for (auto& i : data) { - i = RandomNumber<ui64>(); - } - for (size_t writePos = 0; writePos < data.size();) { - size_t writeCount = Min<size_t>(1 + RandomNumber<size_t>(1 << 10), data.ysize() - writePos); - file.Write(&data[writePos], sizeof(ui64) * writeCount); - writePos += writeCount; + for (auto& i : data) { + i = RandomNumber<ui64>(); + } + for (size_t writePos = 0; writePos < data.size();) { + size_t writeCount = Min<size_t>(1 + RandomNumber<size_t>(1 << 10), data.ysize() - writePos); + file.Write(&data[writePos], sizeof(ui64) * writeCount); + writePos += writeCount; size_t readPos = RandomNumber(writePos); - size_t readCount = RandomNumber(writePos - readPos); + size_t readCount = RandomNumber(writePos - readPos); UNIT_ASSERT_VALUES_EQUAL( file.Pread(&readResult[0], readCount * sizeof(ui64), readPos * sizeof(ui64)), - readCount * sizeof(ui64)); + readCount * sizeof(ui64)); for (size_t i = 0; i < readCount; ++i) { UNIT_ASSERT_VALUES_EQUAL(readResult[i], data[i + readPos]); } - } - file.Finish(); + } + file.Finish(); TDirectIOBufferedFile fileNew(FileName_, RdOnly | Direct | Seq | OpenAlways, 1 << 15); - for (int i = 0; i < 1000; ++i) { + for (int i = 0; i < 1000; ++i) { size_t readPos = RandomNumber(data.size()); - size_t readCount = RandomNumber(data.size() - readPos); + size_t readCount = RandomNumber(data.size() - readPos); UNIT_ASSERT_VALUES_EQUAL( fileNew.Pread(&readResult[0], readCount * sizeof(ui64), readPos * sizeof(ui64)), - readCount * sizeof(ui64)); - for (size_t j = 0; j < readCount; ++j) { + readCount * sizeof(ui64)); + for (size_t j = 0; j < readCount; ++j) { UNIT_ASSERT_VALUES_EQUAL(readResult[j], data[j + readPos]); - } - } - size_t readCount = data.size(); + } + } + size_t readCount = data.size(); UNIT_ASSERT_VALUES_EQUAL( fileNew.Pread(&readResult[0], readCount * sizeof(ui64), 0), - readCount * sizeof(ui64)); + readCount * sizeof(ui64)); for (size_t i = 0; i < readCount; ++i) { UNIT_ASSERT_VALUES_EQUAL(readResult[i], data[i]); } NFs::Remove(FileName_); - } + } void TestHugeFile(size_t size) { TTempFile tmpFile("test.file"); @@ -77,12 +77,12 @@ Y_UNIT_TEST_SUITE(TDirectIoTestSuite) { } Y_UNIT_TEST(TestHugeFile1) { - if constexpr (sizeof(size_t) > 4) { + if constexpr (sizeof(size_t) > 4) { TestHugeFile(5 * 1024 * 1024 * 1024ULL); } } Y_UNIT_TEST(TestHugeFile2) { - if constexpr (sizeof(size_t) > 4) { + if constexpr (sizeof(size_t) > 4) { TestHugeFile(5 * 1024 * 1024 * 1024ULL + 1111); } } @@ -91,7 +91,7 @@ Y_UNIT_TEST_SUITE(TDirectIoTestSuite) { Y_UNIT_TEST_SUITE(TDirectIoErrorHandling) { Y_UNIT_TEST(Constructor) { // A non-existent file should not be opened for reading - UNIT_ASSERT_EXCEPTION(TDirectIOBufferedFile(FileName_, RdOnly, 1 << 15), TFileError); + UNIT_ASSERT_EXCEPTION(TDirectIOBufferedFile(FileName_, RdOnly, 1 << 15), TFileError); } Y_UNIT_TEST(WritingReadOnlyFileBufferFlushed) { diff --git a/util/system/dynlib.cpp b/util/system/dynlib.cpp index 9d2541c25f..d77605723f 100644 --- a/util/system/dynlib.cpp +++ b/util/system/dynlib.cpp @@ -1,138 +1,138 @@ -#include "dynlib.h" - -#include "guard.h" -#include "mutex.h" +#include "dynlib.h" + +#include "guard.h" +#include "mutex.h" #include <util/generic/singleton.h> -#include <util/generic/yexception.h> - -#ifdef _win32_ - #include "winint.h" - - #define DLLOPEN(path, flags) LoadLibrary(path) - #define DLLCLOSE(hndl) FreeLibrary(hndl) - #define DLLSYM(hndl, name) GetProcAddress(hndl, name) -#else - #include <dlfcn.h> - - #ifndef RTLD_GLOBAL - #define RTLD_GLOBAL (0) - #endif - +#include <util/generic/yexception.h> + +#ifdef _win32_ + #include "winint.h" + + #define DLLOPEN(path, flags) LoadLibrary(path) + #define DLLCLOSE(hndl) FreeLibrary(hndl) + #define DLLSYM(hndl, name) GetProcAddress(hndl, name) +#else + #include <dlfcn.h> + + #ifndef RTLD_GLOBAL + #define RTLD_GLOBAL (0) + #endif + using HINSTANCE = void*; - - #define DLLOPEN(path, flags) dlopen(path, flags) - #define DLLCLOSE(hndl) dlclose(hndl) - #define DLLSYM(hndl, name) dlsym(hndl, name) -#endif - + + #define DLLOPEN(path, flags) dlopen(path, flags) + #define DLLCLOSE(hndl) dlclose(hndl) + #define DLLSYM(hndl, name) dlsym(hndl, name) +#endif + inline TString DLLERR() { -#ifdef _unix_ - return dlerror(); -#endif - -#ifdef _win32_ - char* msg = 0; - DWORD cnt = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, +#ifdef _unix_ + return dlerror(); +#endif + +#ifdef _win32_ + char* msg = 0; + DWORD cnt = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, nullptr); - if (!msg) - return "DLLERR() unknown error"; - while (cnt && isspace(msg[cnt - 1])) + if (!msg) + return "DLLERR() unknown error"; + while (cnt && isspace(msg[cnt - 1])) --cnt; TString err(msg, 0, cnt); - LocalFree(msg); - return err; -#endif -} - -class TDynamicLibrary::TImpl { -private: - inline TImpl(const char* path, int flags) - : Module(DLLOPEN(path, flags)) - , Unloadable(true) - { - (void)flags; - - if (!Module) { + LocalFree(msg); + return err; +#endif +} + +class TDynamicLibrary::TImpl { +private: + inline TImpl(const char* path, int flags) + : Module(DLLOPEN(path, flags)) + , Unloadable(true) + { + (void)flags; + + if (!Module) { ythrow yexception() << DLLERR().data(); - } - } - - class TCreateMutex: public TMutex { - }; - -public: - static inline TImpl* SafeCreate(const char* path, int flags) { - auto guard = Guard(*Singleton<TCreateMutex>()); - - return new TImpl(path, flags); - } + } + } + + class TCreateMutex: public TMutex { + }; + +public: + static inline TImpl* SafeCreate(const char* path, int flags) { + auto guard = Guard(*Singleton<TCreateMutex>()); + + return new TImpl(path, flags); + } inline ~TImpl() { - if (Module && Unloadable) { - DLLCLOSE(Module); - } - } - + if (Module && Unloadable) { + DLLCLOSE(Module); + } + } + inline void* SymOptional(const char* name) noexcept { - return (void*)DLLSYM(Module, name); - } - - inline void* Sym(const char* name) { - void* symbol = SymOptional(name); - + return (void*)DLLSYM(Module, name); + } + + inline void* Sym(const char* name) { + void* symbol = SymOptional(name); + if (symbol == nullptr) { ythrow yexception() << DLLERR().data(); - } - - return symbol; - } - - inline void SetUnloadable(bool unloadable) { - Unloadable = unloadable; - } - -private: - HINSTANCE Module; - bool Unloadable; -}; - + } + + return symbol; + } + + inline void SetUnloadable(bool unloadable) { + Unloadable = unloadable; + } + +private: + HINSTANCE Module; + bool Unloadable; +}; + TDynamicLibrary::TDynamicLibrary() noexcept { -} - +} + TDynamicLibrary::TDynamicLibrary(const TString& path, int flags) { Open(path.data(), flags); -} - +} + TDynamicLibrary::~TDynamicLibrary() = default; - + void TDynamicLibrary::Open(const char* path, int flags) { Impl_.Reset(TImpl::SafeCreate(path, flags)); -} - +} + void TDynamicLibrary::Close() noexcept { - Impl_.Destroy(); -} - + Impl_.Destroy(); +} + void* TDynamicLibrary::SymOptional(const char* name) noexcept { - if (!IsLoaded()) { + if (!IsLoaded()) { return nullptr; - } - - return Impl_->SymOptional(name); -} - -void* TDynamicLibrary::Sym(const char* name) { - if (!IsLoaded()) { + } + + return Impl_->SymOptional(name); +} + +void* TDynamicLibrary::Sym(const char* name) { + if (!IsLoaded()) { ythrow yexception() << "library not loaded"; - } - - return Impl_->Sym(name); -} - + } + + return Impl_->Sym(name); +} + bool TDynamicLibrary::IsLoaded() const noexcept { - return (bool)Impl_.Get(); -} + return (bool)Impl_.Get(); +} void TDynamicLibrary::SetUnloadable(bool unloadable) { - Impl_->SetUnloadable(unloadable); + Impl_->SetUnloadable(unloadable); } diff --git a/util/system/dynlib.h b/util/system/dynlib.h index 66eaf4a5c1..1a5015f7f4 100644 --- a/util/system/dynlib.h +++ b/util/system/dynlib.h @@ -1,58 +1,58 @@ #pragma once -#include "defaults.h" - +#include "defaults.h" + #include <util/generic/ptr.h> #include <util/generic/string.h> - + #define Y_GET_FUNC(dll, name) FUNC_##name((dll).Sym(#name)) #define Y_GET_FUNC_OPTIONAL(dll, name) FUNC_##name((dll).SymOptional(#name)) #ifdef _win32_ - #define DEFAULT_DLLOPEN_FLAGS 0 + #define DEFAULT_DLLOPEN_FLAGS 0 #else - #include <dlfcn.h> + #include <dlfcn.h> - #ifndef RTLD_GLOBAL - #define RTLD_GLOBAL (0) - #endif + #ifndef RTLD_GLOBAL + #define RTLD_GLOBAL (0) + #endif - #define DEFAULT_DLLOPEN_FLAGS (RTLD_NOW | RTLD_GLOBAL) + #define DEFAULT_DLLOPEN_FLAGS (RTLD_NOW | RTLD_GLOBAL) #endif -class TDynamicLibrary { -public: +class TDynamicLibrary { +public: TDynamicLibrary() noexcept; TDynamicLibrary(const TString& path, int flags = DEFAULT_DLLOPEN_FLAGS); ~TDynamicLibrary(); - void Open(const char* path, int flags = DEFAULT_DLLOPEN_FLAGS); + void Open(const char* path, int flags = DEFAULT_DLLOPEN_FLAGS); void Close() noexcept; void* SymOptional(const char* name) noexcept; - void* Sym(const char* name); + void* Sym(const char* name); bool IsLoaded() const noexcept; - void SetUnloadable(bool unloadable); // Set to false to avoid unloading on destructor + void SetUnloadable(bool unloadable); // Set to false to avoid unloading on destructor -private: - class TImpl; - THolder<TImpl> Impl_; +private: + class TImpl; + THolder<TImpl> Impl_; }; // a wrapper for a symbol template <class TLib> -class TExternalSymbol { +class TExternalSymbol { private: - TLib* PLib; - TDynamicLibrary* DLib; + TLib* PLib; + TDynamicLibrary* DLib; TString lname; TString vname; - + public: TExternalSymbol() noexcept { PLib = nullptr; DLib = nullptr; } - TExternalSymbol(const TExternalSymbol& es) { + TExternalSymbol(const TExternalSymbol& es) { PLib = nullptr; DLib = nullptr; if (es.IsDynamic()) @@ -60,7 +60,7 @@ public: else if (es.IsStatic()) SetSym(es.Symbol()); } - TExternalSymbol& operator=(const TExternalSymbol& es) { + TExternalSymbol& operator=(const TExternalSymbol& es) { if (this != &es) { Close(); if (es.IsDynamic()) @@ -74,14 +74,14 @@ public: delete DLib; } // set the symbol from dynamic source - void Open(const char* lib_name, const char* vtbl_name) { + void Open(const char* lib_name, const char* vtbl_name) { if (DLib != nullptr || PLib != nullptr) return; try { DLib = new TDynamicLibrary(); DLib->Open(lib_name); - PLib = (TLib*)DLib->Sym(vtbl_name); - } catch (...) { + PLib = (TLib*)DLib->Sym(vtbl_name); + } catch (...) { delete DLib; DLib = nullptr; throw; diff --git a/util/system/env.cpp b/util/system/env.cpp index ead9b566a5..eb90154e51 100644 --- a/util/system/env.cpp +++ b/util/system/env.cpp @@ -4,11 +4,11 @@ #include <util/generic/yexception.h> #ifdef _win_ - #include <util/generic/vector.h> - #include "winint.h" + #include <util/generic/vector.h> + #include "winint.h" #else - #include <cerrno> - #include <cstdlib> + #include <cerrno> + #include <cstdlib> #endif /** diff --git a/util/system/env_ut.cpp b/util/system/env_ut.cpp index e03cc01658..0b68360300 100644 --- a/util/system/env_ut.cpp +++ b/util/system/env_ut.cpp @@ -1,7 +1,7 @@ #include <library/cpp/testing/unittest/registar.h> #include <util/generic/string.h> -#include "env.h" +#include "env.h" Y_UNIT_TEST_SUITE(EnvTest) { Y_UNIT_TEST(GetSetEnvTest) { diff --git a/util/system/err.cpp b/util/system/err.cpp index 5573ea1ee9..9580d7ad5c 100644 --- a/util/system/err.cpp +++ b/util/system/err.cpp @@ -1,79 +1,79 @@ #include "defaults.h" -#include "progname.h" -#include "compat.h" -#include "error.h" +#include "progname.h" +#include "compat.h" +#include "error.h" -#include <util/generic/scope.h> +#include <util/generic/scope.h> -#include <util/stream/printf.h> -#include <util/stream/output.h> +#include <util/stream/printf.h> +#include <util/stream/output.h> -void vwarnx(const char* fmt, va_list args) { - Cerr << GetProgramName() << ": "; +void vwarnx(const char* fmt, va_list args) { + Cerr << GetProgramName() << ": "; - if (fmt) { - Printf(Cerr, fmt, args); - } + if (fmt) { + Printf(Cerr, fmt, args); + } - Cerr << '\n'; -} - -void vwarn(const char* fmt, va_list args) { - int curErrNo = errno; - auto curErrText = LastSystemErrorText(); + Cerr << '\n'; +} - Y_DEFER { - errno = curErrNo; - }; +void vwarn(const char* fmt, va_list args) { + int curErrNo = errno; + auto curErrText = LastSystemErrorText(); - Cerr << GetProgramName() << ": "; + Y_DEFER { + errno = curErrNo; + }; - if (fmt) { - Printf(Cerr, fmt, args); - Cerr << ": "; - } + Cerr << GetProgramName() << ": "; - Cerr << curErrText << '\n'; + if (fmt) { + Printf(Cerr, fmt, args); + Cerr << ": "; + } + + Cerr << curErrText << '\n'; } -void warn(const char* fmt, ...) { - va_list args; +void warn(const char* fmt, ...) { + va_list args; - va_start(args, fmt); - vwarn(fmt, args); - va_end(args); + va_start(args, fmt); + vwarn(fmt, args); + va_end(args); } -void warnx(const char* fmt, ...) { - va_list args; +void warnx(const char* fmt, ...) { + va_list args; - va_start(args, fmt); - vwarnx(fmt, args); - va_end(args); + va_start(args, fmt); + vwarnx(fmt, args); + va_end(args); } -void verr(int status, const char* fmt, va_list args) { - vwarn(fmt, args); - exit(status); +void verr(int status, const char* fmt, va_list args) { + vwarn(fmt, args); + exit(status); } -void err(int status, const char* fmt, ...) { - va_list args; - - va_start(args, fmt); - verr(status, fmt, args); - va_end(args); +void err(int status, const char* fmt, ...) { + va_list args; + + va_start(args, fmt); + verr(status, fmt, args); + va_end(args); } -void verrx(int status, const char* fmt, va_list args) { - vwarnx(fmt, args); - exit(status); +void verrx(int status, const char* fmt, va_list args) { + vwarnx(fmt, args); + exit(status); } -void errx(int status, const char* fmt, ...) { - va_list args; - - va_start(args, fmt); - verrx(status, fmt, args); - va_end(args); +void errx(int status, const char* fmt, ...) { + va_list args; + + va_start(args, fmt); + verrx(status, fmt, args); + va_end(args); } diff --git a/util/system/error.cpp b/util/system/error.cpp index f778ec42cb..6ba2dc64b5 100644 --- a/util/system/error.cpp +++ b/util/system/error.cpp @@ -1,21 +1,21 @@ -#include "tls.h" -#include "error.h" - +#include "tls.h" +#include "error.h" + #include <util/string/strip.h> -#include <util/generic/strfcpy.h> - -#include <cerrno> -#include <cstdio> -#include <cstring> - -#if defined(_win_) - #include <util/network/socket.h> - #include <util/generic/singleton.h> - #include "winint.h" -#elif defined(_unix_) - #include <unistd.h> -#endif - +#include <util/generic/strfcpy.h> + +#include <cerrno> +#include <cstdio> +#include <cstring> + +#if defined(_win_) + #include <util/network/socket.h> + #include <util/generic/singleton.h> + #include "winint.h" +#elif defined(_unix_) + #include <unistd.h> +#endif + void ClearLastSystemError() { #if defined(_win_) SetLastError(0); @@ -24,13 +24,13 @@ void ClearLastSystemError() { #endif } -int LastSystemError() { -#if defined(_win_) +int LastSystemError() { +#if defined(_win_) int ret = GetLastError(); - + if (ret) - return ret; - + return ret; + ret = WSAGetLastError(); if (ret) @@ -39,34 +39,34 @@ int LastSystemError() { ret = *(_errno()); return ret; -#else - return errno; -#endif -} - -#if defined(_win_) -namespace { - struct TErrString { +#else + return errno; +#endif +} + +#if defined(_win_) +namespace { + struct TErrString { inline TErrString() noexcept { - data[0] = 0; - } - - char data[1024]; - }; -} -#endif - -const char* LastSystemErrorText(int code) { -#if defined(_win_) + data[0] = 0; + } + + char data[1024]; + }; +} +#endif + +const char* LastSystemErrorText(int code) { +#if defined(_win_) TErrString& text(*Singleton<TErrString>()); - LastSystemErrorText(text.data, sizeof(text.data), code); - - return text.data; -#else - return strerror(code); -#endif -} - + LastSystemErrorText(text.data, sizeof(text.data), code); + + return text.data; +#else + return strerror(code); +#endif +} + #ifdef _win_ static char* Strip(char* s) { size_t len = strlen(s); @@ -79,18 +79,18 @@ static char* Strip(char* s) { } #endif // _win_ -void LastSystemErrorText(char* str, size_t size, int code) { -#if defined(_win_) - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, code, 0, str, DWORD(size), 0); +void LastSystemErrorText(char* str, size_t size, int code) { +#if defined(_win_) + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, code, 0, str, DWORD(size), 0); Strip(str); -#elif defined(_sun_) +#elif defined(_sun_) strfcpy(str, strerror(code), size); -#elif defined(_freebsd_) || defined(_darwin_) || defined(_musl_) || defined(_bionic_) +#elif defined(_freebsd_) || defined(_darwin_) || defined(_musl_) || defined(_bionic_) strerror_r(code, str, size); -#elif defined(_linux_) | defined(_cygwin_) +#elif defined(_linux_) | defined(_cygwin_) char* msg = strerror_r(code, str, size); strncpy(str, msg, size); -#else - #error port me gently! -#endif -} +#else + #error port me gently! +#endif +} diff --git a/util/system/error.h b/util/system/error.h index 5f2d4cc547..610276b90a 100644 --- a/util/system/error.h +++ b/util/system/error.h @@ -1,95 +1,95 @@ #pragma once - + #include "defaults.h" + +#if defined(_win_) + #include <winerror.h> + #include <errno.h> + + #undef E_FAIL + #undef ERROR_TIMEOUT + + #if defined(_MSC_VER) + #undef EADDRINUSE + #undef EADDRNOTAVAIL + #undef EAFNOSUPPORT + #undef EALREADY + #undef ECANCELED + #undef ECONNABORTED + #undef ECONNREFUSED + #undef ECONNRESET + #undef EDESTADDRREQ + #undef EHOSTUNREACH + #undef EINPROGRESS + #undef EISCONN + #undef ELOOP + #undef EMSGSIZE + #undef ENETDOWN + #undef ENETRESET + #undef ENETUNREACH + #undef ENOBUFS + #undef ENOPROTOOPT + #undef ENOTCONN + #undef ENOTSOCK + #undef EOPNOTSUPP + #undef EPROTONOSUPPORT + #undef EPROTOTYPE + #undef ETIMEDOUT + #undef EWOULDBLOCK + #undef ENAMETOOLONG + #undef ENOTEMPTY -#if defined(_win_) - #include <winerror.h> - #include <errno.h> - - #undef E_FAIL - #undef ERROR_TIMEOUT - - #if defined(_MSC_VER) - #undef EADDRINUSE - #undef EADDRNOTAVAIL - #undef EAFNOSUPPORT - #undef EALREADY - #undef ECANCELED - #undef ECONNABORTED - #undef ECONNREFUSED - #undef ECONNRESET - #undef EDESTADDRREQ - #undef EHOSTUNREACH - #undef EINPROGRESS - #undef EISCONN - #undef ELOOP - #undef EMSGSIZE - #undef ENETDOWN - #undef ENETRESET - #undef ENETUNREACH - #undef ENOBUFS - #undef ENOPROTOOPT - #undef ENOTCONN - #undef ENOTSOCK - #undef EOPNOTSUPP - #undef EPROTONOSUPPORT - #undef EPROTOTYPE - #undef ETIMEDOUT - #undef EWOULDBLOCK - #undef ENAMETOOLONG - #undef ENOTEMPTY - - #define EWOULDBLOCK WSAEWOULDBLOCK - #define EINPROGRESS WSAEINPROGRESS - #define EALREADY WSAEALREADY - #define ENOTSOCK WSAENOTSOCK - #define EDESTADDRREQ WSAEDESTADDRREQ - #define EMSGSIZE WSAEMSGSIZE - #define EPROTOTYPE WSAEPROTOTYPE - #define ENOPROTOOPT WSAENOPROTOOPT - #define EPROTONOSUPPORT WSAEPROTONOSUPPORT - #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT - #define EOPNOTSUPP WSAEOPNOTSUPP - #define EPFNOSUPPORT WSAEPFNOSUPPORT - #define EAFNOSUPPORT WSAEAFNOSUPPORT - #define EADDRINUSE WSAEADDRINUSE - #define EADDRNOTAVAIL WSAEADDRNOTAVAIL - #define ENETDOWN WSAENETDOWN - #define ENETUNREACH WSAENETUNREACH - #define ENETRESET WSAENETRESET - #define ECONNABORTED WSAECONNABORTED - #define ECONNRESET WSAECONNRESET - #define ENOBUFS WSAENOBUFS - #define EISCONN WSAEISCONN - #define ENOTCONN WSAENOTCONN - #define ESHUTDOWN WSAESHUTDOWN - #define ETOOMANYREFS WSAETOOMANYREFS - #define ETIMEDOUT WSAETIMEDOUT - #define ECONNREFUSED WSAECONNREFUSED - #define ELOOP WSAELOOP - #define ENAMETOOLONG WSAENAMETOOLONG - #define EHOSTDOWN WSAEHOSTDOWN - #define EHOSTUNREACH WSAEHOSTUNREACH - #define ENOTEMPTY WSAENOTEMPTY - #define EPROCLIM WSAEPROCLIM - #define EUSERS WSAEUSERS - #define ESTALE WSAESTALE - #define EREMOTE WSAEREMOTE - #define ECANCELED WSAECANCELLED - #endif - - #define EDQUOT WSAEDQUOT -#endif - + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EINPROGRESS WSAEINPROGRESS + #define EALREADY WSAEALREADY + #define ENOTSOCK WSAENOTSOCK + #define EDESTADDRREQ WSAEDESTADDRREQ + #define EMSGSIZE WSAEMSGSIZE + #define EPROTOTYPE WSAEPROTOTYPE + #define ENOPROTOOPT WSAENOPROTOOPT + #define EPROTONOSUPPORT WSAEPROTONOSUPPORT + #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT + #define EOPNOTSUPP WSAEOPNOTSUPP + #define EPFNOSUPPORT WSAEPFNOSUPPORT + #define EAFNOSUPPORT WSAEAFNOSUPPORT + #define EADDRINUSE WSAEADDRINUSE + #define EADDRNOTAVAIL WSAEADDRNOTAVAIL + #define ENETDOWN WSAENETDOWN + #define ENETUNREACH WSAENETUNREACH + #define ENETRESET WSAENETRESET + #define ECONNABORTED WSAECONNABORTED + #define ECONNRESET WSAECONNRESET + #define ENOBUFS WSAENOBUFS + #define EISCONN WSAEISCONN + #define ENOTCONN WSAENOTCONN + #define ESHUTDOWN WSAESHUTDOWN + #define ETOOMANYREFS WSAETOOMANYREFS + #define ETIMEDOUT WSAETIMEDOUT + #define ECONNREFUSED WSAECONNREFUSED + #define ELOOP WSAELOOP + #define ENAMETOOLONG WSAENAMETOOLONG + #define EHOSTDOWN WSAEHOSTDOWN + #define EHOSTUNREACH WSAEHOSTUNREACH + #define ENOTEMPTY WSAENOTEMPTY + #define EPROCLIM WSAEPROCLIM + #define EUSERS WSAEUSERS + #define ESTALE WSAESTALE + #define EREMOTE WSAEREMOTE + #define ECANCELED WSAECANCELLED + #endif + + #define EDQUOT WSAEDQUOT +#endif + void ClearLastSystemError(); -int LastSystemError(); -void LastSystemErrorText(char* str, size_t size, int code); -const char* LastSystemErrorText(int code); - -inline const char* LastSystemErrorText() { - return LastSystemErrorText(LastSystemError()); -} - -inline void LastSystemErrorText(char* str, size_t size) { - LastSystemErrorText(str, size, LastSystemError()); -} +int LastSystemError(); +void LastSystemErrorText(char* str, size_t size, int code); +const char* LastSystemErrorText(int code); + +inline const char* LastSystemErrorText() { + return LastSystemErrorText(LastSystemError()); +} + +inline void LastSystemErrorText(char* str, size_t size) { + LastSystemErrorText(str, size, LastSystemError()); +} diff --git a/util/system/error_ut.cpp b/util/system/error_ut.cpp index 763b0dddb7..0370ddaea9 100644 --- a/util/system/error_ut.cpp +++ b/util/system/error_ut.cpp @@ -1,41 +1,41 @@ -#include "error.h" - +#include "error.h" + #include <library/cpp/testing/unittest/registar.h> - + #include <util/generic/ylimits.h> - + #ifdef _win_ - #include "winint.h" + #include "winint.h" #else - #include <fcntl.h> + #include <fcntl.h> #endif -class TSysErrorTest: public TTestBase { - UNIT_TEST_SUITE(TSysErrorTest); - UNIT_TEST(TestErrorCode) - UNIT_TEST(TestErrorMessage) - UNIT_TEST_SUITE_END(); - -private: - inline void TestErrorCode() { - GenFailure(); - - UNIT_ASSERT(LastSystemError() != 0); - } - - inline void TestErrorMessage() { - GenFailure(); - - UNIT_ASSERT(*LastSystemErrorText() != 0); - } - - inline void GenFailure() { +class TSysErrorTest: public TTestBase { + UNIT_TEST_SUITE(TSysErrorTest); + UNIT_TEST(TestErrorCode) + UNIT_TEST(TestErrorMessage) + UNIT_TEST_SUITE_END(); + +private: + inline void TestErrorCode() { + GenFailure(); + + UNIT_ASSERT(LastSystemError() != 0); + } + + inline void TestErrorMessage() { + GenFailure(); + + UNIT_ASSERT(*LastSystemErrorText() != 0); + } + + inline void GenFailure() { #ifdef _win_ - SetLastError(3); + SetLastError(3); #else - UNIT_ASSERT(open("/non-existent", O_RDONLY) < 0); + UNIT_ASSERT(open("/non-existent", O_RDONLY) < 0); #endif - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TSysErrorTest); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TSysErrorTest); diff --git a/util/system/event.cpp b/util/system/event.cpp index 79b3cdb291..3d4780ea10 100644 --- a/util/system/event.cpp +++ b/util/system/event.cpp @@ -1,114 +1,114 @@ #include "datetime.h" #include "defaults.h" - -#include <cstdio> - + +#include <cstdio> + #include "atomic.h" -#include "event.h" -#include "mutex.h" -#include "condvar.h" +#include "event.h" +#include "mutex.h" +#include "condvar.h" #ifdef _win_ - #include "winint.h" -#endif - + #include "winint.h" +#endif + class TSystemEvent::TEvImpl: public TAtomicRefCount<TSystemEvent::TEvImpl> { -public: -#ifdef _win_ - inline TEvImpl(ResetMode rmode) { +public: +#ifdef _win_ + inline TEvImpl(ResetMode rmode) { cond = CreateEvent(nullptr, rmode == rManual ? true : false, false, nullptr); - } - + } + inline ~TEvImpl() { - CloseHandle(cond); - } - + CloseHandle(cond); + } + inline void Reset() noexcept { - ResetEvent(cond); - } - + ResetEvent(cond); + } + inline void Signal() noexcept { - SetEvent(cond); - } - + SetEvent(cond); + } + inline bool WaitD(TInstant deadLine) noexcept { - if (deadLine == TInstant::Max()) { - return WaitForSingleObject(cond, INFINITE) == WAIT_OBJECT_0; - } - - const TInstant now = Now(); - - if (now < deadLine) { - //TODO - return WaitForSingleObject(cond, (deadLine - now).MilliSeconds()) == WAIT_OBJECT_0; - } - + if (deadLine == TInstant::Max()) { + return WaitForSingleObject(cond, INFINITE) == WAIT_OBJECT_0; + } + + const TInstant now = Now(); + + if (now < deadLine) { + //TODO + return WaitForSingleObject(cond, (deadLine - now).MilliSeconds()) == WAIT_OBJECT_0; + } + return (WaitForSingleObject(cond, 0) == WAIT_OBJECT_0); - } -#else - inline TEvImpl(ResetMode rmode) + } +#else + inline TEvImpl(ResetMode rmode) : Manual(rmode == rManual ? true : false) - { - } - + { + } + inline void Signal() noexcept { if (Manual && AtomicGet(Signaled)) { - return; // shortcut - } - - with_lock (Mutex) { + return; // shortcut + } + + with_lock (Mutex) { AtomicSet(Signaled, 1); - } - - if (Manual) { - Cond.BroadCast(); - } else { - Cond.Signal(); - } - } + } + + if (Manual) { + Cond.BroadCast(); + } else { + Cond.Signal(); + } + } inline void Reset() noexcept { AtomicSet(Signaled, 0); - } - + } + inline bool WaitD(TInstant deadLine) noexcept { if (Manual && AtomicGet(Signaled)) { - return true; // shortcut - } - - bool resSignaled = true; - - with_lock (Mutex) { + return true; // shortcut + } + + bool resSignaled = true; + + with_lock (Mutex) { while (!AtomicGet(Signaled)) { - if (!Cond.WaitD(Mutex, deadLine)) { + if (!Cond.WaitD(Mutex, deadLine)) { resSignaled = AtomicGet(Signaled); // timed out, but Signaled could have been set - - break; - } - } - - if (!Manual) { + + break; + } + } + + if (!Manual) { AtomicSet(Signaled, 0); - } - } - - return resSignaled; - } -#endif - -private: -#ifdef _win_ - HANDLE cond; -#else - TCondVar Cond; - TMutex Mutex; + } + } + + return resSignaled; + } +#endif + +private: +#ifdef _win_ + HANDLE cond; +#else + TCondVar Cond; + TMutex Mutex; TAtomic Signaled = 0; - bool Manual; -#endif -}; - + bool Manual; +#endif +}; + TSystemEvent::TSystemEvent(ResetMode rmode) - : EvImpl_(new TEvImpl(rmode)) + : EvImpl_(new TEvImpl(rmode)) { } @@ -125,13 +125,13 @@ TSystemEvent& TSystemEvent::operator=(const TSystemEvent& other) noexcept { TSystemEvent::~TSystemEvent() = default; void TSystemEvent::Reset() noexcept { - EvImpl_->Reset(); + EvImpl_->Reset(); } void TSystemEvent::Signal() noexcept { - EvImpl_->Signal(); + EvImpl_->Signal(); } bool TSystemEvent::WaitD(TInstant deadLine) noexcept { - return EvImpl_->WaitD(deadLine); -} + return EvImpl_->WaitD(deadLine); +} diff --git a/util/system/event.h b/util/system/event.h index cab2fc478a..05aadb2cef 100644 --- a/util/system/event.h +++ b/util/system/event.h @@ -4,17 +4,17 @@ #include <util/datetime/base.h> struct TEventResetType { - enum ResetMode { - rAuto, // the state will be nonsignaled after Wait() returns - rManual, // we need call Reset() to set the state to nonsignaled. - }; + enum ResetMode { + rAuto, // the state will be nonsignaled after Wait() returns + rManual, // we need call Reset() to set the state to nonsignaled. + }; }; /** * DEPRECATED! * * Use TAutoEvent, TManualEvent for the direct replacement. - * Use TManualEvent to prevent SEGFAULT (http://nga.at.yandex-team.ru/5772). + * Use TManualEvent to prevent SEGFAULT (http://nga.at.yandex-team.ru/5772). */ class TSystemEvent: public TEventResetType { public: @@ -27,40 +27,40 @@ public: void Reset() noexcept; void Signal() noexcept; - /* - * return true if signaled, false if timed out. - */ + /* + * return true if signaled, false if timed out. + */ bool WaitD(TInstant deadLine) noexcept; - - /* - * return true if signaled, false if timed out. - */ + + /* + * return true if signaled, false if timed out. + */ inline bool WaitT(TDuration timeOut) noexcept { - return WaitD(timeOut.ToDeadLine()); - } - - /* - * wait infinite time - */ + return WaitD(timeOut.ToDeadLine()); + } + + /* + * wait infinite time + */ inline void WaitI() noexcept { - WaitD(TInstant::Max()); - } - - //return true if signaled, false if timed out. + WaitD(TInstant::Max()); + } + + //return true if signaled, false if timed out. inline bool Wait(ui32 timer) noexcept { - return WaitT(TDuration::MilliSeconds(timer)); - } - + return WaitT(TDuration::MilliSeconds(timer)); + } + inline bool Wait() noexcept { - WaitI(); - - return true; - } - -private: - class TEvImpl; + WaitI(); + + return true; + } + +private: + class TEvImpl; TIntrusivePtr<TEvImpl> EvImpl_; -}; +}; class TAutoEvent: public TSystemEvent { public: diff --git a/util/system/event_ut.cpp b/util/system/event_ut.cpp index 2506cb7a91..4c2bfe4eb2 100644 --- a/util/system/event_ut.cpp +++ b/util/system/event_ut.cpp @@ -1,6 +1,6 @@ -#include "event.h" -#include "atomic.h" - +#include "event.h" +#include "atomic.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/thread/pool.h> @@ -13,42 +13,42 @@ namespace { { } - TAtomic Counter; + TAtomic Counter; TManualEvent event; bool failed; }; - struct TThreadTask: public IObjectInQueue { - public: - TThreadTask(TSharedData& data, size_t id) - : Data_(data) - , Id_(id) - { - } + struct TThreadTask: public IObjectInQueue { + public: + TThreadTask(TSharedData& data, size_t id) + : Data_(data) + , Id_(id) + { + } void Process(void*) override { - THolder<TThreadTask> This(this); - - if (Id_ == 0) { - usleep(100); + THolder<TThreadTask> This(this); + + if (Id_ == 0) { + usleep(100); bool cond = Data_.Counter == 0; if (!cond) { Data_.failed = true; } - Data_.event.Signal(); - } else { - while (!Data_.event.WaitT(TDuration::Seconds(100))) { + Data_.event.Signal(); + } else { + while (!Data_.event.WaitT(TDuration::Seconds(100))) { } - AtomicAdd(Data_.Counter, Id_); + AtomicAdd(Data_.Counter, Id_); } - } + } - private: - TSharedData& Data_; - size_t Id_; + private: + TSharedData& Data_; + size_t Id_; }; - class TSignalTask: public IObjectInQueue { + class TSignalTask: public IObjectInQueue { private: TManualEvent& Ev_; @@ -63,7 +63,7 @@ namespace { } }; - class TOwnerTask: public IObjectInQueue { + class TOwnerTask: public IObjectInQueue { public: TManualEvent Barrier; THolder<TManualEvent> Ev; @@ -80,20 +80,20 @@ namespace { } }; -} +} Y_UNIT_TEST_SUITE(EventTest) { Y_UNIT_TEST(WaitAndSignalTest) { TSharedData data; TThreadPool queue; queue.Start(5); - for (size_t i = 0; i < 5; ++i) { + for (size_t i = 0; i < 5; ++i) { UNIT_ASSERT(queue.Add(new TThreadTask(data, i))); } queue.Stop(); UNIT_ASSERT(data.Counter == 10); UNIT_ASSERT(!data.failed); - } + } Y_UNIT_TEST(ConcurrentSignalAndWaitTest) { // test for problem detected by thread-sanitizer (signal/wait race) SEARCH-2113 @@ -114,7 +114,7 @@ Y_UNIT_TEST_SUITE(EventTest) { /** Test for a problem: http://nga.at.yandex-team.ru/5772 */ Y_UNIT_TEST(DestructorBeforeSignalFinishTest) { - return; + return; TVector<THolder<IObjectInQueue>> tasks; for (size_t i = 0; i < 1000; ++i) { auto owner = MakeHolder<TOwnerTask>(); @@ -123,7 +123,7 @@ Y_UNIT_TEST_SUITE(EventTest) { } TThreadPool queue; - queue.Start(4); + queue.Start(4); for (auto& task : tasks) { UNIT_ASSERT(queue.Add(task.Get())); } diff --git a/util/system/execpath.cpp b/util/system/execpath.cpp index 33198af58b..10a8ab0818 100644 --- a/util/system/execpath.cpp +++ b/util/system/execpath.cpp @@ -1,41 +1,41 @@ -#include "platform.h" - -#include <stdlib.h> - +#include "platform.h" + +#include <stdlib.h> + #if defined(_solaris_) - #include <stdlib.h> + #include <stdlib.h> #elif defined(_darwin_) - #include <mach-o/dyld.h> + #include <mach-o/dyld.h> #elif defined(_win_) - #include "winint.h" - #include <io.h> + #include "winint.h" + #include <io.h> #elif defined(_linux_) - #include <unistd.h> + #include <unistd.h> #elif defined(_freebsd_) - #include <string.h> - #include <sys/types.h> // for u_int not defined in sysctl.h - #include <sys/sysctl.h> - #include <unistd.h> + #include <string.h> + #include <sys/types.h> // for u_int not defined in sysctl.h + #include <sys/sysctl.h> + #include <unistd.h> #endif #include <util/folder/dirut.h> #include <util/generic/singleton.h> -#include <util/generic/function.h> +#include <util/generic/function.h> #include <util/generic/yexception.h> #include <util/memory/tempbuf.h> -#include <util/stream/file.h> -#include <util/stream/pipe.h> -#include <util/string/cast.h> - -#include "filemap.h" +#include <util/stream/file.h> +#include <util/stream/pipe.h> +#include <util/string/cast.h> + +#include "filemap.h" #include "execpath.h" #include "fs.h" -#if defined(_freebsd_) +#if defined(_freebsd_) static inline bool GoodPath(const TString& path) { return path.find('/') != TString::npos; -} - +} + static inline int FreeBSDSysCtl(int* mib, size_t mibSize, TTempBuf& res) { for (size_t i = 0; i < 2; ++i) { size_t cb = res.Size(); @@ -47,12 +47,12 @@ static inline int FreeBSDSysCtl(int* mib, size_t mibSize, TTempBuf& res) { } else { return errno; } - } + } return errno; -} - +} + static inline TString FreeBSDGetExecPath() { - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; TTempBuf buf; int r = FreeBSDSysCtl(mib, Y_ARRAY_SIZE(mib), buf); if (r == 0) { @@ -67,12 +67,12 @@ static inline TString FreeBSDGetExecPath() { return NFs::ReadLink(path); } else { return TString(); - } -} - + } +} + static inline TString FreeBSDGetArgv0() { - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, getpid()}; - TTempBuf buf; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, getpid()}; + TTempBuf buf; int r = FreeBSDSysCtl(mib, Y_ARRAY_SIZE(mib), buf); if (r == 0) { return TString(buf.Data()); @@ -81,8 +81,8 @@ static inline TString FreeBSDGetArgv0() { } else { ythrow yexception() << "FreeBSDGetArgv0() failed: " << LastSystemErrorText(); } -} - +} + static inline bool FreeBSDGuessExecPath(const TString& guessPath, TString& execPath) { if (NFs::Exists(guessPath)) { // now it should work for real @@ -98,15 +98,15 @@ static inline bool FreeBSDGuessExecBasePath(const TString& guessBasePath, TStrin return FreeBSDGuessExecPath(TString(guessBasePath) + "/" + getprogname(), execPath); } -#endif - +#endif + static TString GetExecPathImpl() { #if defined(_solaris_) return execname(); #elif defined(_darwin_) TTempBuf execNameBuf; for (size_t i = 0; i < 2; ++i) { - std::remove_pointer_t<TFunctionArg<decltype(_NSGetExecutablePath), 1>> bufsize = execNameBuf.Size(); + std::remove_pointer_t<TFunctionArg<decltype(_NSGetExecutablePath), 1>> bufsize = execNameBuf.Size(); int r = _NSGetExecutablePath(execNameBuf.Data(), &bufsize); if (r == 0) { return execNameBuf.Data(); @@ -127,10 +127,10 @@ static TString GetExecPathImpl() { return execNameBuf.Data(); } } -#elif defined(_linux_) || defined(_cygwin_) +#elif defined(_linux_) || defined(_cygwin_) TString path("/proc/self/exe"); return NFs::ReadLink(path); -// TODO(yoda): check if the filename ends with " (deleted)" +// TODO(yoda): check if the filename ends with " (deleted)" #elif defined(_freebsd_) TString execPath = FreeBSDGetExecPath(); if (GoodPath(execPath)) { @@ -151,49 +151,49 @@ static TString GetExecPathImpl() { ythrow yexception() << "can not resolve exec path"; #else - #error dont know how to implement GetExecPath on this platform + #error dont know how to implement GetExecPath on this platform #endif } -static bool GetPersistentExecPathImpl(TString& to) { +static bool GetPersistentExecPathImpl(TString& to) { #if defined(_solaris_) - to = TString("/proc/self/object/a.out"); + to = TString("/proc/self/object/a.out"); return true; #elif defined(_linux_) || defined(_cygwin_) - to = TString("/proc/self/exe"); + to = TString("/proc/self/exe"); return true; #elif defined(_freebsd_) - to = TString("/proc/curproc/file"); + to = TString("/proc/curproc/file"); return true; #else // defined(_win_) || defined(_darwin_) or unknown Y_UNUSED(to); - return false; + return false; #endif } -namespace { +namespace { struct TExecPathsHolder { inline TExecPathsHolder() { - ExecPath = GetExecPathImpl(); - - if (!GetPersistentExecPathImpl(PersistentExecPath)) { - PersistentExecPath = ExecPath; - } - } - - static inline auto Instance() { - return SingletonWithPriority<TExecPathsHolder, 1>(); - } - + ExecPath = GetExecPathImpl(); + + if (!GetPersistentExecPathImpl(PersistentExecPath)) { + PersistentExecPath = ExecPath; + } + } + + static inline auto Instance() { + return SingletonWithPriority<TExecPathsHolder, 1>(); + } + TString ExecPath; TString PersistentExecPath; - }; -} + }; +} const TString& GetExecPath() { - return TExecPathsHolder::Instance()->ExecPath; + return TExecPathsHolder::Instance()->ExecPath; } const TString& GetPersistentExecPath() { - return TExecPathsHolder::Instance()->PersistentExecPath; + return TExecPathsHolder::Instance()->PersistentExecPath; } diff --git a/util/system/execpath_ut.cpp b/util/system/execpath_ut.cpp index 16b01466f5..2b5d8da888 100644 --- a/util/system/execpath_ut.cpp +++ b/util/system/execpath_ut.cpp @@ -1,22 +1,22 @@ #include "execpath.h" - + #include <library/cpp/testing/unittest/registar.h> - -#include "platform.h" + +#include "platform.h" #include <util/folder/dirut.h> Y_UNIT_TEST_SUITE(TExecPathTest) { Y_UNIT_TEST(TestIt) { TString execPath = GetExecPath(); TString persistentExecPath = GetPersistentExecPath(); - - try { + + try { UNIT_ASSERT(NFs::Exists(execPath)); UNIT_ASSERT(NFs::Exists(persistentExecPath)); - } catch (...) { + } catch (...) { Cerr << execPath << Endl; - - throw; - } + + throw; + } } } diff --git a/util/system/fasttime.cpp b/util/system/fasttime.cpp index 057a814f0a..33f56edd95 100644 --- a/util/system/fasttime.cpp +++ b/util/system/fasttime.cpp @@ -1,29 +1,29 @@ -#include "dynlib.h" -#include "fasttime.h" +#include "dynlib.h" +#include "fasttime.h" #include <util/generic/singleton.h> #include <util/generic/yexception.h> #include <utility> - + #include <util/thread/singleton.h> -#if defined(_win_) || defined(_arm32_) || defined(_cygwin_) +#if defined(_win_) || defined(_arm32_) || defined(_cygwin_) ui64 InterpolatedMicroSeconds() { return MicroSeconds(); } #else - #include <dlfcn.h> - #include <sys/time.h> - - #if defined(_musl_) - #include <util/generic/hash.h> - #include <util/generic/vector.h> - #include <util/generic/string.h> - - #include <contrib/libs/linuxvdso/interface.h> - #endif - + #include <dlfcn.h> + #include <sys/time.h> + + #if defined(_musl_) + #include <util/generic/hash.h> + #include <util/generic/vector.h> + #include <util/generic/string.h> + + #include <contrib/libs/linuxvdso/interface.h> + #endif + namespace { using TTime = ui64; @@ -36,13 +36,13 @@ namespace { // not DEFAULT, cause library/cpp/gettimeofday Func = reinterpret_cast<TFunc>(dlsym(RTLD_NEXT, "gettimeofday")); - #if defined(_musl_) + #if defined(_musl_) if (!Func) { Func = reinterpret_cast<TFunc>(NVdso::Function("__vdso_gettimeofday", "LINUX_2.6")); - } - #endif - - if (!Func) { + } + #endif + + if (!Func) { Func = reinterpret_cast<TFunc>(Libc()->Sym("gettimeofday")); } } @@ -59,16 +59,16 @@ namespace { static inline THolder<TDynamicLibrary> OpenLibc() { const char* libs[] = { - "/lib/libc.so.8", - "/lib/libc.so.7", - "/lib/libc.so.6", - }; + "/lib/libc.so.8", + "/lib/libc.so.7", + "/lib/libc.so.6", + }; for (auto& lib : libs) { try { return MakeHolder<TDynamicLibrary>(lib); } catch (...) { - // ¯\_(ツ)_/¯ + // ¯\_(ツ)_/¯ } } @@ -179,7 +179,7 @@ namespace { } B_ = (n * sxy - sx * sy) / (n * sxx - sx * sx); - A_ = (sy - B_ * sx) / n; + A_ = (sy - B_ * sx) / n; } private: diff --git a/util/system/fhandle.cpp b/util/system/fhandle.cpp index 67250ae1e5..51b8d659d1 100644 --- a/util/system/fhandle.cpp +++ b/util/system/fhandle.cpp @@ -1 +1 @@ -#include "fhandle.h" +#include "fhandle.h" diff --git a/util/system/fhandle.h b/util/system/fhandle.h index f8033e3c14..3290839f87 100644 --- a/util/system/fhandle.h +++ b/util/system/fhandle.h @@ -2,26 +2,26 @@ #include "defaults.h" -using WIN_HANDLE = void*; -#define INVALID_WIN_HANDLE ((WIN_HANDLE)(long)-1) - -using UNIX_HANDLE = int; -#define INVALID_UNIX_HANDLE -1 - +using WIN_HANDLE = void*; +#define INVALID_WIN_HANDLE ((WIN_HANDLE)(long)-1) + +using UNIX_HANDLE = int; +#define INVALID_UNIX_HANDLE -1 + #if defined(_win_) -using FHANDLE = WIN_HANDLE; - #define INVALID_FHANDLE INVALID_WIN_HANDLE +using FHANDLE = WIN_HANDLE; + #define INVALID_FHANDLE INVALID_WIN_HANDLE #elif defined(_unix_) -using FHANDLE = UNIX_HANDLE; - #define INVALID_FHANDLE INVALID_UNIX_HANDLE -#else - #error -#endif - -#if defined(_cygwin_) -using OS_HANDLE = WIN_HANDLE; - #define INVALID_OS_HANDLE INVALID_WIN_HANDLE +using FHANDLE = UNIX_HANDLE; + #define INVALID_FHANDLE INVALID_UNIX_HANDLE #else -using OS_HANDLE = FHANDLE; - #define INVALID_OS_HANDLE INVALID_FHANDLE + #error #endif + +#if defined(_cygwin_) +using OS_HANDLE = WIN_HANDLE; + #define INVALID_OS_HANDLE INVALID_WIN_HANDLE +#else +using OS_HANDLE = FHANDLE; + #define INVALID_OS_HANDLE INVALID_FHANDLE +#endif diff --git a/util/system/file.cpp b/util/system/file.cpp index 4a261d020c..3e5c7be9b3 100644 --- a/util/system/file.cpp +++ b/util/system/file.cpp @@ -1,66 +1,66 @@ -#include "file.h" -#include "flock.h" -#include "fstat.h" -#include "sysstat.h" +#include "file.h" +#include "flock.h" +#include "fstat.h" +#include "sysstat.h" #include "align.h" #include "info.h" - + #include <array> -#include <util/string/util.h> -#include <util/string/cast.h> -#include <util/string/builder.h> - -#include <util/stream/hex.h> -#include <util/stream/format.h> - -#include <util/random/random.h> - +#include <util/string/util.h> +#include <util/string/cast.h> +#include <util/string/builder.h> + +#include <util/stream/hex.h> +#include <util/stream/format.h> + +#include <util/random/random.h> + #include <util/generic/size_literals.h> #include <util/generic/string.h> #include <util/generic/ylimits.h> -#include <util/generic/yexception.h> - -#include <util/datetime/base.h> - -#include <errno.h> +#include <util/generic/yexception.h> + +#include <util/datetime/base.h> +#include <errno.h> + #if defined(_unix_) - #include <fcntl.h> + #include <fcntl.h> - #if defined(_linux_) && (!defined(_android_) || __ANDROID_API__ >= 21) && !defined(FALLOC_FL_KEEP_SIZE) - #include <linux/falloc.h> - #endif + #if defined(_linux_) && (!defined(_android_) || __ANDROID_API__ >= 21) && !defined(FALLOC_FL_KEEP_SIZE) + #include <linux/falloc.h> + #endif - #include <stdlib.h> - #include <unistd.h> - #include <sys/mman.h> + #include <stdlib.h> + #include <unistd.h> + #include <sys/mman.h> #elif defined(_win_) - #include "winint.h" - #include "fs_win.h" - #include <io.h> + #include "winint.h" + #include "fs_win.h" + #include <io.h> #endif -#if defined(_bionic_) - #include <sys/sendfile.h> - #define HAVE_POSIX_FADVISE 0 - #define HAVE_SYNC_FILE_RANGE 0 -#elif defined(_linux_) - #include <sys/sendfile.h> - #define HAVE_POSIX_FADVISE 1 - #define HAVE_SYNC_FILE_RANGE 1 +#if defined(_bionic_) + #include <sys/sendfile.h> + #define HAVE_POSIX_FADVISE 0 + #define HAVE_SYNC_FILE_RANGE 0 +#elif defined(_linux_) + #include <sys/sendfile.h> + #define HAVE_POSIX_FADVISE 1 + #define HAVE_SYNC_FILE_RANGE 1 #elif defined(__FreeBSD__) && !defined(WITH_VALGRIND) - #include <sys/param.h> - #define HAVE_POSIX_FADVISE (__FreeBSD_version >= 900501) - #define HAVE_SYNC_FILE_RANGE 0 + #include <sys/param.h> + #define HAVE_POSIX_FADVISE (__FreeBSD_version >= 900501) + #define HAVE_SYNC_FILE_RANGE 0 #else - #define HAVE_POSIX_FADVISE 0 - #define HAVE_SYNC_FILE_RANGE 0 + #define HAVE_POSIX_FADVISE 0 + #define HAVE_SYNC_FILE_RANGE 0 #endif static bool IsStupidFlagCombination(EOpenMode oMode) { // ForAppend will actually not be applied in the following combinations: - return (oMode & (CreateAlways | ForAppend)) == (CreateAlways | ForAppend) || (oMode & (TruncExisting | ForAppend)) == (TruncExisting | ForAppend) || (oMode & (CreateNew | ForAppend)) == (CreateNew | ForAppend); + return (oMode & (CreateAlways | ForAppend)) == (CreateAlways | ForAppend) || (oMode & (TruncExisting | ForAppend)) == (TruncExisting | ForAppend) || (oMode & (CreateNew | ForAppend)) == (CreateNew | ForAppend); } TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { @@ -107,7 +107,7 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { } if (oMode & ::ForAppend) { faMode |= GENERIC_WRITE; - faMode |= FILE_APPEND_DATA; + faMode |= FILE_APPEND_DATA; faMode &= ~FILE_WRITE_DATA; } @@ -127,7 +127,7 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { attrMode |= FILE_ATTRIBUTE_TEMPORARY; } if (oMode & Transient) { - attrMode |= FILE_FLAG_DELETE_ON_CLOSE; + attrMode |= FILE_FLAG_DELETE_ON_CLOSE; } if ((oMode & (Direct | DirectAligned)) && (oMode & WrOnly)) { // WrOnly or RdWr @@ -137,7 +137,7 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { Fd_ = NFsPrivate::CreateFileWithUtf8Name(fName, faMode, shMode, fcMode, attrMode, inheritHandle); if ((oMode & ::ForAppend) && (Fd_ != INVALID_FHANDLE)) { - ::SetFilePointer(Fd_, 0, 0, FILE_END); + ::SetFilePointer(Fd_, 0, 0, FILE_END); } #elif defined(_unix_) @@ -172,18 +172,18 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { } if (oMode & ::ForAppend) { - fcMode |= O_APPEND; - } - + fcMode |= O_APPEND; + } + if (oMode & CloseOnExec) { fcMode |= O_CLOEXEC; } - /* I don't now about this for unix... + /* I don't now about this for unix... if (oMode & Temp) { } */ - #if defined(_freebsd_) + #if defined(_freebsd_) if (oMode & (Direct | DirectAligned)) { fcMode |= O_DIRECT; } @@ -191,7 +191,7 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { if (oMode & Sync) { fcMode |= O_SYNC; } - #elif defined(_linux_) + #elif defined(_linux_) if (oMode & DirectAligned) { /* * O_DIRECT in Linux requires aligning request size and buffer address @@ -203,12 +203,12 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { if (oMode & Sync) { fcMode |= O_SYNC; } - #endif - - #if defined(_linux_) - fcMode |= O_LARGEFILE; - #endif + #endif + #if defined(_linux_) + fcMode |= O_LARGEFILE; + #endif + ui32 permMode = 0; if (oMode & AXOther) { permMode |= S_IXOTH; @@ -241,14 +241,14 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { do { Fd_ = ::open(fName.data(), fcMode, permMode); } while (Fd_ == -1 && errno == EINTR); - - #if HAVE_POSIX_FADVISE - if (Fd_ >= 0) { - if (oMode & NoReuse) { + + #if HAVE_POSIX_FADVISE + if (Fd_ >= 0) { + if (oMode & NoReuse) { ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_NOREUSE); } - - if (oMode & Seq) { + + if (oMode & Seq) { ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_SEQUENTIAL); } @@ -256,14 +256,14 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept { ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_RANDOM); } } - #endif + #endif - //temp file + //temp file if (Fd_ >= 0 && (oMode & Transient)) { unlink(fName.data()); - } + } #else - #error unsupported platform + #error unsupported platform #endif } @@ -271,26 +271,26 @@ bool TFileHandle::Close() noexcept { bool isOk = true; #ifdef _win_ if (Fd_ != INVALID_FHANDLE) { - isOk = (::CloseHandle(Fd_) != 0); + isOk = (::CloseHandle(Fd_) != 0); } - if (!isOk) { + if (!isOk) { Y_VERIFY(GetLastError() != ERROR_INVALID_HANDLE, "must not quietly close invalid handle"); - } + } #elif defined(_unix_) if (Fd_ != INVALID_FHANDLE) { isOk = (::close(Fd_) == 0 || errno == EINTR); } - if (!isOk) { - // Do not quietly close bad descriptor, - // because often it means double close - // that is disasterous + if (!isOk) { + // Do not quietly close bad descriptor, + // because often it means double close + // that is disasterous Y_VERIFY(errno != EBADF, "must not quietly close bad descriptor: fd=%d", int(Fd_)); - } + } #else - #error unsupported platform + #error unsupported platform #endif - Fd_ = INVALID_FHANDLE; + Fd_ = INVALID_FHANDLE; return isOk; } @@ -298,7 +298,7 @@ static inline i64 DoSeek(FHANDLE h, i64 offset, SeekDir origin) noexcept { if (h == INVALID_FHANDLE) { return -1L; } -#if defined(_win_) +#if defined(_win_) static ui32 dir[] = {FILE_BEGIN, FILE_CURRENT, FILE_END}; LARGE_INTEGER pos; pos.QuadPart = offset; @@ -309,22 +309,22 @@ static inline i64 DoSeek(FHANDLE h, i64 offset, SeekDir origin) noexcept { return pos.QuadPart; #elif defined(_unix_) static int dir[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - #if defined(_sun_) - return ::llseek(h, (offset_t)offset, dir[origin]); - #else - return ::lseek(h, (off_t)offset, dir[origin]); - #endif -#else - #error unsupported platform -#endif + #if defined(_sun_) + return ::llseek(h, (offset_t)offset, dir[origin]); + #else + return ::lseek(h, (off_t)offset, dir[origin]); + #endif +#else + #error unsupported platform +#endif } i64 TFileHandle::GetPosition() const noexcept { - return DoSeek(Fd_, 0, sCur); + return DoSeek(Fd_, 0, sCur); } i64 TFileHandle::Seek(i64 offset, SeekDir origin) noexcept { - return DoSeek(Fd_, offset, origin); + return DoSeek(Fd_, offset, origin); } i64 TFileHandle::GetLength() const noexcept { @@ -343,7 +343,7 @@ bool TFileHandle::Resize(i64 length) noexcept { if (length == currentLength) { return true; } -#if defined(_win_) +#if defined(_win_) i64 currentPosition = GetPosition(); if (currentPosition == -1L) { return false; @@ -356,10 +356,10 @@ bool TFileHandle::Resize(i64 length) noexcept { Seek(currentPosition, sSet); } return true; -#elif defined(_unix_) +#elif defined(_unix_) return (0 == ftruncate(Fd_, (off_t)length)); #else - #error unsupported platform + #error unsupported platform #endif } @@ -375,15 +375,15 @@ bool TFileHandle::Reserve(i64 length) noexcept { if (!Resize(length)) { return false; } -#if defined(_win_) +#if defined(_win_) if (!::SetFileValidData(Fd_, length)) { Resize(currentLength); return false; } -#elif defined(_unix_) -// No way to implement this under FreeBSD. Just do nothing +#elif defined(_unix_) +// No way to implement this under FreeBSD. Just do nothing #else - #error unsupported platform + #error unsupported platform #endif return true; } @@ -406,9 +406,9 @@ bool TFileHandle::ShrinkToFit() noexcept { return false; } #if defined(_linux_) && (!defined(_android_) || __ANDROID_API__ >= 21) - return !ftruncate(Fd_, (off_t)GetLength()); + return !ftruncate(Fd_, (off_t)GetLength()); #else - return true; + return true; #endif } @@ -433,31 +433,31 @@ bool TFileHandle::Flush() noexcept { * Fail in case of EIO, ENOSPC, EDQUOT - data might be lost. */ return ret == 0 || errno == EROFS || errno == EINVAL - #if defined(_darwin_) + #if defined(_darwin_) // ENOTSUP fd does not refer to a vnode || errno == ENOTSUP - #endif + #endif ; #else - #error unsupported platform + #error unsupported platform #endif -} +} bool TFileHandle::FlushData() noexcept { -#if defined(_linux_) - if (!IsOpen()) { - return false; - } - +#if defined(_linux_) + if (!IsOpen()) { + return false; + } + int ret = ::fdatasync(Fd_); // Same loginc in error handling as for fsync above. return ret == 0 || errno == EROFS || errno == EINVAL; -#else - return Flush(); -#endif -} - +#else + return Flush(); +#endif +} + i32 TFileHandle::Read(void* buffer, ui32 byteCount) noexcept { // FIXME size and return must be 64-bit if (!IsOpen()) { @@ -476,7 +476,7 @@ i32 TFileHandle::Read(void* buffer, ui32 byteCount) noexcept { } while (ret == -1 && errno == EINTR); return ret; #else - #error unsupported platform + #error unsupported platform #endif } @@ -497,14 +497,14 @@ i32 TFileHandle::Write(const void* buffer, ui32 byteCount) noexcept { } while (ret == -1 && errno == EINTR); return ret; #else - #error unsupported platform + #error unsupported platform #endif } i32 TFileHandle::Pread(void* buffer, ui32 byteCount, i64 offset) const noexcept { #if defined(_win_) - OVERLAPPED io; - Zero(io); + OVERLAPPED io; + Zero(io); DWORD bytesRead = 0; io.Offset = (ui32)offset; io.OffsetHigh = (ui32)(offset >> 32); @@ -522,14 +522,14 @@ i32 TFileHandle::Pread(void* buffer, ui32 byteCount, i64 offset) const noexcept } while (ret == -1 && errno == EINTR); return ret; #else - #error unsupported platform + #error unsupported platform #endif } i32 TFileHandle::Pwrite(const void* buffer, ui32 byteCount, i64 offset) const noexcept { #if defined(_win_) - OVERLAPPED io; - Zero(io); + OVERLAPPED io; + Zero(io); DWORD bytesWritten = 0; io.Offset = (ui32)offset; io.OffsetHigh = (ui32)(offset >> 32); @@ -544,7 +544,7 @@ i32 TFileHandle::Pwrite(const void* buffer, ui32 byteCount, i64 offset) const no } while (ret == -1 && errno == EINTR); return ret; #else - #error unsupported platform + #error unsupported platform #endif } @@ -559,9 +559,9 @@ FHANDLE TFileHandle::Duplicate() const noexcept { } return dupHandle; #elif defined(_unix_) - return ::dup(Fd_); + return ::dup(Fd_); #else - #error unsupported platform + #error unsupported platform #endif } @@ -593,47 +593,47 @@ int TFileHandle::Duplicate2Posix(int dstHandle) const noexcept { } return dstHandle; #else - #error unsupported platform + #error unsupported platform #endif } bool TFileHandle::LinkTo(const TFileHandle& fh) const noexcept { -#if defined(_unix_) +#if defined(_unix_) while (dup2(fh.Fd_, Fd_) == -1) { if (errno != EINTR) { return false; } } return true; -#elif defined(_win_) - TFileHandle nh(fh.Duplicate()); - - if (!nh.IsOpen()) { - return false; - } - - //not thread-safe - nh.Swap(*const_cast<TFileHandle*>(this)); - - return true; -#else - #error unsupported -#endif -} - +#elif defined(_win_) + TFileHandle nh(fh.Duplicate()); + + if (!nh.IsOpen()) { + return false; + } + + //not thread-safe + nh.Swap(*const_cast<TFileHandle*>(this)); + + return true; +#else + #error unsupported +#endif +} + int TFileHandle::Flock(int op) noexcept { - return ::Flock(Fd_, op); + return ::Flock(Fd_, op); } -bool TFileHandle::SetDirect() { +bool TFileHandle::SetDirect() { #ifdef _linux_ - const long flags = fcntl(Fd_, F_GETFL); - const int r = fcntl(Fd_, F_SETFL, flags | O_DIRECT); - - return !r; -#endif - - return false; + const long flags = fcntl(Fd_, F_GETFL); + const int r = fcntl(Fd_, F_SETFL, flags | O_DIRECT); + + return !r; +#endif + + return false; } void TFileHandle::ResetDirect() { @@ -646,7 +646,7 @@ void TFileHandle::ResetDirect() { i64 TFileHandle::CountCache(i64 offset, i64 length) const noexcept { #ifdef _linux_ const i64 pageSize = NSystemInfo::GetPageSize(); - constexpr size_t vecSize = 512; // Fetch up to 2MiB at once + constexpr size_t vecSize = 512; // Fetch up to 2MiB at once const i64 batchSize = vecSize * pageSize; std::array<ui8, vecSize> vec; void* ptr = nullptr; @@ -723,10 +723,10 @@ i64 TFileHandle::CountCache(i64 offset, i64 length) const noexcept { void TFileHandle::PrefetchCache(i64 offset, i64 length, bool wait) const noexcept { #ifdef _linux_ - #if HAVE_POSIX_FADVISE + #if HAVE_POSIX_FADVISE // POSIX_FADV_WILLNEED starts reading upto read_ahead_kb in background ::posix_fadvise(Fd_, offset, length, POSIX_FADV_WILLNEED); - #endif + #endif if (wait) { TFileHandle devnull("/dev/null", OpenExisting | WrOnly | CloseOnExec); @@ -778,14 +778,14 @@ bool TFileHandle::FlushCache(i64 offset, i64 length, bool wait) noexcept { TString DecodeOpenMode(ui32 mode0) { ui32 mode = mode0; - TStringBuilder r; + TStringBuilder r; -#define F(flag) \ - if ((mode & flag) == flag) { \ - mode &= ~flag; \ - if (r) { \ +#define F(flag) \ + if ((mode & flag) == flag) { \ + mode &= ~flag; \ + if (r) { \ r << TStringBuf("|"); \ - } \ + } \ r << TStringBuf(#flag); \ } @@ -827,76 +827,76 @@ TString DecodeOpenMode(ui32 mode0) { #undef F if (mode != 0) { - if (r) { + if (r) { r << TStringBuf("|"); - } - - r << Hex(mode); + } + + r << Hex(mode); } - if (!r) { - return "0"; - } + if (!r) { + return "0"; + } return r; -} +} -class TFile::TImpl: public TAtomicRefCount<TImpl> { -public: +class TFile::TImpl: public TAtomicRefCount<TImpl> { +public: inline TImpl(FHANDLE fd, const TString& fname = TString()) - : Handle_(fd) - , FileName_(fname) - { - } + : Handle_(fd) + , FileName_(fname) + { + } inline TImpl(const TString& fName, EOpenMode oMode) - : Handle_(fName, oMode) - , FileName_(fName) - { - if (!Handle_.IsOpen()) { + : Handle_(fName, oMode) + , FileName_(fName) + { + if (!Handle_.IsOpen()) { ythrow TFileError() << "can't open " << fName.Quote() << " with mode " << DecodeOpenMode(oMode) << " (" << Hex(oMode.ToBaseType()) << ")"; } - } + } inline ~TImpl() = default; - inline void Close() { + inline void Close() { if (!Handle_.Close()) { - ythrow TFileError() << "can't close " << FileName_.Quote(); + ythrow TFileError() << "can't close " << FileName_.Quote(); } - } + } const TString& GetName() const noexcept { - return FileName_; - } + return FileName_; + } void SetName(const TString& newName) { - FileName_ = newName; - } + FileName_ = newName; + } const TFileHandle& GetHandle() const noexcept { - return Handle_; - } + return Handle_; + } - i64 Seek(i64 offset, SeekDir origin) { - i64 pos = Handle_.Seek(offset, origin); + i64 Seek(i64 offset, SeekDir origin) { + i64 pos = Handle_.Seek(offset, origin); if (pos == -1L) { - ythrow TFileError() << "can't seek " << offset << " bytes in " << FileName_.Quote(); + ythrow TFileError() << "can't seek " << offset << " bytes in " << FileName_.Quote(); } - return pos; - } + return pos; + } - void Resize(i64 length) { + void Resize(i64 length) { if (!Handle_.Resize(length)) { - ythrow TFileError() << "can't resize " << FileName_.Quote() << " to size " << length; + ythrow TFileError() << "can't resize " << FileName_.Quote() << " to size " << length; } - } + } - void Reserve(i64 length) { + void Reserve(i64 length) { if (!Handle_.Reserve(length)) { - ythrow TFileError() << "can't reserve " << length << " for file " << FileName_.Quote(); + ythrow TFileError() << "can't reserve " << length << " for file " << FileName_.Quote(); } - } + } void FallocateNoResize(i64 length) { if (!Handle_.FallocateNoResize(length)) { @@ -910,27 +910,27 @@ public: } } - void Flush() { + void Flush() { if (!Handle_.Flush()) { - ythrow TFileError() << "can't flush " << FileName_.Quote(); + ythrow TFileError() << "can't flush " << FileName_.Quote(); } - } + } - void FlushData() { + void FlushData() { if (!Handle_.FlushData()) { - ythrow TFileError() << "can't flush data " << FileName_.Quote(); + ythrow TFileError() << "can't flush data " << FileName_.Quote(); } - } - - TFile Duplicate() const { - TFileHandle dupH(Handle_.Duplicate()); + } + + TFile Duplicate() const { + TFileHandle dupH(Handle_.Duplicate()); if (!dupH.IsOpen()) { - ythrow TFileError() << "can't duplicate the handle of " << FileName_.Quote(); + ythrow TFileError() << "can't duplicate the handle of " << FileName_.Quote(); } - TFile res(dupH); - dupH.Release(); - return res; - } + TFile res(dupH); + dupH.Release(); + return res; + } // Maximum amount of bytes to be read via single system call. // Some libraries fail when it is greater than max int. @@ -952,112 +952,112 @@ public: return reallyRead; } - size_t Read(void* bufferIn, size_t numBytes) { - ui8* buf = (ui8*)bufferIn; + size_t Read(void* bufferIn, size_t numBytes) { + ui8* buf = (ui8*)bufferIn; - while (numBytes) { + while (numBytes) { const size_t reallyRead = ReadOrFail(buf, numBytes); if (reallyRead == 0) { // file exhausted - break; + break; } - buf += reallyRead; - numBytes -= reallyRead; + buf += reallyRead; + numBytes -= reallyRead; } - return buf - (ui8*)bufferIn; - } + return buf - (ui8*)bufferIn; + } - void Load(void* buf, size_t len) { + void Load(void* buf, size_t len) { if (Read(buf, len) != len) { - ythrow TFileError() << "can't read " << len << " bytes from " << FileName_.Quote(); + ythrow TFileError() << "can't read " << len << " bytes from " << FileName_.Quote(); } - } + } // Maximum amount of bytes to be written via single system call. // Some libraries fail when it is greater than max int. // Syscalls can cause contention if they operate on very large data blocks. static constexpr size_t MaxWritePortion = 1_GB; - void Write(const void* buffer, size_t numBytes) { - const ui8* buf = (const ui8*)buffer; + void Write(const void* buffer, size_t numBytes) { + const ui8* buf = (const ui8*)buffer; - while (numBytes) { + while (numBytes) { const i32 toWrite = (i32)Min(MaxWritePortion, numBytes); - const i32 reallyWritten = Handle_.Write(buf, toWrite); + const i32 reallyWritten = Handle_.Write(buf, toWrite); if (reallyWritten < 0) { - ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote(); + ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote(); } - - buf += reallyWritten; - numBytes -= reallyWritten; + + buf += reallyWritten; + numBytes -= reallyWritten; } - } + } - size_t Pread(void* bufferIn, size_t numBytes, i64 offset) const { - ui8* buf = (ui8*)bufferIn; + size_t Pread(void* bufferIn, size_t numBytes, i64 offset) const { + ui8* buf = (ui8*)bufferIn; - while (numBytes) { + while (numBytes) { const i32 toRead = (i32)Min(MaxReadPortion, numBytes); const i32 reallyRead = RawPread(buf, toRead, offset); if (reallyRead < 0) { - ythrow TFileError() << "can not read data from " << FileName_.Quote(); + ythrow TFileError() << "can not read data from " << FileName_.Quote(); } if (reallyRead == 0) { // file exausted - break; + break; } - buf += reallyRead; - offset += reallyRead; - numBytes -= reallyRead; + buf += reallyRead; + offset += reallyRead; + numBytes -= reallyRead; } - return buf - (ui8*)bufferIn; - } + return buf - (ui8*)bufferIn; + } i32 RawPread(void* buf, ui32 len, i64 offset) const { return Handle_.Pread(buf, len, offset); } - void Pload(void* buf, size_t len, i64 offset) const { + void Pload(void* buf, size_t len, i64 offset) const { if (Pread(buf, len, offset) != len) { - ythrow TFileError() << "can't read " << len << " bytes at offset " << offset << " from " << FileName_.Quote(); + ythrow TFileError() << "can't read " << len << " bytes at offset " << offset << " from " << FileName_.Quote(); } - } + } - void Pwrite(const void* buffer, size_t numBytes, i64 offset) const { - const ui8* buf = (const ui8*)buffer; + void Pwrite(const void* buffer, size_t numBytes, i64 offset) const { + const ui8* buf = (const ui8*)buffer; - while (numBytes) { + while (numBytes) { const i32 toWrite = (i32)Min(MaxWritePortion, numBytes); - const i32 reallyWritten = Handle_.Pwrite(buf, toWrite, offset); + const i32 reallyWritten = Handle_.Pwrite(buf, toWrite, offset); if (reallyWritten < 0) { - ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote(); + ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote(); } - buf += reallyWritten; - offset += reallyWritten; - numBytes -= reallyWritten; + buf += reallyWritten; + offset += reallyWritten; + numBytes -= reallyWritten; } - } - - void Flock(int op) { - if (0 != Handle_.Flock(op)) { - ythrow TFileError() << "can't flock " << FileName_.Quote(); - } - } - + } + + void Flock(int op) { + if (0 != Handle_.Flock(op)) { + ythrow TFileError() << "can't flock " << FileName_.Quote(); + } + } + void SetDirect() { - if (!Handle_.SetDirect()) { - ythrow TFileError() << "can't set direct mode for " << FileName_.Quote(); - } + if (!Handle_.SetDirect()) { + ythrow TFileError() << "can't set direct mode for " << FileName_.Quote(); + } } void ResetDirect() { @@ -1082,18 +1082,18 @@ public: } } -private: - TFileHandle Handle_; +private: + TFileHandle Handle_; TString FileName_; }; TFile::TFile() - : Impl_(new TImpl(INVALID_FHANDLE)) + : Impl_(new TImpl(INVALID_FHANDLE)) { } TFile::TFile(FHANDLE fd) - : Impl_(new TImpl(fd)) + : Impl_(new TImpl(fd)) { } @@ -1103,38 +1103,38 @@ TFile::TFile(FHANDLE fd, const TString& name) } TFile::TFile(const TString& fName, EOpenMode oMode) - : Impl_(new TImpl(fName, oMode)) + : Impl_(new TImpl(fName, oMode)) { } TFile::~TFile() = default; void TFile::Close() { - Impl_->Close(); + Impl_->Close(); } const TString& TFile::GetName() const noexcept { - return Impl_->GetName(); + return Impl_->GetName(); } i64 TFile::GetPosition() const noexcept { - return Impl_->GetHandle().GetPosition(); + return Impl_->GetHandle().GetPosition(); } i64 TFile::GetLength() const noexcept { - return Impl_->GetHandle().GetLength(); + return Impl_->GetHandle().GetLength(); } bool TFile::IsOpen() const noexcept { - return Impl_->GetHandle().IsOpen(); + return Impl_->GetHandle().IsOpen(); } FHANDLE TFile::GetHandle() const noexcept { - return Impl_->GetHandle(); + return Impl_->GetHandle(); } i64 TFile::Seek(i64 offset, SeekDir origin) { - return Impl_->Seek(offset, origin); + return Impl_->Seek(offset, origin); } void TFile::Resize(i64 length) { @@ -1154,21 +1154,21 @@ void TFile::ShrinkToFit() { } void TFile::Flush() { - Impl_->Flush(); -} - -void TFile::FlushData() { - Impl_->FlushData(); + Impl_->Flush(); } -TFile TFile::Duplicate() const { - TFile res = Impl_->Duplicate(); - res.Impl_->SetName(Impl_->GetName()); +void TFile::FlushData() { + Impl_->FlushData(); +} + +TFile TFile::Duplicate() const { + TFile res = Impl_->Duplicate(); + res.Impl_->SetName(Impl_->GetName()); return res; } size_t TFile::Read(void* buf, size_t len) { - return Impl_->Read(buf, len); + return Impl_->Read(buf, len); } i32 TFile::RawRead(void* buf, size_t len) { @@ -1180,15 +1180,15 @@ size_t TFile::ReadOrFail(void* buf, size_t len) { } void TFile::Load(void* buf, size_t len) { - Impl_->Load(buf, len); + Impl_->Load(buf, len); } void TFile::Write(const void* buf, size_t len) { - Impl_->Write(buf, len); + Impl_->Write(buf, len); } size_t TFile::Pread(void* buf, size_t len, i64 offset) const { - return Impl_->Pread(buf, len, offset); + return Impl_->Pread(buf, len, offset); } i32 TFile::RawPread(void* buf, ui32 len, i64 offset) const { @@ -1196,15 +1196,15 @@ i32 TFile::RawPread(void* buf, ui32 len, i64 offset) const { } void TFile::Pload(void* buf, size_t len, i64 offset) const { - Impl_->Pload(buf, len, offset); + Impl_->Pload(buf, len, offset); } void TFile::Pwrite(const void* buf, size_t len, i64 offset) const { - Impl_->Pwrite(buf, len, offset); + Impl_->Pwrite(buf, len, offset); } void TFile::Flock(int op) { - Impl_->Flock(op); + Impl_->Flock(op); } void TFile::SetDirect() { @@ -1231,17 +1231,17 @@ void TFile::FlushCache(i64 offset, i64 length, bool wait) { Impl_->FlushCache(offset, length, wait); } -void TFile::LinkTo(const TFile& f) const { - if (!Impl_->GetHandle().LinkTo(f.Impl_->GetHandle())) { - ythrow TFileError() << "can not link fd(" << GetName() << " -> " << f.GetName() << ")"; - } -} - +void TFile::LinkTo(const TFile& f) const { + if (!Impl_->GetHandle().LinkTo(f.Impl_->GetHandle())) { + ythrow TFileError() << "can not link fd(" << GetName() << " -> " << f.GetName() << ")"; + } +} + TFile TFile::Temporary(const TString& prefix) { - //TODO - handle impossible case of name collision - return TFile(prefix + ToString(MicroSeconds()) + "-" + ToString(RandomNumber<ui64>()), CreateNew | RdWr | Seq | Temp | Transient); -} - + //TODO - handle impossible case of name collision + return TFile(prefix + ToString(MicroSeconds()) + "-" + ToString(RandomNumber<ui64>()), CreateNew | RdWr | Seq | Temp | Transient); +} + TFile TFile::ForAppend(const TString& path) { return TFile(path, OpenAlways | WrOnly | Seq | ::ForAppend); } @@ -1251,7 +1251,7 @@ TFile Duplicate(FILE* f) { } TFile Duplicate(int fd) { -#if defined(_win_) +#if defined(_win_) /* There are two options of how to duplicate a file descriptor on Windows: * * 1: @@ -1276,10 +1276,10 @@ TFile Duplicate(int fd) { } return TFile(dupHandle); -#elif defined(_unix_) +#elif defined(_unix_) return TFile(::dup(fd)); #else - #error unsupported platform + #error unsupported platform #endif } @@ -1287,13 +1287,13 @@ bool PosixDisableReadAhead(FHANDLE fileHandle, void* addr) noexcept { int ret = -1; #if HAVE_POSIX_FADVISE - #if defined(_linux_) + #if defined(_linux_) Y_UNUSED(fileHandle); ret = madvise(addr, 0, MADV_RANDOM); // according to klamm@ posix_fadvise does not work under linux, madvise does work - #else + #else Y_UNUSED(addr); ret = ::posix_fadvise(fileHandle, 0, 0, POSIX_FADV_RANDOM); - #endif + #endif #else Y_UNUSED(fileHandle); Y_UNUSED(addr); diff --git a/util/system/file.h b/util/system/file.h index 9502e159b6..c38e5bd43b 100644 --- a/util/system/file.h +++ b/util/system/file.h @@ -1,25 +1,25 @@ #pragma once #include "fhandle.h" -#include "flock.h" - +#include "flock.h" + #include <util/generic/flags.h> #include <util/generic/ptr.h> -#include <util/generic/noncopyable.h> - -#include <cstdio> +#include <util/generic/noncopyable.h> +#include <cstdio> + enum EOpenModeFlag { - OpenExisting = 0, // Opens a file. It fails if the file does not exist. + OpenExisting = 0, // Opens a file. It fails if the file does not exist. TruncExisting = 1, // Opens a file and truncates it to zero size. It fails if the file does not exist. - OpenAlways = 2, // Opens a file, always. If a file does not exist, it creates a file. - CreateNew = 3, // Creates a new file. It fails if a specified file exists. - CreateAlways = 4, // Creates a new file, always. If a file exists, it overwrites the file. - MaskCreation = 7, + OpenAlways = 2, // Opens a file, always. If a file does not exist, it creates a file. + CreateNew = 3, // Creates a new file. It fails if a specified file exists. + CreateAlways = 4, // Creates a new file, always. If a file exists, it overwrites the file. + MaskCreation = 7, RdOnly = 8, // open for reading only WrOnly = 16, // open for writing only - RdWr = 24, // open for reading and writing + RdWr = 24, // open for reading and writing MaskRW = 24, Seq = 0x20, // file access is primarily sequential (POSIX_FADV_SEQUENTIAL) @@ -39,12 +39,12 @@ enum EOpenModeFlag { AXGroup = 0x00100000, AWGroup = 0x00200000, ARGroup = 0x00400000, - AXUser = 0x01000000, - AWUser = 0x02000000, - ARUser = 0x04000000, - AX = AXUser | AXGroup | AXOther, - AW = AWUser | AWGroup, - AR = ARUser | ARGroup | AROther, + AXUser = 0x01000000, + AWUser = 0x02000000, + ARUser = 0x04000000, + AX = AXUser | AXGroup | AXOther, + AW = AWUser | AWGroup, + AR = ARUser | ARGroup | AROther, ARW = AR | AW, AMask = 0x0FFF0000, }; @@ -60,13 +60,13 @@ enum SeekDir { sEnd = 2, }; -class TFileHandle: public TNonCopyable { +class TFileHandle: public TNonCopyable { public: constexpr TFileHandle() = default; /// Warning: takes ownership of fd, so closes it in destructor. inline TFileHandle(FHANDLE fd) noexcept - : Fd_(fd) + : Fd_(fd) { } @@ -85,21 +85,21 @@ public: bool Close() noexcept; inline FHANDLE Release() noexcept { - FHANDLE ret = Fd_; - Fd_ = INVALID_FHANDLE; + FHANDLE ret = Fd_; + Fd_ = INVALID_FHANDLE; return ret; } inline void Swap(TFileHandle& r) noexcept { - DoSwap(Fd_, r.Fd_); + DoSwap(Fd_, r.Fd_); } inline operator FHANDLE() const noexcept { - return Fd_; + return Fd_; } inline bool IsOpen() const noexcept { - return Fd_ != INVALID_FHANDLE; + return Fd_ != INVALID_FHANDLE; } i64 GetPosition() const noexcept; @@ -111,7 +111,7 @@ public: bool FallocateNoResize(i64 length) noexcept; bool ShrinkToFit() noexcept; bool Flush() noexcept; - //flush data only, without file metadata + //flush data only, without file metadata bool FlushData() noexcept; i32 Read(void* buffer, ui32 byteCount) noexcept; i32 Write(const void* buffer, ui32 byteCount) noexcept; @@ -122,11 +122,11 @@ public: FHANDLE Duplicate() const noexcept; int Duplicate2Posix(int dstHandle) const noexcept; - //dup2 - like semantics, return true on success + //dup2 - like semantics, return true on success bool LinkTo(const TFileHandle& fh) const noexcept; - - //very low-level methods - bool SetDirect(); + + //very low-level methods + bool SetDirect(); void ResetDirect(); /* Manual file cache management, length = 0 means "as much as possible" */ @@ -167,10 +167,10 @@ public: void FallocateNoResize(i64 length); void ShrinkToFit(); void Flush(); - void FlushData(); + void FlushData(); - void LinkTo(const TFile& f) const; - TFile Duplicate() const; + void LinkTo(const TFile& f) const; + TFile Duplicate() const; // Reads up to 1 GB without retrying, returns -1 on error i32 RawRead(void* buf, size_t len); @@ -195,8 +195,8 @@ public: void Pwrite(const void* buf, size_t len, i64 offset) const; void Flock(int op); - - //do not use, their meaning very platform-dependant + + //do not use, their meaning very platform-dependant void SetDirect(); void ResetDirect(); @@ -213,10 +213,10 @@ public: static TFile Temporary(const TString& prefix); static TFile ForAppend(const TString& path); - + private: class TImpl; - TSimpleIntrusivePtr<TImpl> Impl_; + TSimpleIntrusivePtr<TImpl> Impl_; }; TFile Duplicate(FILE*); diff --git a/util/system/file_lock.cpp b/util/system/file_lock.cpp index 45d91282c5..11cf67adc9 100644 --- a/util/system/file_lock.cpp +++ b/util/system/file_lock.cpp @@ -1,5 +1,5 @@ #include "file_lock.h" -#include "flock.h" +#include "flock.h" #include <util/generic/yexception.h> diff --git a/util/system/file_lock.h b/util/system/file_lock.h index b2aaff5baf..2c0118484f 100644 --- a/util/system/file_lock.h +++ b/util/system/file_lock.h @@ -4,11 +4,11 @@ #include <util/generic/noncopyable.h> #include <util/system/file.h> -enum class EFileLockType { +enum class EFileLockType { Exclusive, Shared }; - + class TFileLock: public TFile { public: TFileLock(const TString& filename, const EFileLockType type = EFileLockType::Exclusive); diff --git a/util/system/file_ut.cpp b/util/system/file_ut.cpp index 941e6a50f3..799da739f8 100644 --- a/util/system/file_ut.cpp +++ b/util/system/file_ut.cpp @@ -1,22 +1,22 @@ -#include "file.h" +#include "file.h" #include "fs.h" #include "tempfile.h" - + #include <library/cpp/testing/unittest/registar.h> - -#include <util/stream/file.h> -#include <util/generic/yexception.h> + +#include <util/stream/file.h> +#include <util/generic/yexception.h> class TFileTest: public TTestBase { - UNIT_TEST_SUITE(TFileTest); - UNIT_TEST(TestOpen); + UNIT_TEST_SUITE(TFileTest); + UNIT_TEST(TestOpen); UNIT_TEST(TestOpenSync); - UNIT_TEST(TestRW); - UNIT_TEST(TestReWrite); - UNIT_TEST(TestAppend); - UNIT_TEST(TestLinkTo); - UNIT_TEST(TestResize); - UNIT_TEST(TestLocale); + UNIT_TEST(TestRW); + UNIT_TEST(TestReWrite); + UNIT_TEST(TestAppend); + UNIT_TEST(TestLinkTo); + UNIT_TEST(TestResize); + UNIT_TEST(TestLocale); UNIT_TEST(TestFlush); UNIT_TEST(TestFlushSpecialFile); UNIT_TEST(TestRawRead); @@ -24,13 +24,13 @@ class TFileTest: public TTestBase { UNIT_TEST(TestRawPread); UNIT_TEST(TestPread); UNIT_TEST(TestCache); - UNIT_TEST_SUITE_END(); - -public: - void TestOpen(); + UNIT_TEST_SUITE_END(); + +public: + void TestOpen(); void TestOpenSync(); - void TestRW(); - void TestLocale(); + void TestRW(); + void TestLocale(); void TestFlush(); void TestFlushSpecialFile(); void TestRawRead(); @@ -38,83 +38,83 @@ public: void TestRawPread(); void TestPread(); void TestCache(); - - inline void TestLinkTo() { - TTempFile tmp1("tmp1"); - TTempFile tmp2("tmp2"); - - { - TFile f1(tmp1.Name(), OpenAlways | WrOnly); - TFile f2(tmp2.Name(), OpenAlways | WrOnly); - - f1.LinkTo(f2); - - f1.Write("12345", 5); - f2.Write("67890", 5); - } - + + inline void TestLinkTo() { + TTempFile tmp1("tmp1"); + TTempFile tmp2("tmp2"); + + { + TFile f1(tmp1.Name(), OpenAlways | WrOnly); + TFile f2(tmp2.Name(), OpenAlways | WrOnly); + + f1.LinkTo(f2); + + f1.Write("12345", 5); + f2.Write("67890", 5); + } + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp2.Name()).ReadAll(), "1234567890"); - } - - inline void TestAppend() { - TTempFile tmp("tmp"); - - { - TFile f(tmp.Name(), OpenAlways | WrOnly); - - f.Write("12345678", 8); - } - - { - TFile f(tmp.Name(), OpenAlways | WrOnly | ForAppend); - - f.Write("67", 2); - f.Write("89", 2); - } - + } + + inline void TestAppend() { + TTempFile tmp("tmp"); + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("12345678", 8); + } + + { + TFile f(tmp.Name(), OpenAlways | WrOnly | ForAppend); + + f.Write("67", 2); + f.Write("89", 2); + } + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp.Name()).ReadAll(), "123456786789"); - } - - inline void TestReWrite() { - TTempFile tmp("tmp"); - - { - TFile f(tmp.Name(), OpenAlways | WrOnly); - - f.Write("12345678", 8); - } - - { - TFile f(tmp.Name(), OpenAlways | WrOnly); - - f.Write("6789", 4); - } - + } + + inline void TestReWrite() { + TTempFile tmp("tmp"); + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("12345678", 8); + } + + { + TFile f(tmp.Name(), OpenAlways | WrOnly); + + f.Write("6789", 4); + } + UNIT_ASSERT_EQUAL(TUnbufferedFileInput(tmp.Name()).ReadAll(), "67895678"); - } + } - inline void TestResize() { - TTempFile tmp("tmp"); + inline void TestResize() { + TTempFile tmp("tmp"); - { - TFile file(tmp.Name(), OpenAlways | WrOnly); + { + TFile file(tmp.Name(), OpenAlways | WrOnly); - file.Write("1234567", 7); - file.Seek(3, sSet); + file.Write("1234567", 7); + file.Seek(3, sSet); - file.Resize(5); - UNIT_ASSERT_EQUAL(file.GetLength(), 5); - UNIT_ASSERT_EQUAL(file.GetPosition(), 3); + file.Resize(5); + UNIT_ASSERT_EQUAL(file.GetLength(), 5); + UNIT_ASSERT_EQUAL(file.GetPosition(), 3); - file.Resize(12); - UNIT_ASSERT_EQUAL(file.GetLength(), 12); - UNIT_ASSERT_EQUAL(file.GetPosition(), 3); + file.Resize(12); + UNIT_ASSERT_EQUAL(file.GetLength(), 12); + UNIT_ASSERT_EQUAL(file.GetPosition(), 3); } - + const TString data = TUnbufferedFileInput(tmp.Name()).ReadAll(); - UNIT_ASSERT_EQUAL(data.length(), 12); + UNIT_ASSERT_EQUAL(data.length(), 12); UNIT_ASSERT(data.StartsWith("12345")); - } + } }; UNIT_TEST_SUITE_REGISTRATION(TFileTest); @@ -168,7 +168,7 @@ void TFileTest::TestRW() { UNIT_ASSERT_VALUES_EQUAL(f1.GetName(), "f1.txt"); UNIT_ASSERT_VALUES_EQUAL(f1.GetLength(), 0); ui32 d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - f1.Write(&d, sizeof(ui32) * 10); + f1.Write(&d, sizeof(ui32) * 10); UNIT_ASSERT_VALUES_EQUAL(f1.GetLength(), 40); UNIT_ASSERT_VALUES_EQUAL(f1.GetPosition(), 40); UNIT_ASSERT_VALUES_EQUAL(f1.Seek(12, sSet), 12); @@ -197,7 +197,7 @@ void TFileTest::TestRW() { } #ifdef _unix_ - #include <locale.h> + #include <locale.h> #endif void TFileTest::TestLocale() { @@ -328,86 +328,86 @@ void TFileTest::TestPread() { } #ifdef _linux_ - #include <sys/statfs.h> + #include <sys/statfs.h> #endif #ifndef TMPFS_MAGIC - #define TMPFS_MAGIC 0x01021994 + #define TMPFS_MAGIC 0x01021994 #endif -void TFileTest::TestCache(){ +void TFileTest::TestCache(){ #ifdef _linux_ - {// create file in /tmp, current dir could be tmpfs which does not support fadvise - TFile file(MakeTempName("/tmp"), OpenAlways | Transient | RdWr | NoReadAhead); + {// create file in /tmp, current dir could be tmpfs which does not support fadvise + TFile file(MakeTempName("/tmp"), OpenAlways | Transient | RdWr | NoReadAhead); -struct statfs fs; -if (!fstatfs(file.GetHandle(), &fs) && fs.f_type == TMPFS_MAGIC) { - return; -} +struct statfs fs; +if (!fstatfs(file.GetHandle(), &fs) && fs.f_type == TMPFS_MAGIC) { + return; +} -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 0), 0); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 0), 0); -file.Resize(7); -file.PrefetchCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(3, 2), 2); +file.Resize(7); +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(3, 2), 2); -file.FlushCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); +file.FlushCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); -file.EvictCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); -file.PrefetchCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 7); -file.Resize(12345); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 4096); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(4096, 0), 0); +file.Resize(12345); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 4096); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(4096, 0), 0); -file.PrefetchCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 12345); +file.PrefetchCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 12345); -file.FlushCache(); -file.EvictCache(); -UNIT_ASSERT_LE(file.CountCache(), 0); +file.FlushCache(); +file.EvictCache(); +UNIT_ASSERT_LE(file.CountCache(), 0); -file.Resize(33333333); -file.PrefetchCache(11111111, 11111111); -UNIT_ASSERT_GE(file.CountCache(), 11111111); +file.Resize(33333333); +file.PrefetchCache(11111111, 11111111); +UNIT_ASSERT_GE(file.CountCache(), 11111111); -UNIT_ASSERT_LE(file.CountCache(0, 11111111), 1111111); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(11111111, 11111111), 11111111); -UNIT_ASSERT_LE(file.CountCache(22222222, 11111111), 1111111); +UNIT_ASSERT_LE(file.CountCache(0, 11111111), 1111111); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(11111111, 11111111), 11111111); +UNIT_ASSERT_LE(file.CountCache(22222222, 11111111), 1111111); -file.FlushCache(11111111, 11111111); -UNIT_ASSERT_GE(file.CountCache(), 11111111); +file.FlushCache(11111111, 11111111); +UNIT_ASSERT_GE(file.CountCache(), 11111111); -// first and last incomplete pages could stay in cache -file.EvictCache(11111111, 11111111); -UNIT_ASSERT_LT(file.CountCache(11111111, 11111111), 4096 * 2); +// first and last incomplete pages could stay in cache +file.EvictCache(11111111, 11111111); +UNIT_ASSERT_LT(file.CountCache(11111111, 11111111), 4096 * 2); -file.EvictCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); -} +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), 0); +} #else - {TFile file(MakeTempName(), OpenAlways | Transient | RdWr); + {TFile file(MakeTempName(), OpenAlways | Transient | RdWr); -file.Resize(12345); +file.Resize(12345); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), -1); -file.PrefetchCache(); -file.FlushCache(); -file.EvictCache(); -UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 12345), -1); -} +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(), -1); +file.PrefetchCache(); +file.FlushCache(); +file.EvictCache(); +UNIT_ASSERT_VALUES_EQUAL(file.CountCache(0, 12345), -1); +} #endif } Y_UNIT_TEST_SUITE(TTestDecodeOpenMode) { Y_UNIT_TEST(It) { - UNIT_ASSERT_VALUES_EQUAL("0", DecodeOpenMode(0)); + UNIT_ASSERT_VALUES_EQUAL("0", DecodeOpenMode(0)); UNIT_ASSERT_VALUES_EQUAL("RdOnly", DecodeOpenMode(RdOnly)); UNIT_ASSERT_VALUES_EQUAL("RdWr", DecodeOpenMode(RdWr)); UNIT_ASSERT_VALUES_EQUAL("WrOnly|ForAppend", DecodeOpenMode(WrOnly | ForAppend)); diff --git a/util/system/filemap.cpp b/util/system/filemap.cpp index 7454a4cb94..0884e6a0dc 100644 --- a/util/system/filemap.cpp +++ b/util/system/filemap.cpp @@ -1,84 +1,84 @@ -#include "info.h" +#include "info.h" #include "madvise.h" #include "defaults.h" #include "hi_lo.h" -#include <util/generic/buffer.h> +#include <util/generic/buffer.h> #include <util/generic/yexception.h> -#include <util/generic/singleton.h> +#include <util/generic/singleton.h> -#if defined(_win_) - #include "winint.h" +#if defined(_win_) + #include "winint.h" #elif defined(_unix_) - #include <sys/types.h> - #include <sys/mman.h> - - #if !defined(_linux_) - #ifdef MAP_POPULATE - #error unlisted platform supporting MAP_POPULATE - #endif - #define MAP_POPULATE 0 - #endif - - #if !defined(_freebsd_) - #ifdef MAP_NOCORE - #error unlisted platform supporting MAP_NOCORE - #endif - #define MAP_NOCORE 0 - #endif -#else - #error todo + #include <sys/types.h> + #include <sys/mman.h> + + #if !defined(_linux_) + #ifdef MAP_POPULATE + #error unlisted platform supporting MAP_POPULATE + #endif + #define MAP_POPULATE 0 + #endif + + #if !defined(_freebsd_) + #ifdef MAP_NOCORE + #error unlisted platform supporting MAP_NOCORE + #endif + #define MAP_NOCORE 0 + #endif +#else + #error todo #endif #include <util/generic/utility.h> #include <util/system/sanitizers.h> -#include "filemap.h" - +#include "filemap.h" + #undef PAGE_SIZE -#undef GRANULARITY - +#undef GRANULARITY + #ifdef _win_ - #define MAP_FAILED ((void*)(LONG_PTR)-1) + #define MAP_FAILED ((void*)(LONG_PTR)-1) #endif -namespace { - struct TSysInfo { - inline TSysInfo() - : GRANULARITY_(CalcGranularity()) - , PAGE_SIZE_(NSystemInfo::GetPageSize()) - { - } - - static inline const TSysInfo& Instance() { - return *Singleton<TSysInfo>(); - } - +namespace { + struct TSysInfo { + inline TSysInfo() + : GRANULARITY_(CalcGranularity()) + , PAGE_SIZE_(NSystemInfo::GetPageSize()) + { + } + + static inline const TSysInfo& Instance() { + return *Singleton<TSysInfo>(); + } + static inline size_t CalcGranularity() noexcept { -#if defined(_win_) - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwAllocationGranularity; -#else - return NSystemInfo::GetPageSize(); +#if defined(_win_) + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + return sysInfo.dwAllocationGranularity; +#else + return NSystemInfo::GetPageSize(); #endif - } - - const size_t GRANULARITY_; - const size_t PAGE_SIZE_; - }; -} - -#define GRANULARITY (TSysInfo::Instance().GRANULARITY_) -#define PAGE_SIZE (TSysInfo::Instance().PAGE_SIZE_) - -TString TMemoryMapCommon::UnknownFileName() { - return "Unknown_file_name"; -} + } + + const size_t GRANULARITY_; + const size_t PAGE_SIZE_; + }; +} + +#define GRANULARITY (TSysInfo::Instance().GRANULARITY_) +#define PAGE_SIZE (TSysInfo::Instance().PAGE_SIZE_) + +TString TMemoryMapCommon::UnknownFileName() { + return "Unknown_file_name"; +} static inline i64 DownToGranularity(i64 offset) noexcept { return offset & ~((i64)(GRANULARITY - 1)); -} - +} + #if defined(_unix_) static int ModeToMmapFlags(TMemoryMapCommon::EOpenMode mode) { int flags = MAP_NOCORE; @@ -114,44 +114,44 @@ void NPrivate::Precharge(const void* data, size_t dataSize, size_t off, size_t s endOff = dataSize; } size = endOff - off; - if (dataSize == 0 || size == 0) { + if (dataSize == 0 || size == 0) { return; - } + } volatile const char *c = (const char*)data + off, *e = c + size; - for (; c < e; c += 512) { + for (; c < e; c += 512) { *c; - } + } } -class TMemoryMap::TImpl: public TAtomicRefCount<TImpl> { -public: +class TMemoryMap::TImpl: public TAtomicRefCount<TImpl> { +public: inline void CreateMapping() { -#if defined(_win_) +#if defined(_win_) Mapping_ = nullptr; - if (Length_) { + if (Length_) { Mapping_ = CreateFileMapping(File_.GetHandle(), nullptr, (Mode_ & oAccessMask) == TFileMap::oRdWr ? PAGE_READWRITE : PAGE_READONLY, (DWORD)(Length_ >> 32), (DWORD)(Length_ & 0xFFFFFFFF), nullptr); if (Mapping_ == nullptr) { ythrow yexception() << "Can't create file mapping of '" << DbgName_ << "': " << LastSystemErrorText(); - } + } } else { Mapping_ = MAP_FAILED; - } + } #elif defined(_unix_) - if (!(Mode_ & oNotGreedy)) { + if (!(Mode_ & oNotGreedy)) { PtrStart_ = mmap((caddr_t) nullptr, Length_, ModeToMmapProt(Mode_), ModeToMmapFlags(Mode_), File_.GetHandle(), 0); - if ((MAP_FAILED == PtrStart_) && Length_) { + if ((MAP_FAILED == PtrStart_) && Length_) { ythrow yexception() << "Can't map " << (unsigned long)Length_ << " bytes of file '" << DbgName_ << "' at offset 0: " << LastSystemErrorText(); - } - } else { + } + } else { PtrStart_ = nullptr; - } + } #endif - } - + } + void CheckFile() const { if (!File_.IsOpen()) { ythrow yexception() << "TMemoryMap: FILE '" << DbgName_ << "' is not open, " << LastSystemErrorText(); @@ -162,169 +162,169 @@ public: } inline TImpl(FILE* f, EOpenMode om, TString dbgName) - : File_(Duplicate(f)) + : File_(Duplicate(f)) , DbgName_(std::move(dbgName)) - , Length_(File_.GetLength()) - , Mode_(om) - { + , Length_(File_.GetLength()) + , Mode_(om) + { CheckFile(); CreateMapping(); - } - + } + inline TImpl(const TString& name, EOpenMode om) - : File_(name, (om & oRdWr) ? OpenExisting | RdWr : OpenExisting | RdOnly) + : File_(name, (om & oRdWr) ? OpenExisting | RdWr : OpenExisting | RdOnly) , DbgName_(name) - , Length_(File_.GetLength()) - , Mode_(om) - { + , Length_(File_.GetLength()) + , Mode_(om) + { CheckFile(); CreateMapping(); - } - + } + inline TImpl(const TString& name, i64 length, EOpenMode om) - : File_(name, (om & oRdWr) ? OpenExisting | RdWr : OpenExisting | RdOnly) + : File_(name, (om & oRdWr) ? OpenExisting | RdWr : OpenExisting | RdOnly) , DbgName_(name) - , Length_(length) - , Mode_(om) - { + , Length_(length) + , Mode_(om) + { CheckFile(); - if (File_.GetLength() < Length_) { - File_.Resize(Length_); - } - + if (File_.GetLength() < Length_) { + File_.Resize(Length_); + } + CreateMapping(); - } - + } + inline TImpl(const TFile& file, EOpenMode om, TString dbgName) - : File_(file) + : File_(file) , DbgName_(File_.GetName() ? File_.GetName() : std::move(dbgName)) - , Length_(File_.GetLength()) - , Mode_(om) - { + , Length_(File_.GetLength()) + , Mode_(om) + { CheckFile(); CreateMapping(); - } - + } + inline bool IsOpen() const noexcept { - return File_.IsOpen() -#if defined(_win_) + return File_.IsOpen() +#if defined(_win_) && Mapping_ != nullptr #endif - ; - } - + ; + } + inline bool IsWritable() const noexcept { return (Mode_ & oRdWr || Mode_ & oCopyOnWr); } inline TMapResult Map(i64 offset, size_t size) { - assert(File_.IsOpen()); + assert(File_.IsOpen()); - if (offset > Length_) { + if (offset > Length_) { ythrow yexception() << "Can't map something at offset " << offset << " of '" << DbgName_ << "' with length " << Length_; - } + } - if (offset + (i64)size > Length_) { + if (offset + (i64)size > Length_) { ythrow yexception() << "Can't map " << (unsigned long)size << " bytes at offset " << offset << " of '" << DbgName_ << "' with length " << Length_; - } - - TMapResult result; - - i64 base = DownToGranularity(offset); - result.Head = (i32)(offset - base); - size += result.Head; - -#if defined(_win_) + } + + TMapResult result; + + i64 base = DownToGranularity(offset); + result.Head = (i32)(offset - base); + size += result.Head; + +#if defined(_win_) result.Ptr = MapViewOfFile(Mapping_, - (Mode_ & oAccessMask) == oRdOnly ? FILE_MAP_READ : (Mode_ & oAccessMask) == oCopyOnWr ? FILE_MAP_COPY - : FILE_MAP_WRITE, + (Mode_ & oAccessMask) == oRdOnly ? FILE_MAP_READ : (Mode_ & oAccessMask) == oCopyOnWr ? FILE_MAP_COPY + : FILE_MAP_WRITE, Hi32(base), Lo32(base), size); #else - #if defined(_unix_) - if (Mode_ & oNotGreedy) { - #endif + #if defined(_unix_) + if (Mode_ & oNotGreedy) { + #endif result.Ptr = mmap((caddr_t) nullptr, size, ModeToMmapProt(Mode_), ModeToMmapFlags(Mode_), File_.GetHandle(), base); - - if (result.Ptr == (char*)(-1)) { + + if (result.Ptr == (char*)(-1)) { result.Ptr = nullptr; } - #if defined(_unix_) - } else { + #if defined(_unix_) + } else { result.Ptr = PtrStart_ ? static_cast<caddr_t>(PtrStart_) + base : nullptr; - } - #endif + } + #endif #endif if (result.Ptr != nullptr || size == 0) { // allow map of size 0 - result.Size = size; - } else { + result.Size = size; + } else { ythrow yexception() << "Can't map " << (unsigned long)size << " bytes at offset " << offset << " of '" << DbgName_ << "': " << LastSystemErrorText(); - } + } NSan::Unpoison(result.Ptr, result.Size); - if (Mode_ & oPrecharge) { + if (Mode_ & oPrecharge) { NPrivate::Precharge(result.Ptr, result.Size, 0, result.Size); - } - - return result; - } - -#if defined(_win_) - inline bool Unmap(void* ptr, size_t) { - return ::UnmapViewOfFile(ptr) != FALSE; - } + } + + return result; + } + +#if defined(_win_) + inline bool Unmap(void* ptr, size_t) { + return ::UnmapViewOfFile(ptr) != FALSE; + } #else - inline bool Unmap(void* ptr, size_t size) { - #if defined(_unix_) - if (Mode_ & oNotGreedy) { - #endif - return size == 0 || ::munmap(static_cast<caddr_t>(ptr), size) == 0; - #if defined(_unix_) - } else { - return true; - } - #endif - } + inline bool Unmap(void* ptr, size_t size) { + #if defined(_unix_) + if (Mode_ & oNotGreedy) { + #endif + return size == 0 || ::munmap(static_cast<caddr_t>(ptr), size) == 0; + #if defined(_unix_) + } else { + return true; + } + #endif + } #endif - void SetSequential() { -#if defined(_unix_) + void SetSequential() { +#if defined(_unix_) if (!(Mode_ & oNotGreedy) && Length_) { MadviseSequentialAccess(PtrStart_, Length_); } -#endif - } +#endif + } - void Evict(void* ptr, size_t len) { + void Evict(void* ptr, size_t len) { MadviseEvict(ptr, len); - } + } - void Evict() { -#if defined(_unix_) + void Evict() { +#if defined(_unix_) // Evict(PtrStart_, Length_); -#endif - } - +#endif + } + inline ~TImpl() { -#if defined(_win_) - if (Mapping_) { - ::CloseHandle(Mapping_); // != FALSE +#if defined(_win_) + if (Mapping_) { + ::CloseHandle(Mapping_); // != FALSE Mapping_ = nullptr; } #elif defined(_unix_) - if (PtrStart_) { - munmap((caddr_t)PtrStart_, Length_); - } + if (PtrStart_) { + munmap((caddr_t)PtrStart_, Length_); + } #endif - } - + } + inline i64 Length() const noexcept { - return Length_; - } - + return Length_; + } + inline TFile GetFile() const noexcept { - return File_; - } - + return File_; + } + inline TString GetDbgName() const { return DbgName_; } @@ -333,18 +333,18 @@ public: return Mode_; } -private: - TFile File_; +private: + TFile File_; TString DbgName_; // This string is never used to actually open a file, only in exceptions - i64 Length_; + i64 Length_; EOpenMode Mode_; - -#if defined(_win_) - void* Mapping_; + +#if defined(_win_) + void* Mapping_; #elif defined(_unix_) - void* PtrStart_; -#endif -}; + void* PtrStart_; +#endif +}; TMemoryMap::TMemoryMap(const TString& name) : Impl_(new TImpl(name, EOpenModeFlag::oRdOnly)) @@ -352,15 +352,15 @@ TMemoryMap::TMemoryMap(const TString& name) } TMemoryMap::TMemoryMap(const TString& name, EOpenMode om) - : Impl_(new TImpl(name, om)) -{ -} + : Impl_(new TImpl(name, om)) +{ +} TMemoryMap::TMemoryMap(const TString& name, i64 length, EOpenMode om) - : Impl_(new TImpl(name, length, om)) -{ -} - + : Impl_(new TImpl(name, length, om)) +{ +} + TMemoryMap::TMemoryMap(FILE* f, TString dbgName) : Impl_(new TImpl(f, EOpenModeFlag::oRdOnly, std::move(dbgName))) { @@ -368,9 +368,9 @@ TMemoryMap::TMemoryMap(FILE* f, TString dbgName) TMemoryMap::TMemoryMap(FILE* f, EOpenMode om, TString dbgName) : Impl_(new TImpl(f, om, std::move(dbgName))) -{ -} - +{ +} + TMemoryMap::TMemoryMap(const TFile& file, TString dbgName) : Impl_(new TImpl(file, EOpenModeFlag::oRdOnly, std::move(dbgName))) { @@ -378,23 +378,23 @@ TMemoryMap::TMemoryMap(const TFile& file, TString dbgName) TMemoryMap::TMemoryMap(const TFile& file, EOpenMode om, TString dbgName) : Impl_(new TImpl(file, om, std::move(dbgName))) -{ -} - +{ +} + TMemoryMap::~TMemoryMap() = default; - + TMemoryMap::TMapResult TMemoryMap::Map(i64 offset, size_t size) { return Impl_->Map(offset, size); -} - -bool TMemoryMap::Unmap(void* ptr, size_t size) { - return Impl_->Unmap(ptr, size); -} - -bool TMemoryMap::Unmap(TMapResult region) { - return Unmap(region.Ptr, region.Size); -} - +} + +bool TMemoryMap::Unmap(void* ptr, size_t size) { + return Impl_->Unmap(ptr, size); +} + +bool TMemoryMap::Unmap(TMapResult region) { + return Unmap(region.Ptr, region.Size); +} + void TMemoryMap::ResizeAndReset(i64 size) { EOpenMode om = Impl_->GetMode(); TFile file = GetFile(); @@ -408,7 +408,7 @@ TMemoryMap::TMapResult TMemoryMap::ResizeAndRemap(i64 offset, size_t size) { } void TMemoryMap::SetSequential() { - Impl_->SetSequential(); + Impl_->SetSequential(); } void TMemoryMap::Evict(void* ptr, size_t len) { @@ -420,13 +420,13 @@ void TMemoryMap::Evict() { } i64 TMemoryMap::Length() const noexcept { - return Impl_->Length(); -} - + return Impl_->Length(); +} + bool TMemoryMap::IsOpen() const noexcept { - return Impl_->IsOpen(); -} - + return Impl_->IsOpen(); +} + bool TMemoryMap::IsWritable() const noexcept { return Impl_->IsWritable(); } @@ -436,67 +436,67 @@ TMemoryMap::EOpenMode TMemoryMap::GetMode() const noexcept { } TFile TMemoryMap::GetFile() const noexcept { - return Impl_->GetFile(); + return Impl_->GetFile(); } TFileMap::TFileMap(const TMemoryMap& map) noexcept - : Map_(map) -{ -} - + : Map_(map) +{ +} + TFileMap::TFileMap(const TString& name) : Map_(name) { } TFileMap::TFileMap(const TString& name, EOpenMode om) - : Map_(name, om) -{ -} + : Map_(name, om) +{ +} TFileMap::TFileMap(const TString& name, i64 length, EOpenMode om) - : Map_(name, length, om) -{ -} + : Map_(name, length, om) +{ +} TFileMap::TFileMap(FILE* f, EOpenMode om, TString dbgName) : Map_(f, om, dbgName) -{ -} +{ +} TFileMap::TFileMap(const TFile& file, EOpenMode om, TString dbgName) : Map_(file, om, dbgName) -{ -} +{ +} TFileMap::TFileMap(const TFileMap& fm) noexcept - : Map_(fm.Map_) -{ -} + : Map_(fm.Map_) +{ +} void TFileMap::Flush(void* ptr, size_t size, bool sync) { Y_ASSERT(ptr >= Ptr()); Y_ASSERT(static_cast<char*>(ptr) + size <= static_cast<char*>(Ptr()) + MappedSize()); - if (!Region_.IsMapped()) { - return; - } - -#if defined(_win_) + if (!Region_.IsMapped()) { + return; + } + +#if defined(_win_) if (sync) { FlushViewOfFile(ptr, size); } #else msync(ptr, size, sync ? MS_SYNC : MS_ASYNC); #endif -} +} TFileMap::TMapResult TFileMap::Map(i64 offset, size_t size) { - Unmap(); + Unmap(); Region_ = Map_.Map(offset, size); return Region_; -} - +} + TFileMap::TMapResult TFileMap::ResizeAndRemap(i64 offset, size_t size) { // explicit Unmap() is required because in oNotGreedy mode the Map_ object doesn't own the mapped area Unmap(); @@ -504,24 +504,24 @@ TFileMap::TMapResult TFileMap::ResizeAndRemap(i64 offset, size_t size) { return Region_; } -void TFileMap::Unmap() { - if (!Region_.IsMapped()) { - return; +void TFileMap::Unmap() { + if (!Region_.IsMapped()) { + return; } - if (Map_.Unmap(Region_)) { - Region_.Reset(); - } else { + if (Map_.Unmap(Region_)) { + Region_.Reset(); + } else { ythrow yexception() << "can't unmap file"; } -} +} TFileMap::~TFileMap() { - try { + try { // explicit Unmap() is required because in oNotGreedy mode the Map_ object doesn't own the mapped area - Unmap(); - } catch (...) { - // ¯\_(ツ)_/¯ + Unmap(); + } catch (...) { + // ¯\_(ツ)_/¯ } } @@ -529,57 +529,57 @@ void TFileMap::Precharge(size_t pos, size_t size) const { NPrivate::Precharge(Ptr(), MappedSize(), pos, size); } -TMappedAllocation::TMappedAllocation(size_t size, bool shared, void* addr) +TMappedAllocation::TMappedAllocation(size_t size, bool shared, void* addr) : Ptr_(nullptr) - , Size_(0) - , Shared_(shared) -#if defined(_win_) + , Size_(0) + , Shared_(shared) +#if defined(_win_) , Mapping_(nullptr) #endif { - if (size != 0) { - Alloc(size, addr); - } + if (size != 0) { + Alloc(size, addr); + } } -void* TMappedAllocation::Alloc(size_t size, void* addr) { +void* TMappedAllocation::Alloc(size_t size, void* addr) { assert(Ptr_ == nullptr); -#if defined(_win_) - (void)addr; +#if defined(_win_) + (void)addr; Mapping_ = CreateFileMapping((HANDLE)-1, nullptr, PAGE_READWRITE, 0, size ? size : 1, nullptr); - Ptr_ = MapViewOfFile(Mapping_, FILE_MAP_WRITE, 0, 0, size ? size : 1); + Ptr_ = MapViewOfFile(Mapping_, FILE_MAP_WRITE, 0, 0, size ? size : 1); #else - Ptr_ = mmap(addr, size, PROT_READ | PROT_WRITE, (Shared_ ? MAP_SHARED : MAP_PRIVATE) | MAP_ANON, -1, 0); - - if (Ptr_ == (void*)MAP_FAILED) { + Ptr_ = mmap(addr, size, PROT_READ | PROT_WRITE, (Shared_ ? MAP_SHARED : MAP_PRIVATE) | MAP_ANON, -1, 0); + + if (Ptr_ == (void*)MAP_FAILED) { Ptr_ = nullptr; } #endif - if (Ptr_ != nullptr) { - Size_ = size; - } - return Ptr_; + if (Ptr_ != nullptr) { + Size_ = size; + } + return Ptr_; } -void TMappedAllocation::Dealloc() { - if (Ptr_ == nullptr) { +void TMappedAllocation::Dealloc() { + if (Ptr_ == nullptr) { return; - } -#if defined(_win_) - UnmapViewOfFile(Ptr_); - CloseHandle(Mapping_); + } +#if defined(_win_) + UnmapViewOfFile(Ptr_); + CloseHandle(Mapping_); Mapping_ = nullptr; #else - munmap((caddr_t)Ptr_, Size_); + munmap((caddr_t)Ptr_, Size_); #endif Ptr_ = nullptr; - Size_ = 0; + Size_ = 0; } -void TMappedAllocation::swap(TMappedAllocation& with) { - DoSwap(Ptr_, with.Ptr_); - DoSwap(Size_, with.Size_); -#if defined(_win_) - DoSwap(Mapping_, with.Mapping_); +void TMappedAllocation::swap(TMappedAllocation& with) { + DoSwap(Ptr_, with.Ptr_); + DoSwap(Size_, with.Size_); +#if defined(_win_) + DoSwap(Mapping_, with.Mapping_); #endif } diff --git a/util/system/filemap.h b/util/system/filemap.h index 11be64bff4..16ccb6df5d 100644 --- a/util/system/filemap.h +++ b/util/system/filemap.h @@ -1,52 +1,52 @@ #pragma once -#include "file.h" -#include "align.h" -#include "yassert.h" - +#include "file.h" +#include "align.h" +#include "yassert.h" + #include <util/generic/noncopyable.h> #include <util/generic/ptr.h> #include <util/generic/utility.h> #include <util/generic/yexception.h> #include <util/generic/flags.h> #include <util/generic/string.h> - -#include <new> -#include <cstdio> - + +#include <new> +#include <cstdio> + namespace NPrivate { // NB: use TFileMap::Precharge() and TFileMappedArray::Prechage() void Precharge(const void* data, size_t dataSize, size_t offset, size_t size); } -struct TMemoryMapCommon { - struct TMapResult { +struct TMemoryMapCommon { + struct TMapResult { inline size_t MappedSize() const noexcept { - return Size - Head; - } - + return Size - Head; + } + inline void* MappedData() const noexcept { return Ptr ? (void*)((char*)Ptr + Head) : nullptr; - } - + } + inline bool IsMapped() const noexcept { return Ptr != nullptr; - } - + } + inline void Reset() noexcept { Ptr = nullptr; - Size = 0; - Head = 0; - } - - void* Ptr; - size_t Size; - i32 Head; + Size = 0; + Head = 0; + } + + void* Ptr; + size_t Size; + i32 Head; TMapResult(void) noexcept { Reset(); - } - }; + } + }; enum EOpenModeFlag { oRdOnly = 1, @@ -57,31 +57,31 @@ struct TMemoryMapCommon { oNotGreedy = 8, oPrecharge = 16, oPopulate = 32, // Populate page table entries (see mmap's MAP_POPULATE) - }; + }; Y_DECLARE_FLAGS(EOpenMode, EOpenModeFlag) /** * Name that will be printed in exceptions if not specified. * Overridden by name obtained from `TFile` if it's not empty. */ - static TString UnknownFileName(); -}; + static TString UnknownFileName(); +}; Y_DECLARE_OPERATORS_FOR_FLAGS(TMemoryMapCommon::EOpenMode) -class TMemoryMap: public TMemoryMapCommon { -public: +class TMemoryMap: public TMemoryMapCommon { +public: explicit TMemoryMap(const TString& name); explicit TMemoryMap(const TString& name, EOpenMode om); TMemoryMap(const TString& name, i64 length, EOpenMode om); - TMemoryMap(FILE* f, TString dbgName = UnknownFileName()); - TMemoryMap(FILE* f, EOpenMode om, TString dbgName = UnknownFileName()); - TMemoryMap(const TFile& file, TString dbgName = UnknownFileName()); - TMemoryMap(const TFile& file, EOpenMode om, TString dbgName = UnknownFileName()); + TMemoryMap(FILE* f, TString dbgName = UnknownFileName()); + TMemoryMap(FILE* f, EOpenMode om, TString dbgName = UnknownFileName()); + TMemoryMap(const TFile& file, TString dbgName = UnknownFileName()); + TMemoryMap(const TFile& file, EOpenMode om, TString dbgName = UnknownFileName()); ~TMemoryMap(); TMapResult Map(i64 offset, size_t size); - bool Unmap(TMapResult region); + bool Unmap(TMapResult region); void ResizeAndReset(i64 size); TMapResult ResizeAndRemap(i64 offset, size_t size); @@ -92,59 +92,59 @@ public: EOpenMode GetMode() const noexcept; TFile GetFile() const noexcept; - void SetSequential(); - void Evict(void* ptr, size_t len); - void Evict(); + void SetSequential(); + void Evict(void* ptr, size_t len); + void Evict(); - /* - * deprecated - */ - bool Unmap(void* ptr, size_t size); + /* + * deprecated + */ + bool Unmap(void* ptr, size_t size); -private: - class TImpl; - TSimpleIntrusivePtr<TImpl> Impl_; -}; +private: + class TImpl; + TSimpleIntrusivePtr<TImpl> Impl_; +}; -class TFileMap: public TMemoryMapCommon { -public: +class TFileMap: public TMemoryMapCommon { +public: TFileMap(const TMemoryMap& map) noexcept; TFileMap(const TString& name); TFileMap(const TString& name, EOpenMode om); TFileMap(const TString& name, i64 length, EOpenMode om); - TFileMap(FILE* f, EOpenMode om = oRdOnly, TString dbgName = UnknownFileName()); - TFileMap(const TFile& file, EOpenMode om = oRdOnly, TString dbgName = UnknownFileName()); + TFileMap(FILE* f, EOpenMode om = oRdOnly, TString dbgName = UnknownFileName()); + TFileMap(const TFile& file, EOpenMode om = oRdOnly, TString dbgName = UnknownFileName()); TFileMap(const TFileMap& fm) noexcept; ~TFileMap(); TMapResult Map(i64 offset, size_t size); TMapResult ResizeAndRemap(i64 offset, size_t size); - void Unmap(); + void Unmap(); + + void Flush(void* ptr, size_t size) { + Flush(ptr, size, true); + } - void Flush(void* ptr, size_t size) { - Flush(ptr, size, true); - } + void Flush() { + Flush(Ptr(), MappedSize()); + } - void Flush() { - Flush(Ptr(), MappedSize()); - } + void FlushAsync(void* ptr, size_t size) { + Flush(ptr, size, false); + } - void FlushAsync(void* ptr, size_t size) { - Flush(ptr, size, false); - } - - void FlushAsync() { - FlushAsync(Ptr(), MappedSize()); - } + void FlushAsync() { + FlushAsync(Ptr(), MappedSize()); + } inline i64 Length() const noexcept { - return Map_.Length(); - } + return Map_.Length(); + } inline bool IsOpen() const noexcept { - return Map_.IsOpen(); - } + return Map_.IsOpen(); + } inline bool IsWritable() const noexcept { return Map_.IsWritable(); @@ -155,16 +155,16 @@ public: } inline void* Ptr() const noexcept { - return Region_.MappedData(); - } + return Region_.MappedData(); + } inline size_t MappedSize() const noexcept { - return Region_.MappedSize(); - } + return Region_.MappedSize(); + } TFile GetFile() const noexcept { - return Map_.GetFile(); - } + return Map_.GetFile(); + } void Precharge(size_t pos = 0, size_t size = (size_t)-1) const; @@ -176,31 +176,31 @@ public: Map_.Evict(); } -private: - void Flush(void* ptr, size_t size, bool sync); +private: + void Flush(void* ptr, size_t size, bool sync); - TMemoryMap Map_; - TMapResult Region_; -}; + TMemoryMap Map_; + TMapResult Region_; +}; -template <class T> +template <class T> class TFileMappedArray { private: const T* Ptr_; const T* End_; - size_t Size_; - char DummyData_[sizeof(T) + PLATFORM_DATA_ALIGN]; - mutable THolder<T, TDestructor> Dummy_; + size_t Size_; + char DummyData_[sizeof(T) + PLATFORM_DATA_ALIGN]; + mutable THolder<T, TDestructor> Dummy_; THolder<TFileMap> DataHolder_; - + public: - TFileMappedArray() + TFileMappedArray() : Ptr_(nullptr) , End_(nullptr) - , Size_(0) - { - } - ~TFileMappedArray() { + , Size_(0) + { + } + ~TFileMappedArray() { Ptr_ = nullptr; End_ = nullptr; } @@ -215,65 +215,65 @@ public: void Term() { DataHolder_.Destroy(); Ptr_ = nullptr; - Size_ = 0; + Size_ = 0; End_ = nullptr; } void Precharge() { DataHolder_->Precharge(); } - const T& operator[](size_t pos) const { + const T& operator[](size_t pos) const { Y_ASSERT(pos < size()); - return Ptr_[pos]; + return Ptr_[pos]; } /// for STL compatibility only, Size() usage is recommended size_t size() const { - return Size_; + return Size_; } size_t Size() const { return Size_; } const T& GetAt(size_t pos) const { - if (pos < Size_) - return Ptr_[pos]; - return Dummy(); + if (pos < Size_) + return Ptr_[pos]; + return Dummy(); } - void SetDummy(const T& n_Dummy) { - Dummy_.Destroy(); - Dummy_.Reset(new (DummyData()) T(n_Dummy)); + void SetDummy(const T& n_Dummy) { + Dummy_.Destroy(); + Dummy_.Reset(new (DummyData()) T(n_Dummy)); } inline char* DummyData() const noexcept { - return AlignUp((char*)DummyData_); - } - inline const T& Dummy() const { - if (!Dummy_) { - Dummy_.Reset(new (DummyData()) T()); - } - - return *Dummy_; - } + return AlignUp((char*)DummyData_); + } + inline const T& Dummy() const { + if (!Dummy_) { + Dummy_.Reset(new (DummyData()) T()); + } + + return *Dummy_; + } /// for STL compatibility only, Empty() usage is recommended - Y_PURE_FUNCTION bool empty() const noexcept { + Y_PURE_FUNCTION bool empty() const noexcept { return Empty(); } - Y_PURE_FUNCTION bool Empty() const noexcept { - return 0 == Size_; + Y_PURE_FUNCTION bool Empty() const noexcept { + return 0 == Size_; } /// for STL compatibility only, Begin() usage is recommended const T* begin() const noexcept { return Begin(); } const T* Begin() const noexcept { - return Ptr_; + return Ptr_; } /// for STL compatibility only, End() usage is recommended const T* end() const noexcept { - return End_; + return End_; } const T* End() const noexcept { return End_; } - + private: void DoInit(const TString& fileName) { DataHolder_->Map(0, DataHolder_->Length()); @@ -287,10 +287,10 @@ private: } }; -class TMappedAllocation: TMoveOnly { +class TMappedAllocation: TMoveOnly { public: TMappedAllocation(size_t size = 0, bool shared = false, void* addr = nullptr); - ~TMappedAllocation() { + ~TMappedAllocation() { Dealloc(); } TMappedAllocation(TMappedAllocation&& other) { @@ -303,22 +303,22 @@ public: void* Alloc(size_t size, void* addr = nullptr); void Dealloc(); void* Ptr() const { - return Ptr_; + return Ptr_; } char* Data(ui32 pos = 0) const { return (char*)(Ptr_ ? ((char*)Ptr_ + pos) : nullptr); } char* Begin() const noexcept { - return (char*)Ptr(); - } + return (char*)Ptr(); + } char* End() const noexcept { - return Begin() + MappedSize(); - } + return Begin() + MappedSize(); + } size_t MappedSize() const { - return Size_; + return Size_; } - void swap(TMappedAllocation& with); - + void swap(TMappedAllocation& with); + private: void* Ptr_ = nullptr; size_t Size_ = 0; @@ -328,26 +328,26 @@ private: #endif }; -template <class T> -class TMappedArray: private TMappedAllocation { +template <class T> +class TMappedArray: private TMappedAllocation { public: - TMappedArray(size_t siz = 0) - : TMappedAllocation(0) - { + TMappedArray(size_t siz = 0) + : TMappedAllocation(0) + { if (siz) Create(siz); } - ~TMappedArray() { + ~TMappedArray() { Destroy(); } - T* Create(size_t siz) { + T* Create(size_t siz) { Y_ASSERT(MappedSize() == 0 && Ptr() == nullptr); T* arr = (T*)Alloc((sizeof(T) * siz)); if (!arr) return nullptr; Y_ASSERT(MappedSize() == sizeof(T) * siz); for (size_t n = 0; n < siz; n++) - new (&arr[n]) T(); + new (&arr[n]) T(); return arr; } void Destroy() { @@ -358,24 +358,24 @@ public: Dealloc(); } } - T& operator[](size_t pos) { + T& operator[](size_t pos) { Y_ASSERT(pos < size()); return ((T*)Ptr())[pos]; } - const T& operator[](size_t pos) const { + const T& operator[](size_t pos) const { Y_ASSERT(pos < size()); return ((T*)Ptr())[pos]; } - T* begin() { + T* begin() { return (T*)Ptr(); } - T* end() { + T* end() { return (T*)((char*)Ptr() + MappedSize()); } size_t size() const { - return MappedSize() / sizeof(T); + return MappedSize() / sizeof(T); } - void swap(TMappedArray<T>& with) { - TMappedAllocation::swap(with); + void swap(TMappedArray<T>& with) { + TMappedAllocation::swap(with); } }; diff --git a/util/system/filemap_ut.cpp b/util/system/filemap_ut.cpp index 73f109dc88..440e8635c4 100644 --- a/util/system/filemap_ut.cpp +++ b/util/system/filemap_ut.cpp @@ -1,7 +1,7 @@ #include <library/cpp/testing/unittest/registar.h> - + #ifdef _unix_ - #include <sys/resource.h> + #include <sys/resource.h> #endif #include "filemap.h" @@ -17,7 +17,7 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { void BasicTest(TMemoryMapCommon::EOpenMode mode) { char data[] = "abcdefgh"; - TFile file(FileName_, CreateAlways | WrOnly); + TFile file(FileName_, CreateAlways | WrOnly); file.Write(static_cast<void*>(data), sizeof(data)); file.Close(); @@ -31,18 +31,18 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { static_cast<char*>(mappedFile.Ptr())[i] = data[i] + 1; } mappedFile.Flush(); - + TFileMap::TMapResult mapResult = mappedFile.Map(2, 2); UNIT_ASSERT(mapResult.MappedSize() == 2); UNIT_ASSERT(mapResult.MappedData() == mappedFile.Ptr()); UNIT_ASSERT(mappedFile.MappedSize() == 2); UNIT_ASSERT(static_cast<char*>(mappedFile.Ptr())[0] == 'd' && static_cast<char*>(mappedFile.Ptr())[1] == 'e'); - + mappedFile.Unmap(); - UNIT_ASSERT(mappedFile.MappedSize() == 0); - - FILE* f = fopen(FileName_, "rb"); - TFileMap mappedFile2(f); + UNIT_ASSERT(mappedFile.MappedSize() == 0); + + FILE* f = fopen(FileName_, "rb"); + TFileMap mappedFile2(f); mappedFile2.Map(0, mappedFile2.Length()); UNIT_ASSERT(mappedFile2.MappedSize() == sizeof(data)); UNIT_ASSERT(static_cast<char*>(mappedFile2.Ptr())[0] == data[0] + 1); @@ -50,7 +50,7 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { } NFs::Remove(FileName_); } - + Y_UNIT_TEST(TestFileMap) { BasicTest(TMemoryMapCommon::oRdWr); } @@ -126,46 +126,46 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { NFs::Remove(FileName_); } -#if defined(_asan_enabled_) || defined(_msan_enabled_) -//setrlimit incompatible with asan runtime -#elif defined(_cygwin_) -//cygwin is not real unix :( -#else +#if defined(_asan_enabled_) || defined(_msan_enabled_) +//setrlimit incompatible with asan runtime +#elif defined(_cygwin_) +//cygwin is not real unix :( +#else Y_UNIT_TEST(TestNotGreedy) { unsigned page[4096 / sizeof(unsigned)]; - - #if defined(_unix_) + + #if defined(_unix_) // Temporary limit allowed virtual memory size to 1Gb struct rlimit rlim; - - if (getrlimit(RLIMIT_AS, &rlim)) { + + if (getrlimit(RLIMIT_AS, &rlim)) { throw TSystemError() << "Cannot get rlimit for virtual memory"; - } - - rlim_t Limit = 1 * 1024 * 1024 * 1024; - + } + + rlim_t Limit = 1 * 1024 * 1024 * 1024; + if (rlim.rlim_cur > Limit) { rlim.rlim_cur = Limit; - - if (setrlimit(RLIMIT_AS, &rlim)) { + + if (setrlimit(RLIMIT_AS, &rlim)) { throw TSystemError() << "Cannot set rlimit for virtual memory to 1Gb"; - } + } } - #endif + #endif // Make a 128M test file try { TFile file(FileName_, CreateAlways | WrOnly); - - for (unsigned pages = 128 * 1024 * 1024 / sizeof(page), i = 0; pages--; i++) { - std::fill(page, page + sizeof(page) / sizeof(*page), i); + + for (unsigned pages = 128 * 1024 * 1024 / sizeof(page), i = 0; pages--; i++) { + std::fill(page, page + sizeof(page) / sizeof(*page), i); file.Write(page, sizeof(page)); } - + file.Close(); - + // Make 16 maps of our file, which would require 16*128M = 2Gb and exceed our 1Gb limit TVector<THolder<TFileMap>> maps; - + for (int i = 0; i < 16; ++i) { maps.emplace_back(MakeHolder<TFileMap>(FileName_, TMemoryMapCommon::oRdOnly | TMemoryMapCommon::oNotGreedy)); maps.back()->Map(i * sizeof(page), sizeof(page)); @@ -174,59 +174,59 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { // Oh, good, we're not dead yet for (int i = 0; i < 16; ++i) { TFileMap& map = *maps[i]; - - UNIT_ASSERT_EQUAL(map.Length(), 128 * 1024 * 1024); + + UNIT_ASSERT_EQUAL(map.Length(), 128 * 1024 * 1024); UNIT_ASSERT_EQUAL(map.MappedSize(), sizeof(page)); - - const int* mappedPage = (const int*)map.Ptr(); - - for (size_t j = 0; j < sizeof(page) / sizeof(*page); ++j) { + + const int* mappedPage = (const int*)map.Ptr(); + + for (size_t j = 0; j < sizeof(page) / sizeof(*page); ++j) { UNIT_ASSERT_EQUAL(mappedPage[j], i); - } + } } - - #if defined(_unix_) + + #if defined(_unix_) // Restore limits and cleanup rlim.rlim_cur = rlim.rlim_max; - - if (setrlimit(RLIMIT_AS, &rlim)) { + + if (setrlimit(RLIMIT_AS, &rlim)) { throw TSystemError() << "Cannot restore rlimit for virtual memory"; - } - #endif + } + #endif maps.clear(); NFs::Remove(FileName_); - } catch (...) { - // TODO: RAII'ize all this stuff - #if defined(_unix_) + } catch (...) { + // TODO: RAII'ize all this stuff + #if defined(_unix_) rlim.rlim_cur = rlim.rlim_max; - - if (setrlimit(RLIMIT_AS, &rlim)) { + + if (setrlimit(RLIMIT_AS, &rlim)) { throw TSystemError() << "Cannot restore rlimit for virtual memory"; - } - #endif + } + #endif NFs::Remove(FileName_); - + throw; } } -#endif +#endif Y_UNIT_TEST(TestFileMappedArray) { { - TFileMappedArray<ui32> mappedArray; + TFileMappedArray<ui32> mappedArray; ui32 data[] = {123, 456, 789, 10}; size_t sz = sizeof(data) / sizeof(data[0]); - - TFile file(FileName_, CreateAlways | WrOnly); + + TFile file(FileName_, CreateAlways | WrOnly); file.Write(static_cast<void*>(data), sizeof(data)); file.Close(); mappedArray.Init(FileName_); // actual test begin UNIT_ASSERT(mappedArray.Size() == sz); - for (size_t i = 0; i < sz; ++i) { + for (size_t i = 0; i < sz; ++i) { UNIT_ASSERT(mappedArray[i] == data[i]); - } + } UNIT_ASSERT(mappedArray.GetAt(mappedArray.Size()) == 0); UNIT_ASSERT(*mappedArray.Begin() == data[0]); @@ -242,9 +242,9 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { // actual test begin UNIT_ASSERT(mappedArray.Size() == sz); - for (size_t i = 0; i < sz; ++i) { + for (size_t i = 0; i < sz; ++i) { UNIT_ASSERT(mappedArray[i] == data[i]); - } + } UNIT_ASSERT(mappedArray.GetAt(mappedArray.Size()) == 0); UNIT_ASSERT(*mappedArray.Begin() == data[0]); @@ -252,7 +252,7 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { UNIT_ASSERT(!mappedArray.Empty()); // actual test end - file = TFile(FileName_, WrOnly); + file = TFile(FileName_, WrOnly); file.Seek(0, sEnd); file.Write("x", 1); file.Close(); @@ -270,9 +270,9 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { Y_UNIT_TEST(TestMappedArray) { ui32 sz = 10; - - TMappedArray<ui32> mappedArray; - + + TMappedArray<ui32> mappedArray; + ui32* ptr = mappedArray.Create(sz); UNIT_ASSERT(ptr != nullptr); UNIT_ASSERT(mappedArray.size() == sz); @@ -285,7 +285,7 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { UNIT_ASSERT(mappedArray[i] == i); } - TMappedArray<ui32> mappedArray2(1000); + TMappedArray<ui32> mappedArray2(1000); mappedArray.swap(mappedArray2); UNIT_ASSERT(mappedArray.size() == 1000 && mappedArray2.size() == sz); } @@ -299,10 +299,10 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { try { TMemoryMap mappedMem(f); mappedMem.Map(mappedMem.Length() / 2, mappedMem.Length() + 100); // overflow - UNIT_ASSERT(0); // should not go here - } catch (yexception& exc) { + UNIT_ASSERT(0); // should not go here + } catch (yexception& exc) { TString text = exc.what(); // exception should contain failed file name - UNIT_ASSERT(text.find(TMemoryMapCommon::UnknownFileName()) != TString::npos); + UNIT_ASSERT(text.find(TMemoryMapCommon::UnknownFileName()) != TString::npos); fclose(f); } @@ -310,8 +310,8 @@ Y_UNIT_TEST_SUITE(TFileMapTest) { try { TMemoryMap mappedMem(fileForMap); mappedMem.Map(mappedMem.Length() / 2, mappedMem.Length() + 100); // overflow - UNIT_ASSERT(0); // should not go here - } catch (yexception& exc) { + UNIT_ASSERT(0); // should not go here + } catch (yexception& exc) { TString text = exc.what(); // exception should contain failed file name UNIT_ASSERT(text.find(FileName_) != TString::npos); } diff --git a/util/system/flock.cpp b/util/system/flock.cpp index fe88fecaff..ed485109d3 100644 --- a/util/system/flock.cpp +++ b/util/system/flock.cpp @@ -1,71 +1,71 @@ -#include "flock.h" +#include "flock.h" #ifndef _unix_ - #include <util/generic/utility.h> + #include <util/generic/utility.h> + + #include "winint.h" + #include <io.h> + #include <errno.h> - #include "winint.h" - #include <io.h> - #include <errno.h> - - #ifdef __cplusplus + #ifdef __cplusplus extern "C" { - #endif + #endif - int flock(int fd, int op) { - return Flock((HANDLE)_get_osfhandle(fd), op); - } + int flock(int fd, int op) { + return Flock((HANDLE)_get_osfhandle(fd), op); + } - int Flock(void* hdl, int op) { - errno = 0; + int Flock(void* hdl, int op) { + errno = 0; - if (hdl == INVALID_HANDLE_VALUE) { - errno = EBADF; - return -1; - } + if (hdl == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } - DWORD low = 1, high = 0; - OVERLAPPED io; + DWORD low = 1, high = 0; + OVERLAPPED io; - Zero(io); + Zero(io); + + UnlockFileEx(hdl, 0, low, high, &io); - UnlockFileEx(hdl, 0, low, high, &io); - - switch (op & ~LOCK_NB) { - case LOCK_EX: - case LOCK_SH: { - auto mode = ((op & ~LOCK_NB) == LOCK_EX) ? LOCKFILE_EXCLUSIVE_LOCK : 0; - if (op & LOCK_NB) { - if (LockFileEx(hdl, mode | LOCKFILE_FAIL_IMMEDIATELY, 0, low, high, &io)) { - return 0; - } else if (GetLastError() == ERROR_LOCK_VIOLATION) { - ClearLastSystemError(); - errno = EWOULDBLOCK; - return -1; - } - } else { - if (LockFileEx(hdl, mode, 0, low, high, &io)) { - return 0; - } + switch (op & ~LOCK_NB) { + case LOCK_EX: + case LOCK_SH: { + auto mode = ((op & ~LOCK_NB) == LOCK_EX) ? LOCKFILE_EXCLUSIVE_LOCK : 0; + if (op & LOCK_NB) { + if (LockFileEx(hdl, mode | LOCKFILE_FAIL_IMMEDIATELY, 0, low, high, &io)) { + return 0; + } else if (GetLastError() == ERROR_LOCK_VIOLATION) { + ClearLastSystemError(); + errno = EWOULDBLOCK; + return -1; + } + } else { + if (LockFileEx(hdl, mode, 0, low, high, &io)) { + return 0; + } } - break; + break; } - case LOCK_UN: - return 0; - break; - default: - break; + case LOCK_UN: + return 0; + break; + default: + break; } - errno = EINVAL; - return -1; + errno = EINVAL; + return -1; } - int fsync(int fd) { - return _commit(fd); - } + int fsync(int fd) { + return _commit(fd); + } - #ifdef __cplusplus + #ifdef __cplusplus } - #endif + #endif #endif diff --git a/util/system/flock.h b/util/system/flock.h index 797b1970a1..991f892ae5 100644 --- a/util/system/flock.h +++ b/util/system/flock.h @@ -1,35 +1,35 @@ #pragma once -#include "error.h" +#include "error.h" #include "defaults.h" #include "file.h" #if defined(_unix_) - #include <sys/file.h> - #include <fcntl.h> - -static inline int Flock(int fd, int op) { - return flock(fd, op); -} + #include <sys/file.h> + #include <fcntl.h> +static inline int Flock(int fd, int op) { + return flock(fd, op); +} + #else // not _unix_ - #ifdef __cplusplus + #ifdef __cplusplus extern "C" { - #endif + #endif - #define LOCK_SH 1 /* shared lock */ - #define LOCK_EX 2 /* exclusive lock */ - #define LOCK_NB 4 /* don't block when locking */ - #define LOCK_UN 8 /* unlock */ + #define LOCK_SH 1 /* shared lock */ + #define LOCK_EX 2 /* exclusive lock */ + #define LOCK_NB 4 /* don't block when locking */ + #define LOCK_UN 8 /* unlock */ - int Flock(void* hndl, int operation); - int flock(int fd, int operation); - int fsync(int fd); + int Flock(void* hndl, int operation); + int flock(int fd, int operation); + int fsync(int fd); - #ifdef __cplusplus + #ifdef __cplusplus } - #endif + #endif #endif // not _unix_ diff --git a/util/system/flock_ut.cpp b/util/system/flock_ut.cpp index b5f6cb5328..58bed0e4ae 100644 --- a/util/system/flock_ut.cpp +++ b/util/system/flock_ut.cpp @@ -1,18 +1,18 @@ -#include "flock.h" +#include "flock.h" #include "file_lock.h" #include "guard.h" -#include "tempfile.h" - +#include "tempfile.h" + #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TFileLockTest) { Y_UNIT_TEST(TestFlock) { - TTempFileHandle tmp("./file"); - - UNIT_ASSERT_EQUAL(Flock(tmp.GetHandle(), LOCK_EX), 0); - UNIT_ASSERT_EQUAL(Flock(tmp.GetHandle(), LOCK_UN), 0); - } - + TTempFileHandle tmp("./file"); + + UNIT_ASSERT_EQUAL(Flock(tmp.GetHandle(), LOCK_EX), 0); + UNIT_ASSERT_EQUAL(Flock(tmp.GetHandle(), LOCK_UN), 0); + } + Y_UNIT_TEST(TestFileLocker) { TTempFileHandle tmp("./file.locker"); TFileLock fileLockExclusive1("./file.locker"); diff --git a/util/system/fs.cpp b/util/system/fs.cpp index d2611a8ccc..d94a70b40e 100644 --- a/util/system/fs.cpp +++ b/util/system/fs.cpp @@ -1,29 +1,29 @@ #include "fs.h" #include "defaults.h" - + #if defined(_win_) - #include "fs_win.h" + #include "fs_win.h" #else - #include <unistd.h> - #include <errno.h> + #include <unistd.h> + #include <errno.h> #endif - + #include <util/generic/yexception.h> #include <util/memory/tempbuf.h> -#include <util/stream/file.h> +#include <util/stream/file.h> #include <util/charset/wide.h> #include <util/folder/iterator.h> #include <util/system/fstat.h> #include <util/folder/path.h> - + bool NFs::Remove(const TString& path) { #if defined(_win_) return NFsPrivate::WinRemove(path); #else return ::remove(path.data()) == 0; #endif -} - +} + void NFs::RemoveRecursive(const TString& path) { static const TStringBuf errStr = "error while removing "; @@ -32,9 +32,9 @@ void NFs::RemoveRecursive(const TString& path) { } if (!TFileStat(path).IsDir()) { - if (!NFs::Remove(path)) { + if (!NFs::Remove(path)) { ythrow TSystemError() << errStr << path << " with cwd (" << NFs::CurrentWorkingDirectory() << ")"; - } + } } TDirIterator dir(path); @@ -45,9 +45,9 @@ void NFs::RemoveRecursive(const TString& path) { case FTS_D: break; default: - if (!NFs::Remove(it->fts_path)) { + if (!NFs::Remove(it->fts_path)) { ythrow TSystemError() << errStr << it->fts_path << " with cwd (" << NFs::CurrentWorkingDirectory() << ")"; - } + } break; } } @@ -85,12 +85,12 @@ bool NFs::MakeDirectoryRecursive(const TString& path, EFilePermissions mode, boo } bool NFs::Rename(const TString& oldPath, const TString& newPath) { -#if defined(_win_) +#if defined(_win_) return NFsPrivate::WinRename(oldPath, newPath); -#else +#else return ::rename(oldPath.data(), newPath.data()) == 0; -#endif -} +#endif +} void NFs::HardLinkOrCopy(const TString& existingPath, const TString& newPath) { if (!NFs::HardLink(existingPath, newPath)) { @@ -99,13 +99,13 @@ void NFs::HardLinkOrCopy(const TString& existingPath, const TString& newPath) { } bool NFs::HardLink(const TString& existingPath, const TString& newPath) { -#if defined(_win_) +#if defined(_win_) return NFsPrivate::WinHardLink(existingPath, newPath); #elif defined(_unix_) return (0 == link(existingPath.data(), newPath.data())); #endif } - + bool NFs::SymLink(const TString& targetPath, const TString& linkPath) { #if defined(_win_) return NFsPrivate::WinSymLink(targetPath, linkPath); @@ -121,12 +121,12 @@ TString NFs::ReadLink(const TString& path) { TTempBuf buf; while (true) { ssize_t r = readlink(path.data(), buf.Data(), buf.Size()); - if (r < 0) { + if (r < 0) { ythrow yexception() << "can't read link " << path << ", errno = " << errno; - } - if (r < (ssize_t)buf.Size()) { + } + if (r < (ssize_t)buf.Size()) { return TString(buf.Data(), r); - } + } buf = TTempBuf(buf.Size() * 2); } #endif @@ -135,16 +135,16 @@ TString NFs::ReadLink(const TString& path) { void NFs::Cat(const TString& dstPath, const TString& srcPath) { TUnbufferedFileInput src(srcPath); TUnbufferedFileOutput dst(TFile(dstPath, ForAppend | WrOnly | Seq)); - - TransferData(&src, &dst); -} - + + TransferData(&src, &dst); +} + void NFs::Copy(const TString& existingPath, const TString& newPath) { TUnbufferedFileInput src(existingPath); TUnbufferedFileOutput dst(TFile(newPath, CreateAlways | WrOnly | Seq)); - - TransferData(&src, &dst); -} + + TransferData(&src, &dst); +} bool NFs::Exists(const TString& path) { #if defined(_win_) @@ -160,9 +160,9 @@ TString NFs::CurrentWorkingDirectory() { #elif defined(_unix_) TTempBuf result; char* r = getcwd(result.Data(), result.Size()); - if (r == nullptr) { + if (r == nullptr) { throw TIoSystemError() << "failed to getcwd"; - } + } return result.Data(); #endif } @@ -173,7 +173,7 @@ void NFs::SetCurrentWorkingDirectory(TString path) { #else bool ok = !chdir(path.data()); #endif - if (!ok) { + if (!ok) { ythrow TSystemError() << "failed to change directory to " << path.Quote(); - } + } } diff --git a/util/system/fs.h b/util/system/fs.h index 237daf2d2d..9f3dc25ad7 100644 --- a/util/system/fs.h +++ b/util/system/fs.h @@ -1,9 +1,9 @@ #pragma once - + #include <util/generic/flags.h> #include <util/generic/string.h> #include <util/generic/yexception.h> - + namespace NFs { enum EFilePermission { FP_ALL_EXEC = 01, @@ -151,6 +151,6 @@ namespace NFs { Y_ENSURE_EX(Exists(path), TFileError{} << "Path " << path << " does not exists (checked from cwd:" << NFs::CurrentWorkingDirectory() << ")"); return path; } -} +} Y_DECLARE_OPERATORS_FOR_FLAGS(NFs::EFilePermissions) diff --git a/util/system/fs_ut.cpp b/util/system/fs_ut.cpp index de071ebf55..e27a52d73a 100644 --- a/util/system/fs_ut.cpp +++ b/util/system/fs_ut.cpp @@ -2,9 +2,9 @@ #include <library/cpp/testing/unittest/registar.h> -#include "file.h" -#include "sysstat.h" -#include "fstat.h" +#include "file.h" +#include "sysstat.h" +#include "fstat.h" #include <util/folder/dirut.h> #include <util/folder/path.h> @@ -14,16 +14,16 @@ class TFsTest: public TTestBase { UNIT_TEST_SUITE(TFsTest); UNIT_TEST(TestCreateRemove); UNIT_TEST(TestRename); - UNIT_TEST(TestSymlink); + UNIT_TEST(TestSymlink); UNIT_TEST(TestHardlink); UNIT_TEST(TestCwdOpts); UNIT_TEST(TestEnsureExists); UNIT_TEST_SUITE_END(); - -public: + +public: void TestCreateRemove(); void TestRename(); - void TestSymlink(); + void TestSymlink(); void TestHardlink(); void TestCwdOpts(); void TestEnsureExists(); @@ -96,7 +96,7 @@ void TFsTest::TestCreateRemove() { UNIT_ASSERT(!NFs::Exists(dir1)); } -void RunRenameTest(TFsPath src, TFsPath dst) { +void RunRenameTest(TFsPath src, TFsPath dst) { // if previous running was failed TFsPath dir1 = "dir"; TFsPath dir2 = "dst_dir"; @@ -144,7 +144,7 @@ void RunRenameTest(TFsPath src, TFsPath dst) { UNIT_ASSERT(NFs::Remove(dir2)); } -void TFsTest::TestRename() { +void TFsTest::TestRename() { RunRenameTest("src.txt", "dst.txt"); RunRenameTest("src_абвг.txt", "dst_абвг.txt"); } @@ -276,7 +276,7 @@ static void RunSymLinkTest(TString fileLocalName, TString symLinkName) { UNIT_ASSERT(NFs::Remove(subDir)); } -void TFsTest::TestSymlink() { +void TFsTest::TestSymlink() { // if previous running was failed RunSymLinkTest("f.txt", "fl.txt"); RunSymLinkTest("f_абвг.txt", "fl_абвг.txt"); //utf-8 names diff --git a/util/system/fs_win.cpp b/util/system/fs_win.cpp index a410ccac06..4498371365 100644 --- a/util/system/fs_win.cpp +++ b/util/system/fs_win.cpp @@ -4,38 +4,38 @@ #include <util/folder/dirut.h> #include <util/charset/wide.h> -#include "file.h" +#include "file.h" #include <winioctl.h> namespace NFsPrivate { static LPCWSTR UTF8ToWCHAR(const TStringBuf str, TUtf16String& wstr) { wstr.resize(str.size()); - size_t written = 0; + size_t written = 0; if (!UTF8ToWide(str.data(), str.size(), wstr.begin(), written)) return nullptr; - wstr.erase(written); - static_assert(sizeof(WCHAR) == sizeof(wchar16), "expect sizeof(WCHAR) == sizeof(wchar16)"); + wstr.erase(written); + static_assert(sizeof(WCHAR) == sizeof(wchar16), "expect sizeof(WCHAR) == sizeof(wchar16)"); return (const WCHAR*)wstr.data(); } static TString WCHARToUTF8(const LPWSTR wstr, size_t len) { static_assert(sizeof(WCHAR) == sizeof(wchar16), "expect sizeof(WCHAR) == sizeof(wchar16)"); - return WideToUTF8((wchar16*)wstr, len); + return WideToUTF8((wchar16*)wstr, len); } HANDLE CreateFileWithUtf8Name(const TStringBuf fName, ui32 accessMode, ui32 shareMode, ui32 createMode, ui32 attributes, bool inheritHandle) { TUtf16String wstr; - LPCWSTR wname = UTF8ToWCHAR(fName, wstr); - if (!wname) { - ::SetLastError(ERROR_INVALID_NAME); - return INVALID_HANDLE_VALUE; - } - SECURITY_ATTRIBUTES secAttrs; - secAttrs.bInheritHandle = inheritHandle ? TRUE : FALSE; + LPCWSTR wname = UTF8ToWCHAR(fName, wstr); + if (!wname) { + ::SetLastError(ERROR_INVALID_NAME); + return INVALID_HANDLE_VALUE; + } + SECURITY_ATTRIBUTES secAttrs; + secAttrs.bInheritHandle = inheritHandle ? TRUE : FALSE; secAttrs.lpSecurityDescriptor = nullptr; - secAttrs.nLength = sizeof(secAttrs); + secAttrs.nLength = sizeof(secAttrs); return ::CreateFileW(wname, accessMode, shareMode, &secAttrs, createMode, attributes, nullptr); } @@ -43,10 +43,10 @@ namespace NFsPrivate { TUtf16String op, np; LPCWSTR opPtr = UTF8ToWCHAR(oldPath, op); LPCWSTR npPtr = UTF8ToWCHAR(newPath, np); - if (!opPtr || !npPtr) { - ::SetLastError(ERROR_INVALID_NAME); + if (!opPtr || !npPtr) { + ::SetLastError(ERROR_INVALID_NAME); return false; - } + } return MoveFileExW(opPtr, npPtr, MOVEFILE_REPLACE_EXISTING) != 0; } @@ -54,16 +54,16 @@ namespace NFsPrivate { bool WinRemove(const TString& path) { TUtf16String wstr; LPCWSTR wname = UTF8ToWCHAR(path, wstr); - if (!wname) { - ::SetLastError(ERROR_INVALID_NAME); + if (!wname) { + ::SetLastError(ERROR_INVALID_NAME); return false; - } - WIN32_FILE_ATTRIBUTE_DATA fad; - if (::GetFileAttributesExW(wname, GetFileExInfoStandard, &fad)) { - if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + } + WIN32_FILE_ATTRIBUTE_DATA fad; + if (::GetFileAttributesExW(wname, GetFileExInfoStandard, &fad)) { + if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return ::RemoveDirectoryW(wname) != 0; return ::DeleteFileW(wname) != 0; - } + } return false; } @@ -71,53 +71,53 @@ namespace NFsPrivate { bool WinSymLink(const TString& targetName, const TString& linkName) { TString tName(targetName); { - size_t pos; + size_t pos; while ((pos = tName.find('/')) != TString::npos) - tName.replace(pos, 1, LOCSLASH_S); - } + tName.replace(pos, 1, LOCSLASH_S); + } TUtf16String tstr; - LPCWSTR wname = UTF8ToWCHAR(tName, tstr); + LPCWSTR wname = UTF8ToWCHAR(tName, tstr); TUtf16String lstr; LPCWSTR lname = UTF8ToWCHAR(linkName, lstr); - // we can't create a dangling link to a dir in this way - ui32 attr = ::GetFileAttributesW(wname); - if (attr == INVALID_FILE_ATTRIBUTES) { - TTempBuf result; - if (GetFullPathNameW(lname, result.Size(), (LPWSTR)result.Data(), 0) != 0) { + // we can't create a dangling link to a dir in this way + ui32 attr = ::GetFileAttributesW(wname); + if (attr == INVALID_FILE_ATTRIBUTES) { + TTempBuf result; + if (GetFullPathNameW(lname, result.Size(), (LPWSTR)result.Data(), 0) != 0) { TString fullPath = WideToUTF8(TWtringBuf((const wchar16*)result.Data())); - TStringBuf linkDir(fullPath); - linkDir.RNextTok('\\'); - - if (linkDir) { + TStringBuf linkDir(fullPath); + linkDir.RNextTok('\\'); + + if (linkDir) { TString fullTarget(tName); resolvepath(fullTarget, TString{linkDir}); TUtf16String fullTargetW; - LPCWSTR ptrFullTarget = UTF8ToWCHAR(fullTarget, fullTargetW); - attr = ::GetFileAttributesW(ptrFullTarget); - } + LPCWSTR ptrFullTarget = UTF8ToWCHAR(fullTarget, fullTargetW); + attr = ::GetFileAttributesW(ptrFullTarget); + } } } - return 0 != CreateSymbolicLinkW(lname, wname, attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0); + return 0 != CreateSymbolicLinkW(lname, wname, attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0); } bool WinHardLink(const TString& existingPath, const TString& newPath) { TUtf16String ep, np; LPCWSTR epPtr = UTF8ToWCHAR(existingPath, ep); LPCWSTR npPtr = UTF8ToWCHAR(newPath, np); - if (!epPtr || !npPtr) { - ::SetLastError(ERROR_INVALID_NAME); - return false; - } - + if (!epPtr || !npPtr) { + ::SetLastError(ERROR_INVALID_NAME); + return false; + } + return (CreateHardLinkW(npPtr, epPtr, nullptr) != 0); } bool WinExists(const TString& path) { TUtf16String buf; LPCWSTR ptr = UTF8ToWCHAR(path, buf); - return ::GetFileAttributesW(ptr) != INVALID_FILE_ATTRIBUTES; - } + return ::GetFileAttributesW(ptr) != INVALID_FILE_ATTRIBUTES; + } TString WinCurrentWorkingDirectory() { TTempBuf result; @@ -143,76 +143,76 @@ namespace NFsPrivate { LPCWSTR ptr = UTF8ToWCHAR(path, buf); return CreateDirectoryW(ptr, (LPSECURITY_ATTRIBUTES) nullptr); } - // edited part of <Ntifs.h> from Windows DDK + // edited part of <Ntifs.h> from Windows DDK #define SYMLINK_FLAG_RELATIVE 1 - struct TReparseBufferHeader { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; + struct TReparseBufferHeader { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + }; + + struct TSymbolicLinkReparseBuffer: public TReparseBufferHeader { + ULONG Flags; // 0 or SYMLINK_FLAG_RELATIVE + wchar16 PathBuffer[1]; + }; + + struct TMountPointReparseBuffer: public TReparseBufferHeader { + wchar16 PathBuffer[1]; + }; + + struct TGenericReparseBuffer { + wchar16 DataBuffer[1]; + }; + + struct REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + TSymbolicLinkReparseBuffer SymbolicLinkReparseBuffer; + TMountPointReparseBuffer MountPointReparseBuffer; + TGenericReparseBuffer GenericReparseBuffer; + }; }; - struct TSymbolicLinkReparseBuffer: public TReparseBufferHeader { - ULONG Flags; // 0 or SYMLINK_FLAG_RELATIVE - wchar16 PathBuffer[1]; - }; - - struct TMountPointReparseBuffer: public TReparseBufferHeader { - wchar16 PathBuffer[1]; - }; - - struct TGenericReparseBuffer { - wchar16 DataBuffer[1]; - }; - - struct REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - TSymbolicLinkReparseBuffer SymbolicLinkReparseBuffer; - TMountPointReparseBuffer MountPointReparseBuffer; - TGenericReparseBuffer GenericReparseBuffer; - }; - }; - - // the end of edited part of <Ntifs.h> + // the end of edited part of <Ntifs.h> TString WinReadLink(const TString& name) { TFileHandle h = CreateFileWithUtf8Name(name, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, true); - TTempBuf buf; - while (true) { - DWORD bytesReturned = 0; + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, true); + TTempBuf buf; + while (true) { + DWORD bytesReturned = 0; BOOL res = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf.Data(), buf.Size(), &bytesReturned, nullptr); - if (res) { - REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)buf.Data(); - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - wchar16* str = (wchar16*)&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar16)]; - size_t len = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar16); - return WideToUTF8(str, len); - } else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - wchar16* str = (wchar16*)&rdb->MountPointReparseBuffer.PathBuffer[rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar16)]; - size_t len = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar16); - return WideToUTF8(str, len); - } - //this reparse point is unsupported in arcadia + if (res) { + REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)buf.Data(); + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + wchar16* str = (wchar16*)&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar16)]; + size_t len = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar16); + return WideToUTF8(str, len); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + wchar16* str = (wchar16*)&rdb->MountPointReparseBuffer.PathBuffer[rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar16)]; + size_t len = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar16); + return WideToUTF8(str, len); + } + //this reparse point is unsupported in arcadia return TString(); } else { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - buf = TTempBuf(buf.Size() * 2); - } else { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + buf = TTempBuf(buf.Size() * 2); + } else { ythrow yexception() << "can't read link " << name; - } + } } } } - // we can't use this function to get an analog of unix inode due to a lot of NTFS folders do not have this GUID - //(it will be 'create' case really) - /* + // we can't use this function to get an analog of unix inode due to a lot of NTFS folders do not have this GUID + //(it will be 'create' case really) + /* bool GetObjectId(const char* path, GUID* id) { TFileHandle h = CreateFileWithUtf8Name(path, 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, true); @@ -230,4 +230,4 @@ bool GetObjectId(const char* path, GUID* id) { } */ -} +} diff --git a/util/system/fs_win.h b/util/system/fs_win.h index 8086129828..12f33fef68 100644 --- a/util/system/fs_win.h +++ b/util/system/fs_win.h @@ -6,7 +6,7 @@ #include <util/generic/strbuf.h> #include <util/generic/string.h> -namespace NFsPrivate { +namespace NFsPrivate { bool WinRename(const TString& oldPath, const TString& newPath); bool WinSymLink(const TString& targetName, const TString& linkName); @@ -26,4 +26,4 @@ namespace NFsPrivate { bool WinSetCurrentWorkingDirectory(const TString& path); bool WinMakeDirectory(const TString path); -} +} diff --git a/util/system/fstat.cpp b/util/system/fstat.cpp index 81e98cbc6b..dda6cbc069 100644 --- a/util/system/fstat.cpp +++ b/util/system/fstat.cpp @@ -1,19 +1,19 @@ #include "fstat.h" -#include "file.h" - -#include <sys/stat.h> +#include "file.h" + +#include <sys/stat.h> #include <util/folder/path.h> - + #include <cerrno> #if defined(_win_) - #include "fs_win.h" + #include "fs_win.h" - #ifdef _S_IFLNK - #undef _S_IFLNK - #endif - #define _S_IFLNK 0x80000000 + #ifdef _S_IFLNK + #undef _S_IFLNK + #endif + #define _S_IFLNK 0x80000000 ui32 GetFileMode(DWORD fileAttributes) { ui32 mode = 0; @@ -32,9 +32,9 @@ ui32 GetFileMode(DWORD fileAttributes) { return mode; } - #define S_ISDIR(st_mode) (st_mode & _S_IFDIR) - #define S_ISREG(st_mode) (st_mode & _S_IFREG) - #define S_ISLNK(st_mode) (st_mode & _S_IFLNK) + #define S_ISDIR(st_mode) (st_mode & _S_IFDIR) + #define S_ISREG(st_mode) (st_mode & _S_IFREG) + #define S_ISLNK(st_mode) (st_mode & _S_IFLNK) using TSystemFStat = BY_HANDLE_FILE_INFORMATION; @@ -85,8 +85,8 @@ static bool GetStatByHandle(TSystemFStat& fs, FHANDLE f) { static bool GetStatByName(TSystemFStat& fs, const char* fileName, bool nofollow) { #ifdef _win_ TFileHandle h = NFsPrivate::CreateFileWithUtf8Name(fileName, FILE_READ_ATTRIBUTES | FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE, - OPEN_EXISTING, - (nofollow ? FILE_FLAG_OPEN_REPARSE_POINT : 0) | FILE_FLAG_BACKUP_SEMANTICS, true); + OPEN_EXISTING, + (nofollow ? FILE_FLAG_OPEN_REPARSE_POINT : 0) | FILE_FLAG_BACKUP_SEMANTICS, true); if (!h.IsOpen()) { return false; } @@ -98,11 +98,11 @@ static bool GetStatByName(TSystemFStat& fs, const char* fileName, bool nofollow) TFileStat::TFileStat() = default; -TFileStat::TFileStat(const TFile& f) { +TFileStat::TFileStat(const TFile& f) { *this = TFileStat(f.GetHandle()); } -TFileStat::TFileStat(FHANDLE f) { +TFileStat::TFileStat(FHANDLE f) { TSystemFStat st; if (GetStatByHandle(st, f)) { MakeStat(*this, st); @@ -149,14 +149,14 @@ bool TFileStat::IsSymlink() const noexcept { } bool operator==(const TFileStat& l, const TFileStat& r) noexcept { - return l.Mode == r.Mode && - l.Uid == r.Uid && - l.Gid == r.Gid && - l.NLinks == r.NLinks && - l.Size == r.Size && - l.ATime == r.ATime && - l.MTime == r.MTime && - l.CTime == r.CTime; + return l.Mode == r.Mode && + l.Uid == r.Uid && + l.Gid == r.Gid && + l.NLinks == r.NLinks && + l.Size == r.Size && + l.ATime == r.ATime && + l.MTime == r.MTime && + l.CTime == r.CTime; } bool operator!=(const TFileStat& l, const TFileStat& r) noexcept { @@ -164,16 +164,16 @@ bool operator!=(const TFileStat& l, const TFileStat& r) noexcept { } i64 GetFileLength(FHANDLE fd) { -#if defined(_win_) +#if defined(_win_) LARGE_INTEGER pos; if (!::GetFileSizeEx(fd, &pos)) return -1L; return pos.QuadPart; -#elif defined(_unix_) +#elif defined(_unix_) struct stat statbuf; - if (::fstat(fd, &statbuf) != 0) { + if (::fstat(fd, &statbuf) != 0) { return -1L; - } + } if (!(statbuf.st_mode & (S_IFREG | S_IFBLK | S_IFCHR))) { // st_size only makes sense for regular files or devices errno = EINVAL; @@ -181,7 +181,7 @@ i64 GetFileLength(FHANDLE fd) { } return statbuf.st_size; #else - #error unsupported platform + #error unsupported platform #endif } @@ -196,9 +196,9 @@ i64 GetFileLength(const char* name) { #elif defined(_unix_) struct stat buf; int r = ::stat(name, &buf); - if (r == -1) { + if (r == -1) { return -1; - } + } if (!(buf.st_mode & (S_IFREG | S_IFBLK | S_IFCHR))) { // st_size only makes sense for regular files or devices errno = EINVAL; @@ -206,7 +206,7 @@ i64 GetFileLength(const char* name) { } return (i64)buf.st_size; #else - #error unsupported platform + #error unsupported platform #endif } diff --git a/util/system/fstat.h b/util/system/fstat.h index 64e79e1b55..528a5f7eaa 100644 --- a/util/system/fstat.h +++ b/util/system/fstat.h @@ -11,9 +11,9 @@ struct TFileStat { ui32 Uid = 0; /* user ID of owner */ ui32 Gid = 0; /* group ID of owner */ - ui64 NLinks = 0; /* number of hard links */ - ui64 Size = 0; /* total size, in bytes */ - ui64 INode = 0; /* inode number */ + ui64 NLinks = 0; /* number of hard links */ + ui64 Size = 0; /* total size, in bytes */ + ui64 INode = 0; /* inode number */ ui64 AllocationSize = 0; /* number of bytes allocated on the disk */ time_t ATime = 0; /* time of last access */ @@ -22,7 +22,7 @@ struct TFileStat { public: TFileStat(); - + bool IsNull() const noexcept; bool IsFile() const noexcept; @@ -34,7 +34,7 @@ public: TFileStat(const TFsPath& fileName, bool nofollow = false); TFileStat(const TString& fileName, bool nofollow = false); TFileStat(const char* fileName, bool nofollow = false); - + friend bool operator==(const TFileStat& l, const TFileStat& r) noexcept; friend bool operator!=(const TFileStat& l, const TFileStat& r) noexcept; diff --git a/util/system/fstat_ut.cpp b/util/system/fstat_ut.cpp index 160ecd936e..15fcf06859 100644 --- a/util/system/fstat_ut.cpp +++ b/util/system/fstat_ut.cpp @@ -11,55 +11,55 @@ Y_UNIT_TEST_SUITE(TestFileStat) { Y_UNIT_TEST(FileTest) { TString fileName = "f1.txt"; - TFileStat oFs; - { + TFileStat oFs; + { TFile file(fileName.data(), OpenAlways | WrOnly); - file.Write("1234567", 7); - - { - TFileStat fs(file); - UNIT_ASSERT(fs.IsFile()); - UNIT_ASSERT(!fs.IsDir()); - UNIT_ASSERT(!fs.IsSymlink()); - UNIT_ASSERT_VALUES_EQUAL(file.GetLength(), (i64)fs.Size); - UNIT_ASSERT(fs.MTime >= fs.CTime); - UNIT_ASSERT(fs.NLinks == 1); - oFs = fs; - } - - UNIT_ASSERT(file.IsOpen()); - UNIT_ASSERT_VALUES_EQUAL(file.GetLength(), 7); - file.Close(); + file.Write("1234567", 7); + + { + TFileStat fs(file); + UNIT_ASSERT(fs.IsFile()); + UNIT_ASSERT(!fs.IsDir()); + UNIT_ASSERT(!fs.IsSymlink()); + UNIT_ASSERT_VALUES_EQUAL(file.GetLength(), (i64)fs.Size); + UNIT_ASSERT(fs.MTime >= fs.CTime); + UNIT_ASSERT(fs.NLinks == 1); + oFs = fs; + } + + UNIT_ASSERT(file.IsOpen()); + UNIT_ASSERT_VALUES_EQUAL(file.GetLength(), 7); + file.Close(); } - TFileStat cFs(fileName); - UNIT_ASSERT(cFs.IsFile()); - UNIT_ASSERT(!cFs.IsDir()); - UNIT_ASSERT(!cFs.IsSymlink()); - UNIT_ASSERT_VALUES_EQUAL(cFs.Size, oFs.Size); - UNIT_ASSERT(cFs.MTime >= oFs.MTime); - UNIT_ASSERT_VALUES_EQUAL(cFs.CTime, oFs.CTime); - UNIT_ASSERT_VALUES_EQUAL(cFs.NLinks, oFs.NLinks); - UNIT_ASSERT_VALUES_EQUAL(cFs.Mode, oFs.Mode); - UNIT_ASSERT_VALUES_EQUAL(cFs.Uid, oFs.Uid); - UNIT_ASSERT_VALUES_EQUAL(cFs.Gid, oFs.Gid); + TFileStat cFs(fileName); + UNIT_ASSERT(cFs.IsFile()); + UNIT_ASSERT(!cFs.IsDir()); + UNIT_ASSERT(!cFs.IsSymlink()); + UNIT_ASSERT_VALUES_EQUAL(cFs.Size, oFs.Size); + UNIT_ASSERT(cFs.MTime >= oFs.MTime); + UNIT_ASSERT_VALUES_EQUAL(cFs.CTime, oFs.CTime); + UNIT_ASSERT_VALUES_EQUAL(cFs.NLinks, oFs.NLinks); + UNIT_ASSERT_VALUES_EQUAL(cFs.Mode, oFs.Mode); + UNIT_ASSERT_VALUES_EQUAL(cFs.Uid, oFs.Uid); + UNIT_ASSERT_VALUES_EQUAL(cFs.Gid, oFs.Gid); UNIT_ASSERT_VALUES_EQUAL(cFs.INode, oFs.INode); UNIT_ASSERT(unlink(fileName.data()) == 0); - } + } Y_UNIT_TEST(DirTest) { - Mkdir("tmpd", MODE0777); - TFileStat fs("tmpd"); - UNIT_ASSERT(!fs.IsFile()); - UNIT_ASSERT(fs.IsDir()); - UNIT_ASSERT(!fs.IsSymlink()); - //UNIT_ASSERT(fs.Size == 0); // it fails under unix + Mkdir("tmpd", MODE0777); + TFileStat fs("tmpd"); + UNIT_ASSERT(!fs.IsFile()); + UNIT_ASSERT(fs.IsDir()); + UNIT_ASSERT(!fs.IsSymlink()); + //UNIT_ASSERT(fs.Size == 0); // it fails under unix UNIT_ASSERT(NFs::Remove("tmpd")); - fs = TFileStat("tmpd"); - UNIT_ASSERT(!fs.IsFile()); - UNIT_ASSERT(!fs.IsDir()); - UNIT_ASSERT(!fs.IsSymlink()); - UNIT_ASSERT(fs.Size == 0); - UNIT_ASSERT(fs.CTime == 0); + fs = TFileStat("tmpd"); + UNIT_ASSERT(!fs.IsFile()); + UNIT_ASSERT(!fs.IsDir()); + UNIT_ASSERT(!fs.IsSymlink()); + UNIT_ASSERT(fs.Size == 0); + UNIT_ASSERT(fs.CTime == 0); } Y_UNIT_TEST(SymlinkToExistingFileTest) { @@ -154,4 +154,4 @@ Y_UNIT_TEST_SUITE(TestFileStat) { UNIT_ASSERT(unlink(fileName.c_str()) == 0); } -} +} diff --git a/util/system/getpid.cpp b/util/system/getpid.cpp index b9615f0dfa..96823f5f70 100644 --- a/util/system/getpid.cpp +++ b/util/system/getpid.cpp @@ -1,18 +1,18 @@ #include "getpid.h" #ifdef _win_ - // The include file should be Windows.h for Windows <=7, Processthreadsapi.h for Windows >=8 and Server 2012, - // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683180%28v=vs.85%29.aspx - // The way to determine windows version is described in http://msdn.microsoft.com/en-us/library/windows/desktop/aa383745%28v=vs.85%29.aspx - // with additions about Windows Server 2012 in https://social.msdn.microsoft.com/forums/vstudio/en-US/8d76d1d7-d078-4c55-963b-77e060845d0c/what-is-ntddiversion-value-for-ws-2012 - #include <Windows.h> - #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) - #include <processthreadsapi.h> - #endif -#else - #include <sys/types.h> - #include <unistd.h> -#endif + // The include file should be Windows.h for Windows <=7, Processthreadsapi.h for Windows >=8 and Server 2012, + // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683180%28v=vs.85%29.aspx + // The way to determine windows version is described in http://msdn.microsoft.com/en-us/library/windows/desktop/aa383745%28v=vs.85%29.aspx + // with additions about Windows Server 2012 in https://social.msdn.microsoft.com/forums/vstudio/en-US/8d76d1d7-d078-4c55-963b-77e060845d0c/what-is-ntddiversion-value-for-ws-2012 + #include <Windows.h> + #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) + #include <processthreadsapi.h> + #endif +#else + #include <sys/types.h> + #include <unistd.h> +#endif TProcessId GetPID() { #ifdef _win_ diff --git a/util/system/guard.cpp b/util/system/guard.cpp index 29d14dd227..659720a322 100644 --- a/util/system/guard.cpp +++ b/util/system/guard.cpp @@ -1 +1 @@ -#include "guard.h" +#include "guard.h" diff --git a/util/system/guard.h b/util/system/guard.h index efc091d5f8..d47a1a90eb 100644 --- a/util/system/guard.h +++ b/util/system/guard.h @@ -1,28 +1,28 @@ #pragma once #include <util/generic/noncopyable.h> - -template <class T> -struct TCommonLockOps { + +template <class T> +struct TCommonLockOps { static inline void Acquire(T* t) noexcept { - t->Acquire(); - } - + t->Acquire(); + } + static inline void Release(T* t) noexcept { - t->Release(); - } -}; - + t->Release(); + } +}; + template <class T> -struct TTryLockOps: public TCommonLockOps<T> { +struct TTryLockOps: public TCommonLockOps<T> { static inline bool TryAcquire(T* t) noexcept { return t->TryAcquire(); } }; -//must be used with great care +//must be used with great care template <class TOps> -struct TInverseLockOps: public TOps { +struct TInverseLockOps: public TOps { template <class T> static inline void Acquire(T* t) noexcept { TOps::Release(t); @@ -34,108 +34,108 @@ struct TInverseLockOps: public TOps { } }; -template <class T, class TOps = TCommonLockOps<T>> -class TGuard: public TNonCopyable { -public: +template <class T, class TOps = TCommonLockOps<T>> +class TGuard: public TNonCopyable { +public: inline TGuard(const T& t) noexcept { - Init(&t); - } - + Init(&t); + } + inline TGuard(const T* t) noexcept { - Init(t); - } - + Init(t); + } + inline TGuard(TGuard&& g) noexcept - : T_(g.T_) - { + : T_(g.T_) + { g.T_ = nullptr; - } - + } + inline ~TGuard() { - Release(); - } - + Release(); + } + inline void Release() noexcept { - if (WasAcquired()) { - TOps::Release(T_); + if (WasAcquired()) { + TOps::Release(T_); T_ = nullptr; - } - } - + } + } + explicit inline operator bool() const noexcept { - return WasAcquired(); - } - + return WasAcquired(); + } + inline bool WasAcquired() const noexcept { return T_ != nullptr; - } - + } + inline T* GetMutex() const noexcept { - return T_; - } - -private: + return T_; + } + +private: inline void Init(const T* t) noexcept { - T_ = const_cast<T*>(t); - TOps::Acquire(T_); - } - -private: - T* T_; -}; - -/* - * { - * auto guard = Guard(Lock_); - * some code under guard - * } - */ -template <class T> -static inline TGuard<T> Guard(const T& t) { - return {&t}; -} - -/* - * with_lock (Lock_) { - * some code under guard - * } - */ -#define with_lock(X) \ - if (auto Y_GENERATE_UNIQUE_ID(__guard) = ::Guard(X); false) { \ - } else - -/* - * auto guard = Guard(Lock_); - * ... some code under lock - * { - * auto unguard = Unguard(guard); - * ... some code not under lock - * } - * ... some code under lock - */ -template <class T, class TOps = TCommonLockOps<T>> -using TInverseGuard = TGuard<T, TInverseLockOps<TOps>>; - -template <class T, class TOps> -static inline TInverseGuard<T, TOps> Unguard(const TGuard<T, TOps>& guard) { - return {guard.GetMutex()}; -} - -template <class T> -static inline TInverseGuard<T> Unguard(const T& mutex) { - return {&mutex}; -} - -template <class T, class TOps = TTryLockOps<T>> + T_ = const_cast<T*>(t); + TOps::Acquire(T_); + } + +private: + T* T_; +}; + +/* + * { + * auto guard = Guard(Lock_); + * some code under guard + * } + */ +template <class T> +static inline TGuard<T> Guard(const T& t) { + return {&t}; +} + +/* + * with_lock (Lock_) { + * some code under guard + * } + */ +#define with_lock(X) \ + if (auto Y_GENERATE_UNIQUE_ID(__guard) = ::Guard(X); false) { \ + } else + +/* + * auto guard = Guard(Lock_); + * ... some code under lock + * { + * auto unguard = Unguard(guard); + * ... some code not under lock + * } + * ... some code under lock + */ +template <class T, class TOps = TCommonLockOps<T>> +using TInverseGuard = TGuard<T, TInverseLockOps<TOps>>; + +template <class T, class TOps> +static inline TInverseGuard<T, TOps> Unguard(const TGuard<T, TOps>& guard) { + return {guard.GetMutex()}; +} + +template <class T> +static inline TInverseGuard<T> Unguard(const T& mutex) { + return {&mutex}; +} + +template <class T, class TOps = TTryLockOps<T>> class TTryGuard: public TNonCopyable { -public: +public: inline TTryGuard(const T& t) noexcept { - Init(&t); - } + Init(&t); + } inline TTryGuard(const T* t) noexcept { - Init(t); - } + Init(t); + } inline TTryGuard(TTryGuard&& g) noexcept : T_(g.T_) @@ -144,33 +144,33 @@ public: } inline ~TTryGuard() { - Release(); - } + Release(); + } inline void Release() noexcept { - if (WasAcquired()) { - TOps::Release(T_); + if (WasAcquired()) { + TOps::Release(T_); T_ = nullptr; } - } + } inline bool WasAcquired() const noexcept { return T_ != nullptr; - } + } explicit inline operator bool() const noexcept { - return WasAcquired(); - } - -private: + return WasAcquired(); + } + +private: inline void Init(const T* t) noexcept { T_ = nullptr; - T* tMutable = const_cast<T*>(t); - if (TOps::TryAcquire(tMutable)) { - T_ = tMutable; + T* tMutable = const_cast<T*>(t); + if (TOps::TryAcquire(tMutable)) { + T_ = tMutable; } - } + } -private: - T* T_; +private: + T* T_; }; diff --git a/util/system/guard_ut.cpp b/util/system/guard_ut.cpp index 404ede99ab..d3501cba4e 100644 --- a/util/system/guard_ut.cpp +++ b/util/system/guard_ut.cpp @@ -1,17 +1,17 @@ -#include "guard.h" +#include "guard.h" #include "rwlock.h" - + #include <library/cpp/testing/unittest/registar.h> #include <util/thread/pool.h> -struct TTestGuard: public TTestBase { +struct TTestGuard: public TTestBase { UNIT_TEST_SUITE(TTestGuard); - UNIT_TEST(TestGuard) - UNIT_TEST(TestTryGuard) - UNIT_TEST(TestMove) - UNIT_TEST(TestSync) - UNIT_TEST(TestUnguard) + UNIT_TEST(TestGuard) + UNIT_TEST(TestTryGuard) + UNIT_TEST(TestMove) + UNIT_TEST(TestSync) + UNIT_TEST(TestUnguard) UNIT_TEST(TestTryReadGuard) UNIT_TEST(TestWithLock) UNIT_TEST(TestWithLockScope); @@ -41,66 +41,66 @@ struct TTestGuard: public TTestBase { bool guarded; }; - void TestUnguard() { - TGuardChecker m; - - { - auto guard = Guard(m); - - UNIT_ASSERT(m.guarded); - - { - auto unguard = Unguard(guard); - - UNIT_ASSERT(!m.guarded); - } - - UNIT_ASSERT(m.guarded); - } - - { - auto guard = Guard(m); - - UNIT_ASSERT(m.guarded); - - { - auto unguard = Unguard(m); - - UNIT_ASSERT(!m.guarded); - } - - UNIT_ASSERT(m.guarded); - } - } - - void TestMove() { - TGuardChecker m; - size_t n = 0; - - { - auto guard = Guard(m); - - UNIT_ASSERT(m.guarded); - ++n; - } - - UNIT_ASSERT(!m.guarded); - UNIT_ASSERT_VALUES_EQUAL(n, 1); - } - - void TestSync() { - TGuardChecker m; - size_t n = 0; - - with_lock (m) { - UNIT_ASSERT(m.guarded); - ++n; - } - - UNIT_ASSERT(!m.guarded); - UNIT_ASSERT_VALUES_EQUAL(n, 1); - } - + void TestUnguard() { + TGuardChecker m; + + { + auto guard = Guard(m); + + UNIT_ASSERT(m.guarded); + + { + auto unguard = Unguard(guard); + + UNIT_ASSERT(!m.guarded); + } + + UNIT_ASSERT(m.guarded); + } + + { + auto guard = Guard(m); + + UNIT_ASSERT(m.guarded); + + { + auto unguard = Unguard(m); + + UNIT_ASSERT(!m.guarded); + } + + UNIT_ASSERT(m.guarded); + } + } + + void TestMove() { + TGuardChecker m; + size_t n = 0; + + { + auto guard = Guard(m); + + UNIT_ASSERT(m.guarded); + ++n; + } + + UNIT_ASSERT(!m.guarded); + UNIT_ASSERT_VALUES_EQUAL(n, 1); + } + + void TestSync() { + TGuardChecker m; + size_t n = 0; + + with_lock (m) { + UNIT_ASSERT(m.guarded); + ++n; + } + + UNIT_ASSERT(!m.guarded); + UNIT_ASSERT_VALUES_EQUAL(n, 1); + } + void TestGuard() { TGuardChecker checker; @@ -154,7 +154,7 @@ struct TTestGuard: public TTestBase { } int WithLockIncrement(TGuardChecker& m, int n) { - with_lock (m) { + with_lock (m) { UNIT_ASSERT(m.guarded); return n + 1; } @@ -171,7 +171,7 @@ struct TTestGuard: public TTestBase { void TestWithLockScope() { auto Guard = [](auto) { UNIT_FAIL("Non global Guard used"); return 0; }; TGuardChecker m; - with_lock (m) { + with_lock (m) { Y_UNUSED(Guard); } } diff --git a/util/system/hi_lo.h b/util/system/hi_lo.h index f86870534f..ddd89836ab 100644 --- a/util/system/hi_lo.h +++ b/util/system/hi_lo.h @@ -5,7 +5,7 @@ #include <utility> #ifndef _little_endian_ - #error "Not implemented" + #error "Not implemented" #endif namespace NHiLoPrivate { @@ -17,23 +17,23 @@ namespace NHiLoPrivate { { } - TRepr Get() const { - return ReadUnaligned<TRepr>(Ptr); - } - operator TRepr() const { - return Get(); - } + TRepr Get() const { + return ReadUnaligned<TRepr>(Ptr); + } + operator TRepr() const { + return Get(); + } - const char* GetPtr() const { - return Ptr; - } + const char* GetPtr() const { + return Ptr; + } protected: const char* Ptr; }; template <class TRepr> - class TIntRef: public TConstIntRef<TRepr> { + class TIntRef: public TConstIntRef<TRepr> { public: explicit TIntRef(char* ptr) : TConstIntRef<TRepr>(ptr) @@ -45,9 +45,9 @@ namespace NHiLoPrivate { return *this; } - char* GetPtr() const { - return const_cast<char*>(this->Ptr); - } + char* GetPtr() const { + return const_cast<char*>(this->Ptr); + } }; template <class T> @@ -77,12 +77,12 @@ namespace NHiLoPrivate { template <class T> const char* CharPtrOf(const T& value) { - return reinterpret_cast<const char*>(&value); + return reinterpret_cast<const char*>(&value); } template <class T> char* CharPtrOf(T& value) { - return reinterpret_cast<char*>(&value); + return reinterpret_cast<char*>(&value); } template <class T> @@ -99,8 +99,8 @@ namespace NHiLoPrivate { auto MakeIntRef(T&& value) { using TRef = typename TReferenceType<typename std::decay<T>::type>::TType; static_assert( - std::is_scalar<TRef>::value, - "Hi* and Lo* functions can be applied only to scalar values"); + std::is_scalar<TRef>::value, + "Hi* and Lo* functions can be applied only to scalar values"); static_assert(sizeof(TRef) >= sizeof(TRepr), "Requested bit range is not within provided value"); constexpr size_t offset = IsLow ? 0 : sizeof(TRef) - sizeof(TRepr); diff --git a/util/system/hi_lo_ut.cpp b/util/system/hi_lo_ut.cpp index 850c12327d..a62f228a5c 100644 --- a/util/system/hi_lo_ut.cpp +++ b/util/system/hi_lo_ut.cpp @@ -5,65 +5,65 @@ #include "defaults.h" Y_UNIT_TEST_SUITE(HiLo) { - Y_UNIT_TEST(HiLo32) { - ui64 x = 0; - Lo32(x) = 18; - UNIT_ASSERT_VALUES_EQUAL(x, 18); + Y_UNIT_TEST(HiLo32) { + ui64 x = 0; + Lo32(x) = 18; + UNIT_ASSERT_VALUES_EQUAL(x, 18); - Hi32(x) = 33; - UNIT_ASSERT_VALUES_EQUAL(x, 141733920786); + Hi32(x) = 33; + UNIT_ASSERT_VALUES_EQUAL(x, 141733920786); - const ui64 y = 0x33c06196e94c03ab; - UNIT_ASSERT_VALUES_EQUAL(Lo32(y).Get(), 0xe94c03ab); - UNIT_ASSERT_VALUES_EQUAL(Hi32(y).Get(), 0x33c06196); - } + const ui64 y = 0x33c06196e94c03ab; + UNIT_ASSERT_VALUES_EQUAL(Lo32(y).Get(), 0xe94c03ab); + UNIT_ASSERT_VALUES_EQUAL(Hi32(y).Get(), 0x33c06196); + } - Y_UNIT_TEST(HiLo16) { - ui32 x = 0; - Lo16(x) = 18; - UNIT_ASSERT_VALUES_EQUAL(x, 18); + Y_UNIT_TEST(HiLo16) { + ui32 x = 0; + Lo16(x) = 18; + UNIT_ASSERT_VALUES_EQUAL(x, 18); - Hi16(x) = 33; - UNIT_ASSERT_VALUES_EQUAL(x, 2162706); + Hi16(x) = 33; + UNIT_ASSERT_VALUES_EQUAL(x, 2162706); - const ui32 y = 0xe94c03ab; - UNIT_ASSERT_VALUES_EQUAL(Lo16(y).Get(), 0x03ab); - UNIT_ASSERT_VALUES_EQUAL(Hi16(y).Get(), 0xe94c); - } + const ui32 y = 0xe94c03ab; + UNIT_ASSERT_VALUES_EQUAL(Lo16(y).Get(), 0x03ab); + UNIT_ASSERT_VALUES_EQUAL(Hi16(y).Get(), 0xe94c); + } - Y_UNIT_TEST(HiLo8) { - ui16 x = 0; - Lo8(x) = 18; - UNIT_ASSERT_VALUES_EQUAL(x, 18); + Y_UNIT_TEST(HiLo8) { + ui16 x = 0; + Lo8(x) = 18; + UNIT_ASSERT_VALUES_EQUAL(x, 18); - Hi8(x) = 33; - UNIT_ASSERT_VALUES_EQUAL(x, 8466); + Hi8(x) = 33; + UNIT_ASSERT_VALUES_EQUAL(x, 8466); - const ui16 y = 0x03ab; - UNIT_ASSERT_VALUES_EQUAL(Lo8(y).Get(), 0xab); - UNIT_ASSERT_VALUES_EQUAL(Hi8(y).Get(), 0x03); - } + const ui16 y = 0x03ab; + UNIT_ASSERT_VALUES_EQUAL(Lo8(y).Get(), 0xab); + UNIT_ASSERT_VALUES_EQUAL(Hi8(y).Get(), 0x03); + } - Y_UNIT_TEST(Combined) { - ui32 x = 0; - Lo8(Lo16(x)) = 18; - UNIT_ASSERT_VALUES_EQUAL(x, 18); + Y_UNIT_TEST(Combined) { + ui32 x = 0; + Lo8(Lo16(x)) = 18; + UNIT_ASSERT_VALUES_EQUAL(x, 18); - Hi8(Lo16(x)) = 33; - UNIT_ASSERT_VALUES_EQUAL(x, 8466); + Hi8(Lo16(x)) = 33; + UNIT_ASSERT_VALUES_EQUAL(x, 8466); - const ui32 y = 0xe94c03ab; - UNIT_ASSERT_VALUES_EQUAL(Lo8(Lo16(y)).Get(), 0xab); - UNIT_ASSERT_VALUES_EQUAL(Hi8(Lo16(y)).Get(), 0x03); - } + const ui32 y = 0xe94c03ab; + UNIT_ASSERT_VALUES_EQUAL(Lo8(Lo16(y)).Get(), 0xab); + UNIT_ASSERT_VALUES_EQUAL(Hi8(Lo16(y)).Get(), 0x03); + } - Y_UNIT_TEST(NarrowFromWide) { - const ui64 x = 0x1122334455667788ull; - UNIT_ASSERT_VALUES_EQUAL(Lo8(x).Get(), 0x88); - UNIT_ASSERT_VALUES_EQUAL(Hi8(x).Get(), 0x11); - UNIT_ASSERT_VALUES_EQUAL(Lo16(x).Get(), 0x7788); - UNIT_ASSERT_VALUES_EQUAL(Hi16(x).Get(), 0x1122); - UNIT_ASSERT_VALUES_EQUAL(Lo32(x).Get(), 0x55667788); - UNIT_ASSERT_VALUES_EQUAL(Hi32(x).Get(), 0x11223344); - } + Y_UNIT_TEST(NarrowFromWide) { + const ui64 x = 0x1122334455667788ull; + UNIT_ASSERT_VALUES_EQUAL(Lo8(x).Get(), 0x88); + UNIT_ASSERT_VALUES_EQUAL(Hi8(x).Get(), 0x11); + UNIT_ASSERT_VALUES_EQUAL(Lo16(x).Get(), 0x7788); + UNIT_ASSERT_VALUES_EQUAL(Hi16(x).Get(), 0x1122); + UNIT_ASSERT_VALUES_EQUAL(Lo32(x).Get(), 0x55667788); + UNIT_ASSERT_VALUES_EQUAL(Hi32(x).Get(), 0x11223344); + } } diff --git a/util/system/hostname.cpp b/util/system/hostname.cpp index 386f646d6b..72f1265204 100644 --- a/util/system/hostname.cpp +++ b/util/system/hostname.cpp @@ -1,36 +1,36 @@ -#include <util/memory/tempbuf.h> -#include <util/generic/singleton.h> +#include <util/memory/tempbuf.h> +#include <util/generic/singleton.h> #include <util/generic/yexception.h> #include <util/network/ip.h> - + #if defined(_unix_) - #include <unistd.h> - #include <ifaddrs.h> - #include <netdb.h> + #include <unistd.h> + #include <ifaddrs.h> + #include <netdb.h> #endif - -#if defined(_win_) - #include <WinSock2.h> + +#if defined(_win_) + #include <WinSock2.h> #endif #include "defaults.h" #include "yassert.h" -#include "hostname.h" - -namespace { - struct THostNameHolder { - inline THostNameHolder() { - TTempBuf hostNameBuf; - - if (gethostname(hostNameBuf.Data(), hostNameBuf.Size() - 1)) { - ythrow TSystemError() << "can not get host name"; - } - - HostName = hostNameBuf.Data(); +#include "hostname.h" + +namespace { + struct THostNameHolder { + inline THostNameHolder() { + TTempBuf hostNameBuf; + + if (gethostname(hostNameBuf.Data(), hostNameBuf.Size() - 1)) { + ythrow TSystemError() << "can not get host name"; + } + + HostName = hostNameBuf.Data(); } - + TString HostName; - }; + }; struct TFQDNHostNameHolder { inline TFQDNHostNameHolder() { @@ -62,15 +62,15 @@ namespace { TString FQDNHostName; }; -} - +} + const TString& HostName() { - return (Singleton<THostNameHolder>())->HostName; -} - -const char* GetHostName() { + return (Singleton<THostNameHolder>())->HostName; +} + +const char* GetHostName() { return HostName().data(); -} +} const TString& FQDNHostName() { return (Singleton<TFQDNHostNameHolder>())->FQDNHostName; diff --git a/util/system/hostname.h b/util/system/hostname.h index 0839ee2b59..30e9911983 100644 --- a/util/system/hostname.h +++ b/util/system/hostname.h @@ -1,8 +1,8 @@ #pragma once - + #include <util/generic/fwd.h> - -const char* GetHostName(); + +const char* GetHostName(); const TString& HostName(); const char* GetFQDNHostName(); diff --git a/util/system/hostname_ut.cpp b/util/system/hostname_ut.cpp index fb1cb7dde4..13660ec540 100644 --- a/util/system/hostname_ut.cpp +++ b/util/system/hostname_ut.cpp @@ -1,25 +1,25 @@ -#include "hostname.h" - +#include "hostname.h" + #include <library/cpp/testing/unittest/registar.h> + +Y_UNIT_TEST_SUITE(THostNameTest) { + Y_UNIT_TEST(Test1) { + UNIT_ASSERT(*GetHostName() != '?'); + } -Y_UNIT_TEST_SUITE(THostNameTest) { - Y_UNIT_TEST(Test1) { - UNIT_ASSERT(*GetHostName() != '?'); - } - - Y_UNIT_TEST(TestFQDN) { - UNIT_ASSERT(*GetFQDNHostName() != '?'); - } - - Y_UNIT_TEST(TestIsFQDN) { - const auto x = GetFQDNHostName(); - - try { - UNIT_ASSERT(IsFQDN(x)); - } catch (...) { - Cerr << x << Endl; + Y_UNIT_TEST(TestFQDN) { + UNIT_ASSERT(*GetFQDNHostName() != '?'); + } - throw; - } - } -}; + Y_UNIT_TEST(TestIsFQDN) { + const auto x = GetFQDNHostName(); + + try { + UNIT_ASSERT(IsFQDN(x)); + } catch (...) { + Cerr << x << Endl; + + throw; + } + } +}; diff --git a/util/system/hp_timer.cpp b/util/system/hp_timer.cpp index e4c3f21e6b..27f97a9b2b 100644 --- a/util/system/hp_timer.cpp +++ b/util/system/hp_timer.cpp @@ -1,104 +1,104 @@ #include "hp_timer.h" - + #include <util/generic/algorithm.h> -#include <util/generic/singleton.h> -#include <util/datetime/cputimer.h> - +#include <util/generic/singleton.h> +#include <util/datetime/cputimer.h> + using namespace NHPTimer; -namespace { - struct TFreq { - inline TFreq() - : Freq(InitHPTimer()) +namespace { + struct TFreq { + inline TFreq() + : Freq(InitHPTimer()) , Rate(1.0 / Freq) , CyclesPerSecond(static_cast<ui64>(Rate)) - { + { } - - static inline const TFreq& Instance() { + + static inline const TFreq& Instance() { return *SingletonWithPriority<TFreq, 1>(); } - static double EstimateCPUClock() { - for (;;) { + static double EstimateCPUClock() { + for (;;) { ui64 startCycle = 0; ui64 startMS = 0; - + for (;;) { startMS = MicroSeconds(); startCycle = GetCycleCount(); - + ui64 n = MicroSeconds(); if (n - startMS < 100) { break; } - } - + } + Sleep(TDuration::MicroSeconds(5000)); - + ui64 finishCycle = 0; ui64 finishMS = 0; - + for (;;) { finishMS = MicroSeconds(); - + if (finishMS - startMS < 100) { continue; } - + finishCycle = GetCycleCount(); - + ui64 n = MicroSeconds(); - + if (n - finishMS < 100) { break; } - } + } if (startMS < finishMS && startCycle < finishCycle) { return (finishCycle - startCycle) * 1000000.0 / (finishMS - startMS); } - } - } - - static double InitHPTimer() { - const size_t N_VEC = 9; - - double vec[N_VEC]; - + } + } + + static double InitHPTimer() { + const size_t N_VEC = 9; + + double vec[N_VEC]; + for (auto& i : vec) { i = EstimateCPUClock(); - } - - Sort(vec, vec + N_VEC); - - return 1.0 / vec[N_VEC / 2]; - } - - inline double GetSeconds(const STime& a) const { - return static_cast<double>(a) * Freq; - } - - inline double GetClockRate() const { + } + + Sort(vec, vec + N_VEC); + + return 1.0 / vec[N_VEC / 2]; + } + + inline double GetSeconds(const STime& a) const { + return static_cast<double>(a) * Freq; + } + + inline double GetClockRate() const { return Rate; - } - + } + inline ui64 GetCyclesPerSecond() const { return CyclesPerSecond; } - const double Freq; + const double Freq; const double Rate; const ui64 CyclesPerSecond; - }; + }; } double NHPTimer::GetSeconds(const STime& a) noexcept { - return TFreq::Instance().GetSeconds(a); + return TFreq::Instance().GetSeconds(a); } double NHPTimer::GetClockRate() noexcept { - return TFreq::Instance().GetClockRate(); + return TFreq::Instance().GetClockRate(); } ui64 NHPTimer::GetCyclesPerSecond() noexcept { @@ -111,8 +111,8 @@ void NHPTimer::GetTime(STime* pTime) noexcept { double NHPTimer::GetTimePassed(STime* pTime) noexcept { STime old(*pTime); - + *pTime = GetCycleCount(); - + return GetSeconds(*pTime - old); } diff --git a/util/system/hp_timer.h b/util/system/hp_timer.h index 0a4c252ec2..4a664eb3d2 100644 --- a/util/system/hp_timer.h +++ b/util/system/hp_timer.h @@ -1,8 +1,8 @@ #pragma once -#include "defaults.h" +#include "defaults.h" -namespace NHPTimer { +namespace NHPTimer { using STime = i64; // May delay for ~50ms to compute frequency double GetSeconds(const STime& a) noexcept; @@ -17,7 +17,7 @@ namespace NHPTimer { } struct THPTimer { - THPTimer() noexcept { + THPTimer() noexcept { Reset(); } void Reset() noexcept { @@ -30,7 +30,7 @@ struct THPTimer { double PassedReset() noexcept { return NHPTimer::GetTimePassed(&Start); } - + private: NHPTimer::STime Start; }; diff --git a/util/system/info.cpp b/util/system/info.cpp index cf6681e89a..d345c04a67 100644 --- a/util/system/info.cpp +++ b/util/system/info.cpp @@ -1,209 +1,209 @@ -#include "info.h" - +#include "info.h" + #include "error.h" -#include <cstdlib> - -#if defined(_linux_) || defined(_cygwin_) - #include <fcntl.h> - #include <sys/sysinfo.h> -#endif - -#if defined(_win_) - #include "winint.h" - #include <stdio.h> +#include <cstdlib> + +#if defined(_linux_) || defined(_cygwin_) + #include <fcntl.h> + #include <sys/sysinfo.h> +#endif + +#if defined(_win_) + #include "winint.h" + #include <stdio.h> #else - #include <unistd.h> -#endif - -#if defined(_bionic_) -//TODO -#elif defined(_cygwin_) -static int getloadavg(double* loadavg, int nelem) { - for (int i = 0; i < nelem; ++i) { - loadavg[i] = 0.0; - } - - return nelem; -} + #include <unistd.h> +#endif + +#if defined(_bionic_) +//TODO +#elif defined(_cygwin_) +static int getloadavg(double* loadavg, int nelem) { + for (int i = 0; i < nelem; ++i) { + loadavg[i] = 0.0; + } + + return nelem; +} #elif defined(_unix_) || defined(_darwin_) - #include <sys/types.h> + #include <sys/types.h> #endif #if defined(_freebsd_) || defined(_darwin_) - #include <sys/sysctl.h> -#endif - -#include <util/string/ascii.h> -#include <util/string/cast.h> -#include <util/string/strip.h> -#include <util/stream/file.h> + #include <sys/sysctl.h> +#endif + +#include <util/string/ascii.h> +#include <util/string/cast.h> +#include <util/string/strip.h> +#include <util/stream/file.h> #include <util/generic/yexception.h> - -#if defined(_linux_) -static inline size_t CgroupCpus() { - try { - auto q = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_quota_us").ReadAll())); - - if (q <= 0) { - return 0; - } - - auto p = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_period_us").ReadAll())); - - if (p <= 0) { - return 0; - } - + +#if defined(_linux_) +static inline size_t CgroupCpus() { + try { + auto q = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_quota_us").ReadAll())); + + if (q <= 0) { + return 0; + } + + auto p = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_period_us").ReadAll())); + + if (p <= 0) { + return 0; + } + return Max<ssize_t>(1, (q + p / 2) / p); - } catch (...) { - return 0; - } -} -#endif - -size_t NSystemInfo::NumberOfCpus() { -#if defined(_linux_) - if (auto res = CgroupCpus(); res) { - return res; - } -#endif - -#if defined(_win_) - SYSTEM_INFO info; - - GetSystemInfo(&info); - - return info.dwNumberOfProcessors; + } catch (...) { + return 0; + } +} +#endif + +size_t NSystemInfo::NumberOfCpus() { +#if defined(_linux_) + if (auto res = CgroupCpus(); res) { + return res; + } +#endif + +#if defined(_win_) + SYSTEM_INFO info; + + GetSystemInfo(&info); + + return info.dwNumberOfProcessors; #elif defined(_SC_NPROCESSORS_ONLN) return sysconf(_SC_NPROCESSORS_ONLN); -#elif defined(_linux_) - unsigned ret; - int fd, nread, column; - char buf[512]; - static const char matchstr[] = "processor\t:"; - - fd = open("/proc/cpuinfo", O_RDONLY); - - if (fd == -1) { - abort(); - } - - column = 0; - ret = 0; - - while (true) { - nread = read(fd, buf, sizeof(buf)); - - if (nread <= 0) { - break; - } - - for (int i = 0; i < nread; ++i) { - const char ch = buf[i]; - - if (ch == '\n') { - column = 0; - } else if (column != -1) { - if (AsciiToLower(ch) == matchstr[column]) { +#elif defined(_linux_) + unsigned ret; + int fd, nread, column; + char buf[512]; + static const char matchstr[] = "processor\t:"; + + fd = open("/proc/cpuinfo", O_RDONLY); + + if (fd == -1) { + abort(); + } + + column = 0; + ret = 0; + + while (true) { + nread = read(fd, buf, sizeof(buf)); + + if (nread <= 0) { + break; + } + + for (int i = 0; i < nread; ++i) { + const char ch = buf[i]; + + if (ch == '\n') { + column = 0; + } else if (column != -1) { + if (AsciiToLower(ch) == matchstr[column]) { ++column; - - if (column == sizeof(matchstr) - 1) { - column = -1; + + if (column == sizeof(matchstr) - 1) { + column = -1; ++ret; - } - } else { - column = -1; - } - } - } - } - - if (ret == 0) { - abort(); - } - - close(fd); - - return ret; -#elif defined(_freebsd_) || defined(_darwin_) - int mib[2]; - size_t len; - unsigned ncpus = 1; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpus); + } + } else { + column = -1; + } + } + } + } + + if (ret == 0) { + abort(); + } + + close(fd); + + return ret; +#elif defined(_freebsd_) || defined(_darwin_) + int mib[2]; + size_t len; + unsigned ncpus = 1; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(ncpus); if (sysctl(mib, 2, &ncpus, &len, nullptr, 0) == -1) { - abort(); - } - - return ncpus; -#else - #error todo -#endif -} - -size_t NSystemInfo::LoadAverage(double* la, size_t len) { -#if defined(_win_) || defined(_musl_) || defined(_bionic_) + abort(); + } + + return ncpus; +#else + #error todo +#endif +} + +size_t NSystemInfo::LoadAverage(double* la, size_t len) { +#if defined(_win_) || defined(_musl_) || defined(_bionic_) int ret = -1; #else for (size_t i = 0; i < len; ++i) { la[i] = 0; } - - int ret = getloadavg(la, len); + + int ret = getloadavg(la, len); #endif - - if (ret < 0) { - for (size_t i = 0; i < len; ++i) { - la[i] = 0; - } - - ret = len; - } - - return (size_t)ret; -} - -static size_t NCpus; - -size_t NSystemInfo::CachedNumberOfCpus() { - if (!NCpus) { - NCpus = NumberOfCpus(); - } - - return NCpus; -} + + if (ret < 0) { + for (size_t i = 0; i < len; ++i) { + la[i] = 0; + } + + ret = len; + } + + return (size_t)ret; +} + +static size_t NCpus; + +size_t NSystemInfo::CachedNumberOfCpus() { + if (!NCpus) { + NCpus = NumberOfCpus(); + } + + return NCpus; +} size_t NSystemInfo::GetPageSize() noexcept { -#if defined(_win_) - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); +#if defined(_win_) + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); - return sysInfo.dwPageSize; -#else + return sysInfo.dwPageSize; +#else return sysconf(_SC_PAGESIZE); -#endif +#endif } - + size_t NSystemInfo::TotalMemorySize() { -#if defined(_linux_) && defined(_64_) - try { - auto q = FromString<size_t>(StripString(TFileInput("/sys/fs/cgroup/memory/memory.limit_in_bytes").ReadAll())); - - if (q < (((size_t)1) << 60)) { - return q; - } - } catch (...) { - } -#endif - -#if defined(_linux_) || defined(_cygwin_) +#if defined(_linux_) && defined(_64_) + try { + auto q = FromString<size_t>(StripString(TFileInput("/sys/fs/cgroup/memory/memory.limit_in_bytes").ReadAll())); + + if (q < (((size_t)1) << 60)) { + return q; + } + } catch (...) { + } +#endif + +#if defined(_linux_) || defined(_cygwin_) struct sysinfo info; sysinfo(&info); return info.totalram; -#elif defined(_darwin_) +#elif defined(_darwin_) int mib[2]; int64_t memSize; size_t length; @@ -216,7 +216,7 @@ size_t NSystemInfo::TotalMemorySize() { ythrow yexception() << "sysctl failed: " << LastSystemErrorText(); } return (size_t)memSize; -#elif defined(_win_) +#elif defined(_win_) MEMORYSTATUSEX memoryStatusEx; memoryStatusEx.dwLength = sizeof(memoryStatusEx); if (!GlobalMemoryStatusEx(&memoryStatusEx)) { diff --git a/util/system/info.h b/util/system/info.h index 73ebe48a9a..022c4b8ab1 100644 --- a/util/system/info.h +++ b/util/system/info.h @@ -1,12 +1,12 @@ #pragma once - + #include "defaults.h" - -namespace NSystemInfo { - size_t NumberOfCpus(); - size_t CachedNumberOfCpus(); - size_t LoadAverage(double* la, size_t len); + +namespace NSystemInfo { + size_t NumberOfCpus(); + size_t CachedNumberOfCpus(); + size_t LoadAverage(double* la, size_t len); size_t GetPageSize() noexcept; size_t TotalMemorySize(); size_t MaxOpenFiles(); -} +} diff --git a/util/system/info_ut.cpp b/util/system/info_ut.cpp index ad7449f8f4..61618f40ac 100644 --- a/util/system/info_ut.cpp +++ b/util/system/info_ut.cpp @@ -1,22 +1,22 @@ -#include "info.h" - +#include "info.h" + #include <library/cpp/testing/unittest/registar.h> + +class TSysInfoTest: public TTestBase { + UNIT_TEST_SUITE(TSysInfoTest); + UNIT_TEST(TestNumberOfCpus) + UNIT_TEST(TestGetPageSize) + UNIT_TEST_SUITE_END(); -class TSysInfoTest: public TTestBase { - UNIT_TEST_SUITE(TSysInfoTest); - UNIT_TEST(TestNumberOfCpus) - UNIT_TEST(TestGetPageSize) - UNIT_TEST_SUITE_END(); - -private: - inline void TestNumberOfCpus() { - UNIT_ASSERT(NSystemInfo::NumberOfCpus() > 0); - UNIT_ASSERT_EQUAL(NSystemInfo::NumberOfCpus(), NSystemInfo::CachedNumberOfCpus()); - } - - inline void TestGetPageSize() { - UNIT_ASSERT(NSystemInfo::GetPageSize() >= 4096); - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TSysInfoTest); +private: + inline void TestNumberOfCpus() { + UNIT_ASSERT(NSystemInfo::NumberOfCpus() > 0); + UNIT_ASSERT_EQUAL(NSystemInfo::NumberOfCpus(), NSystemInfo::CachedNumberOfCpus()); + } + + inline void TestGetPageSize() { + UNIT_ASSERT(NSystemInfo::GetPageSize() >= 4096); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TSysInfoTest); diff --git a/util/system/interrupt_signals.cpp b/util/system/interrupt_signals.cpp index 96b723f2b8..4731738863 100644 --- a/util/system/interrupt_signals.cpp +++ b/util/system/interrupt_signals.cpp @@ -11,7 +11,7 @@ static void (*InterruptSignalsHandler)(int signum) = nullptr; #ifdef _win_ - #include <windows.h> + #include <windows.h> static BOOL WINAPI WindowsSignalsHandler(_In_ DWORD dwCtrlType) { if (!InterruptSignalsHandler) { diff --git a/util/system/interrupt_signals.h b/util/system/interrupt_signals.h index 9f9c2427f1..9500ff89d0 100644 --- a/util/system/interrupt_signals.h +++ b/util/system/interrupt_signals.h @@ -6,7 +6,7 @@ #ifdef _win_ #ifndef SIGHUP - #define SIGHUP 1 /* Hangup (POSIX). */ + #define SIGHUP 1 /* Hangup (POSIX). */ #endif #endif diff --git a/util/system/interrupt_signals_ut.cpp b/util/system/interrupt_signals_ut.cpp index bec54fec61..7f7ba95059 100644 --- a/util/system/interrupt_signals_ut.cpp +++ b/util/system/interrupt_signals_ut.cpp @@ -10,14 +10,14 @@ #include <windows.h> #endif -Y_UNIT_TEST_SUITE(TTestInterruptSignals) { +Y_UNIT_TEST_SUITE(TTestInterruptSignals) { static TAtomic HandledSigNum = 0; static void Handler(int signum) { AtomicSet(HandledSigNum, signum); } - Y_UNIT_TEST(Test1) { + Y_UNIT_TEST(Test1) { SetInterruptSignalsHandler(Handler); #ifdef _win_ // TODO: unfortunately GenerateConsoleCtrlEvent fails under Wine diff --git a/util/system/madvise.cpp b/util/system/madvise.cpp index 58c894e3ef..67a9b39ee1 100644 --- a/util/system/madvise.cpp +++ b/util/system/madvise.cpp @@ -5,20 +5,20 @@ #include <util/generic/yexception.h> #if defined(_win_) - #include <util/system/winint.h> + #include <util/system/winint.h> #else - #include <sys/types.h> - #include <sys/mman.h> + #include <sys/types.h> + #include <sys/mman.h> #endif -#ifndef MADV_DONTDUMP /* This flag is defined in sys/mman.h since Linux 3.4, but currently old libc header is in use \ - for capability with Ubuntu 12.04, so we need to define it here manually */ - #define MADV_DONTDUMP 16 /* Explicity exclude from the core dump, overrides the coredump filter bits */ +#ifndef MADV_DONTDUMP /* This flag is defined in sys/mman.h since Linux 3.4, but currently old libc header is in use \ + for capability with Ubuntu 12.04, so we need to define it here manually */ + #define MADV_DONTDUMP 16 /* Explicity exclude from the core dump, overrides the coredump filter bits */ #endif -#ifndef MADV_DODUMP /* This flag is defined in sys/mman.h since Linux 3.4, but currently old libc header is in use \ - for capability with Ubuntu 12.04, so we need to define it here manually */ - #define MADV_DODUMP 17 /* Undo the effect of an earlier MADV_DONTDUMP */ +#ifndef MADV_DODUMP /* This flag is defined in sys/mman.h since Linux 3.4, but currently old libc header is in use \ + for capability with Ubuntu 12.04, so we need to define it here manually */ + #define MADV_DODUMP 17 /* Undo the effect of an earlier MADV_DONTDUMP */ #endif namespace { @@ -36,8 +36,8 @@ namespace { #else if (-1 == madvise(begin, size, flag)) { TString err(LastSystemErrorText()); - ythrow yexception() << "madvise(" << begin << ", " << size << ", " << flag << ")" - << " returned error: " << err; + ythrow yexception() << "madvise(" << begin << ", " << size << ", " << flag << ")" + << " returned error: " << err; } #endif } diff --git a/util/system/maxlen.cpp b/util/system/maxlen.cpp index bcc9d72a4f..8eab5c0452 100644 --- a/util/system/maxlen.cpp +++ b/util/system/maxlen.cpp @@ -1 +1 @@ -#include "maxlen.h" +#include "maxlen.h" diff --git a/util/system/maxlen.h b/util/system/maxlen.h index e1ff7f5008..7af653f283 100644 --- a/util/system/maxlen.h +++ b/util/system/maxlen.h @@ -4,29 +4,29 @@ // http://support.microsoft.com/kb/208427 #ifndef URL_MAXLEN - #define URL_MAXLEN 2083 + #define URL_MAXLEN 2083 #endif -#define HOST_MAX 260 +#define HOST_MAX 260 #ifndef URL_MAX - #define URL_MAX 1024 + #define URL_MAX 1024 #endif -#define FULLURL_MAX (URL_MAX + HOST_MAX) +#define FULLURL_MAX (URL_MAX + HOST_MAX) -#define LINKTEXT_MAX 1024 +#define LINKTEXT_MAX 1024 #ifdef WIN32 - #ifndef PATH_MAX - #define PATH_MAX _MAX_PATH - #endif + #ifndef PATH_MAX + #define PATH_MAX _MAX_PATH + #endif #else - #ifndef MAX_PATH - #define MAX_PATH PATH_MAX - #endif + #ifndef MAX_PATH + #define MAX_PATH PATH_MAX + #endif - #ifndef _MAX_PATH - #define _MAX_PATH PATH_MAX - #endif + #ifndef _MAX_PATH + #define _MAX_PATH PATH_MAX + #endif #endif diff --git a/util/system/mem_info.cpp b/util/system/mem_info.cpp index aa51ae3b16..3b2c5197cb 100644 --- a/util/system/mem_info.cpp +++ b/util/system/mem_info.cpp @@ -5,41 +5,41 @@ #include <util/generic/yexception.h> #include <util/stream/file.h> #include <util/string/cast.h> -#include <util/string/builder.h> -#include "error.h" -#include "info.h" +#include <util/string/builder.h> +#include "error.h" +#include "info.h" #if defined(_unix_) - #include <errno.h> - #include <unistd.h> - #if defined(_freebsd_) - #include <sys/sysctl.h> - #include <sys/types.h> - #include <sys/user.h> - #elif defined(_darwin_) && !defined(_arm_) && !defined(__IOS__) - #include <libproc.h> - #elif defined(__MACH__) && defined(__APPLE__) - #include <mach/mach.h> - #endif + #include <errno.h> + #include <unistd.h> + #if defined(_freebsd_) + #include <sys/sysctl.h> + #include <sys/types.h> + #include <sys/user.h> + #elif defined(_darwin_) && !defined(_arm_) && !defined(__IOS__) + #include <libproc.h> + #elif defined(__MACH__) && defined(__APPLE__) + #include <mach/mach.h> + #endif #elif defined(_win_) - #include <Windows.h> - #include <util/generic/ptr.h> + #include <Windows.h> + #include <util/generic/ptr.h> using NTSTATUS = LONG; - #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 - #define STATUS_BUFFER_TOO_SMALL 0xC0000023 + #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 + #define STATUS_BUFFER_TOO_SMALL 0xC0000023 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; -typedef struct _CLIENT_ID { +typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; using KWAIT_REASON = ULONG; -typedef struct _SYSTEM_THREAD_INFORMATION { +typedef struct _SYSTEM_THREAD_INFORMATION { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; @@ -52,7 +52,7 @@ typedef struct _SYSTEM_THREAD_INFORMATION { ULONG ThreadState; KWAIT_REASON WaitReason; } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; -typedef struct _SYSTEM_PROCESS_INFORMATION { +typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER SpareLi1; @@ -99,16 +99,16 @@ typedef enum _SYSTEM_INFORMATION_CLASS { #endif namespace NMemInfo { - TMemInfo GetMemInfo(pid_t pid) { - TMemInfo result; + TMemInfo GetMemInfo(pid_t pid) { + TMemInfo result; #if defined(_unix_) - #if defined(_linux_) || defined(_freebsd_) || defined(_cygwin_) - const ui32 pagesize = NSystemInfo::GetPageSize(); - #endif + #if defined(_linux_) || defined(_freebsd_) || defined(_cygwin_) + const ui32 pagesize = NSystemInfo::GetPageSize(); + #endif - #if defined(_linux_) || defined(_cygwin_) + #if defined(_linux_) || defined(_cygwin_) TString path; if (!pid) { path = "/proc/self/statm"; @@ -116,47 +116,47 @@ namespace NMemInfo { path = TStringBuilder() << TStringBuf("/proc/") << pid << TStringBuf("/statm"); } const TString stats = TUnbufferedFileInput(path).ReadAll(); - - TStringBuf statsiter(stats); - - result.VMS = FromString<ui64>(statsiter.NextTok(' ')) * pagesize; - result.RSS = FromString<ui64>(statsiter.NextTok(' ')) * pagesize; - - #if defined(_cygwin_) - //cygwin not very accurate - result.VMS = Max(result.VMS, result.RSS); - #endif - #elif defined(_freebsd_) - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - size_t size = sizeof(struct kinfo_proc); - - struct kinfo_proc proc; - Zero(proc); - - errno = 0; + + TStringBuf statsiter(stats); + + result.VMS = FromString<ui64>(statsiter.NextTok(' ')) * pagesize; + result.RSS = FromString<ui64>(statsiter.NextTok(' ')) * pagesize; + + #if defined(_cygwin_) + //cygwin not very accurate + result.VMS = Max(result.VMS, result.RSS); + #endif + #elif defined(_freebsd_) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + size_t size = sizeof(struct kinfo_proc); + + struct kinfo_proc proc; + Zero(proc); + + errno = 0; if (sysctl((int*)mib, 4, &proc, &size, nullptr, 0) == -1) { - int err = errno; + int err = errno; TString errtxt = LastSystemErrorText(err); - ythrow yexception() << "sysctl({CTL_KERN,KERN_PROC,KERN_PROC_PID,pid},4,proc,&size,NULL,0) returned -1, errno: " << err << " (" << errtxt << ")" << Endl; - } + ythrow yexception() << "sysctl({CTL_KERN,KERN_PROC,KERN_PROC_PID,pid},4,proc,&size,NULL,0) returned -1, errno: " << err << " (" << errtxt << ")" << Endl; + } - result.VMS = proc.ki_size; - result.RSS = proc.ki_rssize * pagesize; - #elif defined(_darwin_) && !defined(_arm_) && !defined(__IOS__) + result.VMS = proc.ki_size; + result.RSS = proc.ki_rssize * pagesize; + #elif defined(_darwin_) && !defined(_arm_) && !defined(__IOS__) if (!pid) { pid = getpid(); } - struct proc_taskinfo taskInfo; - const int r = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)); + struct proc_taskinfo taskInfo; + const int r = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)); - if (r != sizeof(taskInfo)) { - int err = errno; + if (r != sizeof(taskInfo)) { + int err = errno; TString errtxt = LastSystemErrorText(err); - ythrow yexception() << "proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) returned " << r << ", errno: " << err << " (" << errtxt << ")" << Endl; - } - result.VMS = taskInfo.pti_virtual_size; - result.RSS = taskInfo.pti_resident_size; - #elif defined(__MACH__) && defined(__APPLE__) + ythrow yexception() << "proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) returned " << r << ", errno: " << err << " (" << errtxt << ")" << Endl; + } + result.VMS = taskInfo.pti_virtual_size; + result.RSS = taskInfo.pti_resident_size; + #elif defined(__MACH__) && defined(__APPLE__) Y_UNUSED(pid); struct mach_task_basic_info taskInfo; mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; @@ -169,51 +169,51 @@ namespace NMemInfo { } result.VMS = taskInfo.virtual_size; result.RSS = taskInfo.resident_size; - #elif defined(_arm_) + #elif defined(_arm_) Y_UNUSED(pid); - ythrow yexception() << "arm is not supported"; - #endif + ythrow yexception() << "arm is not supported"; + #endif #elif defined(_win_) - if (!pid) { - pid = GetCurrentProcessId(); - } - - NTSTATUS status; - TArrayHolder<char> buffer; - ULONG bufferSize; - - // Query data for all processes and threads in the system. - // This is probably an overkill if the target process is normal not-privileged one, - // but allows to obtain information even about system processes that are not open-able directly. - typedef NTSTATUS(_stdcall * NTQSI_PROC)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); - NTQSI_PROC NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation"); - bufferSize = 0x4000; - - for (;;) { - buffer.Reset(new char[bufferSize]); - status = NtQuerySystemInformation(SystemProcessInformation, buffer.Get(), bufferSize, &bufferSize); - - if (!status) { - break; - } - - if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_INFO_LENGTH_MISMATCH) { - ythrow yexception() << "NtQuerySystemInformation failed with status code " << status; - } - } - - SYSTEM_PROCESS_INFORMATION* process = (SYSTEM_PROCESS_INFORMATION*)buffer.Get(); - while (process->UniqueProcessId != (HANDLE)(size_t)(pid)) { - if (!process->NextEntryOffset) { - ythrow yexception() << "GetMemInfo: invalid PID"; - } - - process = (SYSTEM_PROCESS_INFORMATION*)((char*)process + process->NextEntryOffset); - } - - result.VMS = process->VirtualSize; - result.RSS = process->WorkingSetSize; + if (!pid) { + pid = GetCurrentProcessId(); + } + + NTSTATUS status; + TArrayHolder<char> buffer; + ULONG bufferSize; + + // Query data for all processes and threads in the system. + // This is probably an overkill if the target process is normal not-privileged one, + // but allows to obtain information even about system processes that are not open-able directly. + typedef NTSTATUS(_stdcall * NTQSI_PROC)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); + NTQSI_PROC NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation"); + bufferSize = 0x4000; + + for (;;) { + buffer.Reset(new char[bufferSize]); + status = NtQuerySystemInformation(SystemProcessInformation, buffer.Get(), bufferSize, &bufferSize); + + if (!status) { + break; + } + + if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_INFO_LENGTH_MISMATCH) { + ythrow yexception() << "NtQuerySystemInformation failed with status code " << status; + } + } + + SYSTEM_PROCESS_INFORMATION* process = (SYSTEM_PROCESS_INFORMATION*)buffer.Get(); + while (process->UniqueProcessId != (HANDLE)(size_t)(pid)) { + if (!process->NextEntryOffset) { + ythrow yexception() << "GetMemInfo: invalid PID"; + } + + process = (SYSTEM_PROCESS_INFORMATION*)((char*)process + process->NextEntryOffset); + } + + result.VMS = process->VirtualSize; + result.RSS = process->WorkingSetSize; #endif - return result; - } + return result; + } } diff --git a/util/system/mem_info.h b/util/system/mem_info.h index f303d49197..3e73a3e95d 100644 --- a/util/system/mem_info.h +++ b/util/system/mem_info.h @@ -1,18 +1,18 @@ #pragma once -#include "compat.h" +#include "compat.h" namespace NMemInfo { - struct TMemInfo { - ui64 RSS; // current RAM size of the process - ui64 VMS; // current VM size of the process + struct TMemInfo { + ui64 RSS; // current RAM size of the process + ui64 VMS; // current VM size of the process - TMemInfo() - : RSS() - , VMS() - { - } - }; + TMemInfo() + : RSS() + , VMS() + { + } + }; - TMemInfo GetMemInfo(pid_t = 0); + TMemInfo GetMemInfo(pid_t = 0); } diff --git a/util/system/mem_info_ut.cpp b/util/system/mem_info_ut.cpp index a1100ba646..147c5b6b21 100644 --- a/util/system/mem_info_ut.cpp +++ b/util/system/mem_info_ut.cpp @@ -2,12 +2,12 @@ #include <library/cpp/testing/unittest/registar.h> -#include "info.h" +#include "info.h" -class TMemInfoTest: public NUnitTest::TTestBase { - UNIT_TEST_SUITE(TMemInfoTest) +class TMemInfoTest: public NUnitTest::TTestBase { + UNIT_TEST_SUITE(TMemInfoTest) UNIT_TEST(TestMemInfo) - UNIT_TEST_SUITE_END(); + UNIT_TEST_SUITE_END(); void TestMemInfo() { using namespace NMemInfo; diff --git a/util/system/mincore.cpp b/util/system/mincore.cpp index 8cbae72586..989302923c 100644 --- a/util/system/mincore.cpp +++ b/util/system/mincore.cpp @@ -8,11 +8,11 @@ #include <cstring> #if defined(_unix_) - #include <sys/unistd.h> - #include <sys/mman.h> - #if defined(_android_) - #include <sys/syscall.h> - #endif + #include <sys/unistd.h> + #include <sys/mman.h> + #if defined(_android_) + #include <sys/syscall.h> + #endif #endif void InCoreMemory(const void* addr, size_t len, unsigned char* vec, size_t vecLen) { diff --git a/util/system/mincore_ut.cpp b/util/system/mincore_ut.cpp index fc46cb1632..ce7d0b9654 100644 --- a/util/system/mincore_ut.cpp +++ b/util/system/mincore_ut.cpp @@ -1,7 +1,7 @@ #include <library/cpp/testing/unittest/registar.h> #ifdef _unix_ - #include <sys/resource.h> + #include <sys/resource.h> #endif #include "filemap.h" diff --git a/util/system/mktemp.cpp b/util/system/mktemp.cpp index 505b7b4a4b..188fb1c7ea 100644 --- a/util/system/mktemp.cpp +++ b/util/system/mktemp.cpp @@ -1,22 +1,22 @@ #include "tempfile.h" - + #include <util/folder/dirut.h> #include <util/generic/yexception.h> -#include <util/stream/file.h> - +#include <util/stream/file.h> + #include <cerrno> #include <cstring> #ifdef _win32_ - #include "winint.h" - #include <io.h> + #include "winint.h" + #include <io.h> #else - #include <unistd.h> - #include <stdlib.h> + #include <unistd.h> + #include <stdlib.h> #endif -extern "C" int mkstemps(char* path, int slen); - +extern "C" int mkstemps(char* path, int slen); + TString MakeTempName(const char* wrkDir, const char* prefix, const char* extension) { #ifndef _win32_ TString filePath; @@ -29,11 +29,11 @@ TString MakeTempName(const char* wrkDir, const char* prefix, const char* extensi if (filePath.back() != '/') { filePath += '/'; - } + } if (prefix) { filePath += prefix; - } + } filePath += "XXXXXX"; // mkstemps requirement @@ -45,7 +45,7 @@ TString MakeTempName(const char* wrkDir, const char* prefix, const char* extensi } filePath += extension; extensionPartLength += strlen(extension); - } + } int fd = mkstemps(const_cast<char*>(filePath.data()), extensionPartLength); if (fd >= 0) { @@ -55,7 +55,7 @@ TString MakeTempName(const char* wrkDir, const char* prefix, const char* extensi #else char tmpDir[MAX_PATH + 1]; // +1 -- for terminating null character char filePath[MAX_PATH]; - const char* pDir = 0; + const char* pDir = 0; if (wrkDir && *wrkDir) { pDir = wrkDir; @@ -68,6 +68,6 @@ TString MakeTempName(const char* wrkDir, const char* prefix, const char* extensi return filePath; } #endif - + ythrow TSystemError() << "can not create temp name(" << wrkDir << ", " << prefix << ", " << extension << ")"; -} +} diff --git a/util/system/mktemp_system.cpp b/util/system/mktemp_system.cpp index 32bea2987c..fa1fa2550d 100644 --- a/util/system/mktemp_system.cpp +++ b/util/system/mktemp_system.cpp @@ -43,133 +43,133 @@ #ifdef _win32_ #include "winint.h" - #include <util/folder/dirut.h> -#else + #include <util/folder/dirut.h> +#else #include <unistd.h> #endif -#include <util/random/random.h> -#include "sysstat.h" +#include <util/random/random.h> +#include "sysstat.h" static const unsigned char padchar[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static int -GetTemp(char* path, int* doopen, int domkdir, int slen) +GetTemp(char* path, int* doopen, int domkdir, int slen) { - char *start, *trv, *suffp; - char* pad; + char *start, *trv, *suffp; + char* pad; #ifndef _win32_ - struct stat sbuf; - int rval; + struct stat sbuf; + int rval; #endif - ui32 rand; + ui32 rand; - if (doopen != nullptr && domkdir) { - errno = EINVAL; - return (0); - } + if (doopen != nullptr && domkdir) { + errno = EINVAL; + return (0); + } - for (trv = path; *trv != '\0'; ++trv) { - ; - } - trv -= slen; - suffp = trv; - --trv; - if (trv < path) { - errno = EINVAL; - return (0); - } + for (trv = path; *trv != '\0'; ++trv) { + ; + } + trv -= slen; + suffp = trv; + --trv; + if (trv < path) { + errno = EINVAL; + return (0); + } - /* Fill space with random characters */ - while (trv >= path && *trv == 'X') { - rand = (RandomNumber<ui32>()) % (sizeof(padchar) - 1); - *trv-- = padchar[rand]; - } - start = trv + 1; + /* Fill space with random characters */ + while (trv >= path && *trv == 'X') { + rand = (RandomNumber<ui32>()) % (sizeof(padchar) - 1); + *trv-- = padchar[rand]; + } + start = trv + 1; - /* + /* * check the target directory. */ - if (doopen != nullptr || domkdir) { - for (; trv > path; --trv) { - if (*trv == '/') { - *trv = '\0'; + if (doopen != nullptr || domkdir) { + for (; trv > path; --trv) { + if (*trv == '/') { + *trv = '\0'; #ifdef _win32_ - ui32 attr = ::GetFileAttributesA(path); - *trv = '/'; - if (attr == 0xFFFFFFFF) - return (0); - if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { - errno = ENOTDIR; - return (0); - } + ui32 attr = ::GetFileAttributesA(path); + *trv = '/'; + if (attr == 0xFFFFFFFF) + return (0); + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = ENOTDIR; + return (0); + } #else - rval = stat(path, &sbuf); - *trv = '/'; - if (rval != 0) { - return (0); - } - if (!S_ISDIR(sbuf.st_mode)) { - errno = ENOTDIR; - return (0); - } + rval = stat(path, &sbuf); + *trv = '/'; + if (rval != 0) { + return (0); + } + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return (0); + } #endif - break; - } + break; + } } - } + } - for (;;) { - if (doopen) { - if ((*doopen = - open(path, O_CREAT | O_EXCL | O_RDWR, 0600)) >= 0) { - return (1); - } - if (errno != EEXIST) { - return (0); - } - } else if (domkdir) { - if (Mkdir(path, S_IRWXU) == 0) { - return (1); - } - if (errno != EEXIST) { - return (0); - } - } else + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT | O_EXCL | O_RDWR, 0600)) >= 0) { + return (1); + } + if (errno != EEXIST) { + return (0); + } + } else if (domkdir) { + if (Mkdir(path, S_IRWXU) == 0) { + return (1); + } + if (errno != EEXIST) { + return (0); + } + } else #ifdef _win32_ - if (::GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) - return (errno == ENOENT); + if (::GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) + return (errno == ENOENT); #else - if (lstat(path, &sbuf)) { - return (errno == ENOENT); - } + if (lstat(path, &sbuf)) { + return (errno == ENOENT); + } #endif - /* If we have a collision, cycle through the space of filenames */ - for (trv = start;;) { - if (*trv == '\0' || trv == suffp) { - return (0); - } - pad = strchr((char*)padchar, *trv); - if (pad == nullptr || *++pad == '\0') { - *trv++ = padchar[0]; - } else { - *trv++ = *pad; - break; - } + /* If we have a collision, cycle through the space of filenames */ + for (trv = start;;) { + if (*trv == '\0' || trv == suffp) { + return (0); + } + pad = strchr((char*)padchar, *trv); + if (pad == nullptr || *++pad == '\0') { + *trv++ = padchar[0]; + } else { + *trv++ = *pad; + break; + } } - } - /*NOTREACHED*/ + } + /*NOTREACHED*/ } -extern "C" int mkstemps(char* path, int slen) { - int fd; +extern "C" int mkstemps(char* path, int slen) { + int fd; return (GetTemp(path, &fd, 0, slen) ? fd : -1); } -#if defined(_win_) -char* mkdtemp(char* path) { - return (GetTemp(path, (int*)nullptr, 1, 0) ? path : (char*)nullptr); +#if defined(_win_) +char* mkdtemp(char* path) { + return (GetTemp(path, (int*)nullptr, 1, 0) ? path : (char*)nullptr); } -#endif +#endif diff --git a/util/system/mlock.cpp b/util/system/mlock.cpp index 435338c98f..03e68d8f50 100644 --- a/util/system/mlock.cpp +++ b/util/system/mlock.cpp @@ -5,24 +5,24 @@ #include "mlock.h" #if defined(_unix_) - #include <sys/mman.h> - #if !defined(MCL_ONFAULT) && defined(MCL_FUTURE) // Old glibc. - #define MCL_ONFAULT (MCL_FUTURE << 1) - #endif - #if defined(_android_) - #include <sys/syscall.h> - #define munlockall() syscall(__NR_munlockall) - #endif + #include <sys/mman.h> + #if !defined(MCL_ONFAULT) && defined(MCL_FUTURE) // Old glibc. + #define MCL_ONFAULT (MCL_FUTURE << 1) + #endif + #if defined(_android_) + #include <sys/syscall.h> + #define munlockall() syscall(__NR_munlockall) + #endif #else - #include "winint.h" + #include "winint.h" #endif -void LockMemory(const void* addr, size_t len) { +void LockMemory(const void* addr, size_t len) { #if defined(_unix_) const size_t pageSize = NSystemInfo::GetPageSize(); - if (mlock(AlignDown(addr, pageSize), AlignUp(len, pageSize))) { + if (mlock(AlignDown(addr, pageSize), AlignUp(len, pageSize))) { ythrow yexception() << LastSystemErrorText(); - } + } #elif defined(_win_) HANDLE hndl = GetCurrentProcess(); SIZE_T min, max; @@ -35,11 +35,11 @@ void LockMemory(const void* addr, size_t len) { #endif } -void UnlockMemory(const void* addr, size_t len) { +void UnlockMemory(const void* addr, size_t len) { #if defined(_unix_) - if (munlock(addr, len)) { + if (munlock(addr, len)) { ythrow yexception() << LastSystemErrorText(); - } + } #elif defined(_win_) HANDLE hndl = GetCurrentProcess(); SIZE_T min, max; @@ -55,9 +55,9 @@ void UnlockMemory(const void* addr, size_t len) { void LockAllMemory(ELockAllMemoryFlags flags) { Y_UNUSED(flags); #if defined(_android_) -// unimplemented +// unimplemented #elif defined(_cygwin_) -// unimplemented +// unimplemented #elif defined(_unix_) int sys_flags = 0; if (flags & LockCurrentMemory) { @@ -75,12 +75,12 @@ void LockAllMemory(ELockAllMemoryFlags flags) { #endif } -void UnlockAllMemory() { -#if defined(_cygwin_) -// unimplemented -#elif defined(_unix_) - if (munlockall()) { +void UnlockAllMemory() { +#if defined(_cygwin_) +// unimplemented +#elif defined(_unix_) + if (munlockall()) { ythrow yexception() << LastSystemErrorText(); - } + } #endif } diff --git a/util/system/mutex.cpp b/util/system/mutex.cpp index 4041402db9..a20aa20b11 100644 --- a/util/system/mutex.cpp +++ b/util/system/mutex.cpp @@ -1,146 +1,146 @@ -#include "mutex.h" - -#include <util/generic/yexception.h> +#include "mutex.h" + +#include <util/generic/yexception.h> #include <errno.h> - -#if defined(_win_) - #include "winint.h" -#else - #include <pthread.h> + +#if defined(_win_) + #include "winint.h" +#else + #include <pthread.h> #endif class TMutex::TImpl { -public: - inline TImpl() { -#if defined(_win_) - InitializeCriticalSection(&Obj); +public: + inline TImpl() { +#if defined(_win_) + InitializeCriticalSection(&Obj); #else - struct T { - pthread_mutexattr_t Attr; - - inline T() { - int result; + struct T { + pthread_mutexattr_t Attr; + + inline T() { + int result; memset(&Attr, 0, sizeof(Attr)); - result = pthread_mutexattr_init(&Attr); - if (result != 0) { - ythrow yexception() << "mutexattr init failed(" << LastSystemErrorText(result) << ")"; - } - - result = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); - if (result != 0) { - ythrow yexception() << "mutexattr set type failed(" << LastSystemErrorText(result) << ")"; - } - } - + result = pthread_mutexattr_init(&Attr); + if (result != 0) { + ythrow yexception() << "mutexattr init failed(" << LastSystemErrorText(result) << ")"; + } + + result = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); + if (result != 0) { + ythrow yexception() << "mutexattr set type failed(" << LastSystemErrorText(result) << ")"; + } + } + inline ~T() { - int result = pthread_mutexattr_destroy(&Attr); + int result = pthread_mutexattr_destroy(&Attr); Y_VERIFY(result == 0, "mutexattr destroy(%s)", LastSystemErrorText(result)); - } - } pma; - - int result = pthread_mutex_init(&Obj, &pma.Attr); - if (result != 0) { - ythrow yexception() << "mutex init failed(" << LastSystemErrorText(result) << ")"; - } + } + } pma; + + int result = pthread_mutex_init(&Obj, &pma.Attr); + if (result != 0) { + ythrow yexception() << "mutex init failed(" << LastSystemErrorText(result) << ")"; + } #endif - } + } inline ~TImpl() { -#if defined(_win_) - DeleteCriticalSection(&Obj); +#if defined(_win_) + DeleteCriticalSection(&Obj); #else - int result = pthread_mutex_destroy(&Obj); + int result = pthread_mutex_destroy(&Obj); Y_VERIFY(result == 0, "mutex destroy failure (%s)", LastSystemErrorText(result)); #endif - } - + } + inline void Acquire() noexcept { -#if defined(_win_) - EnterCriticalSection(&Obj); +#if defined(_win_) + EnterCriticalSection(&Obj); #else - int result = pthread_mutex_lock(&Obj); + int result = pthread_mutex_lock(&Obj); Y_VERIFY(result == 0, "mutex lock failure (%s)", LastSystemErrorText(result)); #endif - } - -#if defined(_win_) - static bool TryEnterCriticalSectionInt(CRITICAL_SECTION* obj) { - #if (_WIN32_WINNT < 0x0400) - if (-1L == ::InterlockedCompareExchange(&obj->LockCount, 0, -1)) { - obj->OwningThread = (HANDLE)(DWORD_PTR)::GetCurrentThreadId(); - obj->RecursionCount = 1; - - return true; - } - - if (obj->OwningThread == (HANDLE)(DWORD_PTR)::GetCurrentThreadId()) { - ::InterlockedIncrement(&obj->LockCount); - ++obj->RecursionCount; - return true; - } - - return false; - #else // _WIN32_WINNT < 0x0400 - return TryEnterCriticalSection(obj); - #endif // _WIN32_WINNT < 0x0400 - } + } + +#if defined(_win_) + static bool TryEnterCriticalSectionInt(CRITICAL_SECTION* obj) { + #if (_WIN32_WINNT < 0x0400) + if (-1L == ::InterlockedCompareExchange(&obj->LockCount, 0, -1)) { + obj->OwningThread = (HANDLE)(DWORD_PTR)::GetCurrentThreadId(); + obj->RecursionCount = 1; + + return true; + } + + if (obj->OwningThread == (HANDLE)(DWORD_PTR)::GetCurrentThreadId()) { + ::InterlockedIncrement(&obj->LockCount); + ++obj->RecursionCount; + return true; + } + + return false; + #else // _WIN32_WINNT < 0x0400 + return TryEnterCriticalSection(obj); + #endif // _WIN32_WINNT < 0x0400 + } #endif // _win_ - + inline bool TryAcquire() noexcept { -#if defined(_win_) - return TryEnterCriticalSectionInt(&Obj); +#if defined(_win_) + return TryEnterCriticalSectionInt(&Obj); #else - int result = pthread_mutex_trylock(&Obj); - if (result == 0 || result == EBUSY) { - return result == 0; - } + int result = pthread_mutex_trylock(&Obj); + if (result == 0 || result == EBUSY) { + return result == 0; + } Y_FAIL("mutex trylock failure (%s)", LastSystemErrorText(result)); #endif - } - + } + inline void Release() noexcept { -#if defined(_win_) - LeaveCriticalSection(&Obj); +#if defined(_win_) + LeaveCriticalSection(&Obj); #else - int result = pthread_mutex_unlock(&Obj); + int result = pthread_mutex_unlock(&Obj); Y_VERIFY(result == 0, "mutex unlock failure (%s)", LastSystemErrorText(result)); #endif - } - + } + inline void* Handle() const noexcept { - return (void*)&Obj; - } - -private: -#ifdef _win_ - CRITICAL_SECTION Obj; -#else - pthread_mutex_t Obj; -#endif -}; - + return (void*)&Obj; + } + +private: +#ifdef _win_ + CRITICAL_SECTION Obj; +#else + pthread_mutex_t Obj; +#endif +}; + TMutex::TMutex() - : Impl_(new TImpl()) -{ + : Impl_(new TImpl()) +{ } TMutex::TMutex(TMutex&&) = default; TMutex::~TMutex() = default; - + void TMutex::Acquire() noexcept { - Impl_->Acquire(); -} - + Impl_->Acquire(); +} + bool TMutex::TryAcquire() noexcept { - return Impl_->TryAcquire(); -} - + return Impl_->TryAcquire(); +} + void TMutex::Release() noexcept { - Impl_->Release(); -} - + Impl_->Release(); +} + void* TMutex::Handle() const noexcept { - return Impl_->Handle(); -} + return Impl_->Handle(); +} diff --git a/util/system/mutex.h b/util/system/mutex.h index 032630d134..519ad426b9 100644 --- a/util/system/mutex.h +++ b/util/system/mutex.h @@ -1,22 +1,22 @@ #pragma once -#include "guard.h" -#include "defaults.h" - +#include "guard.h" +#include "defaults.h" + #include <util/generic/ptr.h> #include <util/generic/noncopyable.h> -class TFakeMutex: public TNonCopyable { -public: +class TFakeMutex: public TNonCopyable { +public: inline void Acquire() noexcept { - } + } inline bool TryAcquire() noexcept { - return true; - } + return true; + } inline void Release() noexcept { - } + } inline void lock() noexcept { Acquire(); @@ -31,18 +31,18 @@ public: } ~TFakeMutex() = default; -}; +}; class TMutex { -public: +public: TMutex(); TMutex(TMutex&&); ~TMutex(); - + void Acquire() noexcept; bool TryAcquire() noexcept; void Release() noexcept; - + inline void lock() noexcept { Acquire(); } @@ -55,10 +55,10 @@ public: Release(); } - //return opaque pointer to real handler + //return opaque pointer to real handler void* Handle() const noexcept; - -private: - class TImpl; - THolder<TImpl> Impl_; -}; + +private: + class TImpl; + THolder<TImpl> Impl_; +}; diff --git a/util/system/mutex_ut.cpp b/util/system/mutex_ut.cpp index c8d7caafa1..3327408600 100644 --- a/util/system/mutex_ut.cpp +++ b/util/system/mutex_ut.cpp @@ -1,16 +1,16 @@ -#include "mutex.h" -#include "atomic.h" - +#include "mutex.h" +#include "atomic.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/thread/pool.h> #include <util/random/random.h> -class TMutexTest: public TTestBase { +class TMutexTest: public TTestBase { UNIT_TEST_SUITE(TMutexTest); - UNIT_TEST(TestBasics) - UNIT_TEST(TestFake) - UNIT_TEST(TestRecursive) + UNIT_TEST(TestBasics) + UNIT_TEST(TestFake) + UNIT_TEST(TestRecursive) UNIT_TEST_SUITE_END(); struct TSharedData { @@ -27,102 +27,102 @@ class TMutexTest: public TTestBase { bool failed; }; - class TThreadTask: public IObjectInQueue { - public: + class TThreadTask: public IObjectInQueue { + public: using PFunc = void (TThreadTask::*)(void); - TThreadTask(PFunc func, TSharedData& data, size_t id) - : Func_(func) - , Data_(data) - , Id_(id) - { - } + TThreadTask(PFunc func, TSharedData& data, size_t id) + : Func_(func) + , Data_(data) + , Id_(id) + { + } void Process(void*) override { - THolder<TThreadTask> This(this); - - (this->*Func_)(); - } - -#define FAIL_ASSERT(cond) \ - if (!(cond)) { \ - Data_.failed = true; \ + THolder<TThreadTask> This(this); + + (this->*Func_)(); + } + +#define FAIL_ASSERT(cond) \ + if (!(cond)) { \ + Data_.failed = true; \ } - void RunBasics() { - Data_.mutex.Acquire(); - - ui32 oldCounter = ui32(Data_.sharedCounter + Id_); - Data_.sharedCounter = oldCounter; - usleep(10 + RandomNumber<ui32>() % 10); - FAIL_ASSERT(Data_.sharedCounter == oldCounter); - - Data_.mutex.Release(); - } - - void RunFakeMutex() { - bool res = Data_.fakeMutex.TryAcquire(); - FAIL_ASSERT(res); - } - - void RunRecursiveMutex() { - for (size_t i = 0; i < Id_ + 1; ++i) { - Data_.mutex.Acquire(); - ++Data_.sharedCounter; - usleep(1); + void RunBasics() { + Data_.mutex.Acquire(); + + ui32 oldCounter = ui32(Data_.sharedCounter + Id_); + Data_.sharedCounter = oldCounter; + usleep(10 + RandomNumber<ui32>() % 10); + FAIL_ASSERT(Data_.sharedCounter == oldCounter); + + Data_.mutex.Release(); + } + + void RunFakeMutex() { + bool res = Data_.fakeMutex.TryAcquire(); + FAIL_ASSERT(res); + } + + void RunRecursiveMutex() { + for (size_t i = 0; i < Id_ + 1; ++i) { + Data_.mutex.Acquire(); + ++Data_.sharedCounter; + usleep(1); } - FAIL_ASSERT(Data_.sharedCounter == Id_ + 1); - - bool res = Data_.mutex.TryAcquire(); - FAIL_ASSERT(res); - Data_.mutex.Release(); - - for (size_t i = 0; i < Id_; ++i) { - --Data_.sharedCounter; - Data_.mutex.Release(); + FAIL_ASSERT(Data_.sharedCounter == Id_ + 1); + + bool res = Data_.mutex.TryAcquire(); + FAIL_ASSERT(res); + Data_.mutex.Release(); + + for (size_t i = 0; i < Id_; ++i) { + --Data_.sharedCounter; + Data_.mutex.Release(); } - FAIL_ASSERT(Data_.sharedCounter == 1); - --Data_.sharedCounter; - Data_.mutex.Release(); - } + FAIL_ASSERT(Data_.sharedCounter == 1); + --Data_.sharedCounter; + Data_.mutex.Release(); + } #undef FAIL_ASSERT - private: - PFunc Func_; - TSharedData& Data_; - size_t Id_; + private: + PFunc Func_; + TSharedData& Data_; + size_t Id_; }; -private: -#define RUN_CYCLE(what, count) \ - Q_.Start(count); \ - for (size_t i = 0; i < count; ++i) { \ - UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i))); \ - } \ - Q_.Stop(); \ - bool b = Data_.failed; \ - Data_.failed = false; \ - UNIT_ASSERT(!b); - - void TestBasics() { - RUN_CYCLE(RunBasics, 5); - - UNIT_ASSERT(Data_.sharedCounter == 10); - Data_.sharedCounter = 0; - } +private: +#define RUN_CYCLE(what, count) \ + Q_.Start(count); \ + for (size_t i = 0; i < count; ++i) { \ + UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i))); \ + } \ + Q_.Stop(); \ + bool b = Data_.failed; \ + Data_.failed = false; \ + UNIT_ASSERT(!b); - void TestFake() { - RUN_CYCLE(RunFakeMutex, 3); - } + void TestBasics() { + RUN_CYCLE(RunBasics, 5); - void TestRecursive() { - RUN_CYCLE(RunRecursiveMutex, 4); - } + UNIT_ASSERT(Data_.sharedCounter == 10); + Data_.sharedCounter = 0; + } + + void TestFake() { + RUN_CYCLE(RunFakeMutex, 3); + } + + void TestRecursive() { + RUN_CYCLE(RunRecursiveMutex, 4); + } #undef RUN_CYCLE -private: - TSharedData Data_; +private: + TSharedData Data_; TThreadPool Q_; }; diff --git a/util/system/nice.cpp b/util/system/nice.cpp index 20fe926054..4cbbf31cd0 100644 --- a/util/system/nice.cpp +++ b/util/system/nice.cpp @@ -3,7 +3,7 @@ #include "platform.h" #if defined(_unix_) - #include <unistd.h> + #include <unistd.h> #endif bool Nice(int prioDelta) { diff --git a/util/system/nice_ut.cpp b/util/system/nice_ut.cpp index ae0051f285..e029008265 100644 --- a/util/system/nice_ut.cpp +++ b/util/system/nice_ut.cpp @@ -5,7 +5,7 @@ #include <library/cpp/testing/unittest/registar.h> #ifdef _unix_ - #include <sys/resource.h> + #include <sys/resource.h> static int GetPriority() { return getpriority(PRIO_PROCESS, 0); @@ -20,23 +20,23 @@ Y_UNIT_TEST_SUITE(NiceTest) { #ifdef _unix_ Y_UNIT_TEST(TestNice) { int prio = GetPriority(); - - if (prio >= 10) { - return; - } - + + if (prio >= 10) { + return; + } + if (Nice(-2)) { UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio - 2); prio -= 2; } else { UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio); } - UNIT_ASSERT(Nice(1)); - UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 1); + UNIT_ASSERT(Nice(1)); + UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 1); UNIT_ASSERT(Nice(0)); - UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 1); - UNIT_ASSERT(Nice(2)); - UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 3); + UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 1); + UNIT_ASSERT(Nice(2)); + UNIT_ASSERT_VALUES_EQUAL(GetPriority(), prio + 3); } #endif } diff --git a/util/system/pipe.cpp b/util/system/pipe.cpp index a543bd7472..012ee2c30e 100644 --- a/util/system/pipe.cpp +++ b/util/system/pipe.cpp @@ -1,50 +1,50 @@ -#include "pipe.h" - +#include "pipe.h" + #include <util/stream/output.h> -#include <util/generic/yexception.h> +#include <util/generic/yexception.h> ssize_t TPipeHandle::Read(void* buffer, size_t byteCount) const noexcept { #ifdef _win_ - return recv(Fd_, (char*)buffer, byteCount, 0); + return recv(Fd_, (char*)buffer, byteCount, 0); #else - return read(Fd_, buffer, byteCount); + return read(Fd_, buffer, byteCount); #endif } ssize_t TPipeHandle::Write(const void* buffer, size_t byteCount) const noexcept { #ifdef _win_ - return send(Fd_, (const char*)buffer, byteCount, 0); + return send(Fd_, (const char*)buffer, byteCount, 0); #else - return write(Fd_, buffer, byteCount); + return write(Fd_, buffer, byteCount); #endif } bool TPipeHandle::Close() noexcept { bool ok = true; - if (Fd_ != INVALID_PIPEHANDLE) { + if (Fd_ != INVALID_PIPEHANDLE) { #ifdef _win_ - ok = closesocket(Fd_) == 0; + ok = closesocket(Fd_) == 0; #else - ok = close(Fd_) == 0; + ok = close(Fd_) == 0; #endif } - Fd_ = INVALID_PIPEHANDLE; + Fd_ = INVALID_PIPEHANDLE; return ok; } void TPipeHandle::Pipe(TPipeHandle& reader, TPipeHandle& writer, EOpenMode mode) { - PIPEHANDLE fds[2]; -#ifdef _win_ + PIPEHANDLE fds[2]; +#ifdef _win_ int r = SocketPair(fds, false /* non-overlapped */, mode & CloseOnExec /* cloexec */); #elif defined(_linux_) int r = pipe2(fds, mode & CloseOnExec ? O_CLOEXEC : 0); -#else - int r = pipe(fds); -#endif - if (r < 0) { - ythrow TFileError() << "failed to create a pipe"; - } - +#else + int r = pipe(fds); +#endif + if (r < 0) { + ythrow TFileError() << "failed to create a pipe"; + } + #if !defined(_win_) && !defined(_linux_) // Non-atomic wrt exec if (mode & CloseOnExec) { @@ -61,19 +61,19 @@ void TPipeHandle::Pipe(TPipeHandle& reader, TPipeHandle& writer, EOpenMode mode) } #endif - TPipeHandle(fds[0]).Swap(reader); - TPipeHandle(fds[1]).Swap(writer); -} - -class TPipe::TImpl: public TAtomicRefCount<TImpl> { + TPipeHandle(fds[0]).Swap(reader); + TPipeHandle(fds[1]).Swap(writer); +} + +class TPipe::TImpl: public TAtomicRefCount<TImpl> { public: TImpl() - : Handle_(INVALID_PIPEHANDLE) + : Handle_(INVALID_PIPEHANDLE) { } - + TImpl(PIPEHANDLE fd) - : Handle_(fd) + : Handle_(fd) { } @@ -82,80 +82,80 @@ public: } bool IsOpen() { - return Handle_.IsOpen(); + return Handle_.IsOpen(); } inline void Close() { - if (!Handle_.IsOpen()) { + if (!Handle_.IsOpen()) { return; - } - if (!Handle_.Close()) { - ythrow TFileError() << "failed to close pipe"; - } + } + if (!Handle_.Close()) { + ythrow TFileError() << "failed to close pipe"; + } } TPipeHandle& GetHandle() noexcept { - return Handle_; + return Handle_; } size_t Read(void* buffer, size_t count) const { - ssize_t r = Handle_.Read(buffer, count); - if (r < 0) { - ythrow TFileError() << "failed to read from pipe"; - } + ssize_t r = Handle_.Read(buffer, count); + if (r < 0) { + ythrow TFileError() << "failed to read from pipe"; + } return r; } size_t Write(const void* buffer, size_t count) const { - ssize_t r = Handle_.Write(buffer, count); - if (r < 0) { - ythrow TFileError() << "failed to write to pipe"; - } + ssize_t r = Handle_.Write(buffer, count); + if (r < 0) { + ythrow TFileError() << "failed to write to pipe"; + } return r; } - + private: - TPipeHandle Handle_; + TPipeHandle Handle_; }; TPipe::TPipe() - : Impl_(new TImpl) + : Impl_(new TImpl) { } TPipe::TPipe(PIPEHANDLE fd) - : Impl_(new TImpl(fd)) + : Impl_(new TImpl(fd)) { } TPipe::~TPipe() = default; void TPipe::Close() { - Impl_->Close(); + Impl_->Close(); } PIPEHANDLE TPipe::GetHandle() const noexcept { - return Impl_->GetHandle(); + return Impl_->GetHandle(); } bool TPipe::IsOpen() const noexcept { - return Impl_->IsOpen(); + return Impl_->IsOpen(); } size_t TPipe::Read(void* buf, size_t len) const { - return Impl_->Read(buf, len); + return Impl_->Read(buf, len); } size_t TPipe::Write(const void* buf, size_t len) const { - return Impl_->Write(buf, len); + return Impl_->Write(buf, len); } void TPipe::Pipe(TPipe& reader, TPipe& writer, EOpenMode mode) { - TImplRef r(new TImpl()); - TImplRef w(new TImpl()); - + TImplRef r(new TImpl()); + TImplRef w(new TImpl()); + TPipeHandle::Pipe(r->GetHandle(), w->GetHandle(), mode); - - r.Swap(reader.Impl_); - w.Swap(writer.Impl_); + + r.Swap(reader.Impl_); + w.Swap(writer.Impl_); } diff --git a/util/system/pipe.h b/util/system/pipe.h index 75d0360049..435e635724 100644 --- a/util/system/pipe.h +++ b/util/system/pipe.h @@ -1,29 +1,29 @@ #pragma once #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Warray-bounds" //need because of bug in gcc4.9.2 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" //need because of bug in gcc4.9.2 #endif -#include "defaults.h" +#include "defaults.h" #include "file.h" #include <util/generic/ptr.h> -#include <util/network/pair.h> -#include <util/generic/noncopyable.h> +#include <util/network/pair.h> +#include <util/generic/noncopyable.h> using PIPEHANDLE = SOCKET; -#define INVALID_PIPEHANDLE INVALID_SOCKET - +#define INVALID_PIPEHANDLE INVALID_SOCKET + /// Pipe-like object: pipe on POSIX and socket on windows -class TPipeHandle: public TNonCopyable { +class TPipeHandle: public TNonCopyable { public: inline TPipeHandle() noexcept - : Fd_(INVALID_PIPEHANDLE) - { - } - + : Fd_(INVALID_PIPEHANDLE) + { + } + inline TPipeHandle(PIPEHANDLE fd) noexcept - : Fd_(fd) + : Fd_(fd) { } @@ -34,21 +34,21 @@ public: bool Close() noexcept; inline PIPEHANDLE Release() noexcept { - PIPEHANDLE ret = Fd_; - Fd_ = INVALID_PIPEHANDLE; + PIPEHANDLE ret = Fd_; + Fd_ = INVALID_PIPEHANDLE; return ret; } inline void Swap(TPipeHandle& r) noexcept { - DoSwap(Fd_, r.Fd_); + DoSwap(Fd_, r.Fd_); } inline operator PIPEHANDLE() const noexcept { - return Fd_; + return Fd_; } inline bool IsOpen() const noexcept { - return Fd_ != INVALID_PIPEHANDLE; + return Fd_ != INVALID_PIPEHANDLE; } ssize_t Read(void* buffer, size_t byteCount) const noexcept; @@ -56,9 +56,9 @@ public: // Only CloseOnExec is supported static void Pipe(TPipeHandle& reader, TPipeHandle& writer, EOpenMode mode = 0); - + private: - PIPEHANDLE Fd_; + PIPEHANDLE Fd_; }; class TPipe { @@ -82,9 +82,9 @@ public: private: class TImpl; using TImplRef = TSimpleIntrusivePtr<TImpl>; - TImplRef Impl_; + TImplRef Impl_; }; #ifdef __GNUC__ - #pragma GCC diagnostic pop + #pragma GCC diagnostic pop #endif diff --git a/util/system/pipe_ut.cpp b/util/system/pipe_ut.cpp index 6d53432de8..1ca4e01faa 100644 --- a/util/system/pipe_ut.cpp +++ b/util/system/pipe_ut.cpp @@ -1,5 +1,5 @@ -#include "pipe.h" - +#include "pipe.h" + #include <library/cpp/testing/unittest/registar.h> Y_UNIT_TEST_SUITE(TPipeTest) { diff --git a/util/system/platform.cpp b/util/system/platform.cpp index 9421235bb4..f08c85eb38 100644 --- a/util/system/platform.cpp +++ b/util/system/platform.cpp @@ -1,18 +1,18 @@ -#include "platform.h" - -#include <cstddef> - -static_assert(sizeof(char) == SIZEOF_CHAR, "incorrect SIZEOF_CHAR"); -static_assert(sizeof(short) == SIZEOF_SHORT, "incorrect SIZEOF_SHORT"); -static_assert(sizeof(int) == SIZEOF_INT, "incorrect SIZEOF_INT"); -static_assert(sizeof(long) == SIZEOF_LONG, "incorrect SIZEOF_LONG"); -static_assert(sizeof(long long) == SIZEOF_LONG_LONG, "incorrect SIZEOF_LONG_LONG"); - -static_assert(sizeof(unsigned char) == SIZEOF_UNSIGNED_CHAR, "incorrect SIZEOF_UNSIGNED_CHAR"); -static_assert(sizeof(unsigned short) == SIZEOF_UNSIGNED_SHORT, "incorrect SIZEOF_UNSIGNED_SHORT"); -static_assert(sizeof(unsigned int) == SIZEOF_UNSIGNED_INT, "incorrect SIZEOF_UNSIGNED_INT"); -static_assert(sizeof(unsigned long) == SIZEOF_UNSIGNED_LONG, "incorrect SIZEOF_UNSIGNED_LONG"); -static_assert(sizeof(unsigned long long) == SIZEOF_UNSIGNED_LONG_LONG, "incorrect SIZEOF_UNSIGNED_LONG_LONG"); - -static_assert(sizeof(void*) == SIZEOF_PTR, "incorrect SIZEOF_PTR"); -static_assert(sizeof(void*) == sizeof(size_t), "unsupported platform"); +#include "platform.h" + +#include <cstddef> + +static_assert(sizeof(char) == SIZEOF_CHAR, "incorrect SIZEOF_CHAR"); +static_assert(sizeof(short) == SIZEOF_SHORT, "incorrect SIZEOF_SHORT"); +static_assert(sizeof(int) == SIZEOF_INT, "incorrect SIZEOF_INT"); +static_assert(sizeof(long) == SIZEOF_LONG, "incorrect SIZEOF_LONG"); +static_assert(sizeof(long long) == SIZEOF_LONG_LONG, "incorrect SIZEOF_LONG_LONG"); + +static_assert(sizeof(unsigned char) == SIZEOF_UNSIGNED_CHAR, "incorrect SIZEOF_UNSIGNED_CHAR"); +static_assert(sizeof(unsigned short) == SIZEOF_UNSIGNED_SHORT, "incorrect SIZEOF_UNSIGNED_SHORT"); +static_assert(sizeof(unsigned int) == SIZEOF_UNSIGNED_INT, "incorrect SIZEOF_UNSIGNED_INT"); +static_assert(sizeof(unsigned long) == SIZEOF_UNSIGNED_LONG, "incorrect SIZEOF_UNSIGNED_LONG"); +static_assert(sizeof(unsigned long long) == SIZEOF_UNSIGNED_LONG_LONG, "incorrect SIZEOF_UNSIGNED_LONG_LONG"); + +static_assert(sizeof(void*) == SIZEOF_PTR, "incorrect SIZEOF_PTR"); +static_assert(sizeof(void*) == sizeof(size_t), "unsupported platform"); diff --git a/util/system/platform.h b/util/system/platform.h index 58f310ab34..79c2dfa49b 100644 --- a/util/system/platform.h +++ b/util/system/platform.h @@ -1,17 +1,17 @@ #pragma once - + // ya style breaks indentation in ifdef's and code becomes unreadable // clang-format off -// What OS ? -// our definition has the form _{osname}_ - -#if defined(_WIN64) +// What OS ? +// our definition has the form _{osname}_ + +#if defined(_WIN64) #define _win64_ #define _win32_ -#elif defined(__WIN32__) || defined(_WIN32) // _WIN32 is also defined by the 64-bit compiler for backward compatibility +#elif defined(__WIN32__) || defined(_WIN32) // _WIN32 is also defined by the 64-bit compiler for backward compatibility #define _win32_ -#else +#else #define _unix_ #if defined(__sun__) || defined(sun) || defined(sparc) || defined(__sparc) @@ -42,13 +42,13 @@ #if defined(__ANDROID__) #define _android_ #endif -#endif - +#endif + #if defined(__IOS__) #define _ios_ #endif -#if defined(_linux_) +#if defined(_linux_) #if defined(_musl_) // nothing to do #elif defined(_android_) @@ -58,17 +58,17 @@ #else #define _glibc_ #endif -#endif - -#if defined(_darwin_) +#endif + +#if defined(_darwin_) #define unix #define __unix__ -#endif - -#if defined(_win32_) || defined(_win64_) +#endif + +#if defined(_win32_) || defined(_win64_) #define _win_ -#endif - +#endif + #if defined(__arm__) || defined(__ARM__) || defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM) #if defined(__arm64) || defined(__arm64__) || defined(__aarch64__) #define _arm64_ @@ -77,7 +77,7 @@ #endif #endif -#if defined(_arm64_) || defined(_arm32_) +#if defined(_arm64_) || defined(_arm32_) #define _arm_ #endif @@ -89,16 +89,16 @@ */ #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) #define _x86_64_ -#endif - +#endif + #if defined(__i386__) || defined(_M_IX86) #define _i386_ #endif #if defined(__ia64__) || defined(_M_IA64) #define _ia64_ -#endif - +#endif + #if defined(__powerpc__) #define _ppc_ #endif @@ -111,41 +111,41 @@ #error "platform not defined, please, define one" #endif -#if defined(_x86_64_) || defined(_i386_) +#if defined(_x86_64_) || defined(_i386_) #define _x86_ -#endif - +#endif + #if defined(__MIC__) #define _mic_ #define _k1om_ #endif -// stdio or MessageBox -#if defined(__CONSOLE__) || defined(_CONSOLE) +// stdio or MessageBox +#if defined(__CONSOLE__) || defined(_CONSOLE) #define _console_ -#endif -#if (defined(_win_) && !defined(_console_)) +#endif +#if (defined(_win_) && !defined(_console_)) #define _windows_ -#elif !defined(_console_) +#elif !defined(_console_) #define _console_ -#endif - -#if defined(__SSE__) || defined(SSE_ENABLED) +#endif + +#if defined(__SSE__) || defined(SSE_ENABLED) #define _sse_ -#endif - -#if defined(__SSE2__) || defined(SSE2_ENABLED) +#endif + +#if defined(__SSE2__) || defined(SSE2_ENABLED) #define _sse2_ -#endif - +#endif + #if defined(__SSE3__) || defined(SSE3_ENABLED) #define _sse3_ #endif -#if defined(__SSSE3__) || defined(SSSE3_ENABLED) +#if defined(__SSSE3__) || defined(SSSE3_ENABLED) #define _ssse3_ -#endif - +#endif + #if defined(__SSE4_1__) || defined(SSE41_ENABLED) #define _sse4_1_ #endif @@ -178,17 +178,17 @@ #define _fma_ #endif -#if defined(__DLL__) || defined(_DLL) +#if defined(__DLL__) || defined(_DLL) #define _dll_ -#endif - -// 16, 32 or 64 +#endif + +// 16, 32 or 64 #if defined(__sparc_v9__) || defined(_x86_64_) || defined(_ia64_) || defined(_arm64_) || defined(_ppc64_) #define _64_ -#else +#else #define _32_ -#endif - +#endif + /* All modern 64-bit Unix systems use scheme LP64 (long, pointers are 64-bit). * Microsoft uses a different scheme: LLP64 (long long, pointers are 64-bit). * @@ -201,29 +201,29 @@ * pointer 64 64 */ -#if defined(_32_) +#if defined(_32_) #define SIZEOF_PTR 4 -#elif defined(_64_) +#elif defined(_64_) #define SIZEOF_PTR 8 -#endif - -#define PLATFORM_DATA_ALIGN SIZEOF_PTR - -#if !defined(SIZEOF_PTR) +#endif + +#define PLATFORM_DATA_ALIGN SIZEOF_PTR + +#if !defined(SIZEOF_PTR) #error todo -#endif - -#define SIZEOF_CHAR 1 +#endif + +#define SIZEOF_CHAR 1 #define SIZEOF_UNSIGNED_CHAR 1 -#define SIZEOF_SHORT 2 +#define SIZEOF_SHORT 2 #define SIZEOF_UNSIGNED_SHORT 2 -#define SIZEOF_INT 4 +#define SIZEOF_INT 4 #define SIZEOF_UNSIGNED_INT 4 - -#if defined(_32_) + +#if defined(_32_) #define SIZEOF_LONG 4 #define SIZEOF_UNSIGNED_LONG 4 -#elif defined(_64_) +#elif defined(_64_) #if defined(_win_) #define SIZEOF_LONG 4 #define SIZEOF_UNSIGNED_LONG 4 @@ -232,15 +232,15 @@ #define SIZEOF_UNSIGNED_LONG 8 #endif // _win_ #endif // _32_ - -#if !defined(SIZEOF_LONG) + +#if !defined(SIZEOF_LONG) #error todo -#endif - -#define SIZEOF_LONG_LONG 8 +#endif + +#define SIZEOF_LONG_LONG 8 #define SIZEOF_UNSIGNED_LONG_LONG 8 - + #undef SIZEOF_SIZE_T // in case we include <Python.h> which defines it, too -#define SIZEOF_SIZE_T SIZEOF_PTR - +#define SIZEOF_SIZE_T SIZEOF_PTR + // clang-format on diff --git a/util/system/platform_ut.cpp b/util/system/platform_ut.cpp index 9bfbce8315..4da8617e7b 100644 --- a/util/system/platform_ut.cpp +++ b/util/system/platform_ut.cpp @@ -1,27 +1,27 @@ -#include "platform.h" - +#include "platform.h" + #include <library/cpp/testing/unittest/registar.h> - -class TPlatformTest: public TTestBase { - UNIT_TEST_SUITE(TPlatformTest); - UNIT_TEST(TestSizeOf) - UNIT_TEST_SUITE_END(); - -private: - inline void TestSizeOf() { - UNIT_ASSERT_EQUAL(SIZEOF_PTR, sizeof(void*)); - UNIT_ASSERT_EQUAL(SIZEOF_CHAR, sizeof(char)); - UNIT_ASSERT_EQUAL(SIZEOF_SHORT, sizeof(short)); - UNIT_ASSERT_EQUAL(SIZEOF_INT, sizeof(int)); - UNIT_ASSERT_EQUAL(SIZEOF_LONG, sizeof(long)); - UNIT_ASSERT_EQUAL(SIZEOF_LONG_LONG, sizeof(long long)); - UNIT_ASSERT_EQUAL(SIZEOF_SIZE_T, sizeof(size_t)); - UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_CHAR, sizeof(unsigned char)); - UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_INT, sizeof(unsigned int)); - UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_LONG, sizeof(unsigned long)); - UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_LONG_LONG, sizeof(unsigned long long)); - UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_SHORT, sizeof(unsigned short)); - } -}; - -UNIT_TEST_SUITE_REGISTRATION(TPlatformTest); + +class TPlatformTest: public TTestBase { + UNIT_TEST_SUITE(TPlatformTest); + UNIT_TEST(TestSizeOf) + UNIT_TEST_SUITE_END(); + +private: + inline void TestSizeOf() { + UNIT_ASSERT_EQUAL(SIZEOF_PTR, sizeof(void*)); + UNIT_ASSERT_EQUAL(SIZEOF_CHAR, sizeof(char)); + UNIT_ASSERT_EQUAL(SIZEOF_SHORT, sizeof(short)); + UNIT_ASSERT_EQUAL(SIZEOF_INT, sizeof(int)); + UNIT_ASSERT_EQUAL(SIZEOF_LONG, sizeof(long)); + UNIT_ASSERT_EQUAL(SIZEOF_LONG_LONG, sizeof(long long)); + UNIT_ASSERT_EQUAL(SIZEOF_SIZE_T, sizeof(size_t)); + UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_CHAR, sizeof(unsigned char)); + UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_INT, sizeof(unsigned int)); + UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_LONG, sizeof(unsigned long)); + UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_LONG_LONG, sizeof(unsigned long long)); + UNIT_ASSERT_EQUAL(SIZEOF_UNSIGNED_SHORT, sizeof(unsigned short)); + } +}; + +UNIT_TEST_SUITE_REGISTRATION(TPlatformTest); diff --git a/util/system/progname.cpp b/util/system/progname.cpp index 2c29119320..99c562c7e6 100644 --- a/util/system/progname.cpp +++ b/util/system/progname.cpp @@ -1,26 +1,26 @@ #include "execpath.h" -#include "progname.h" +#include "progname.h" + +#include <util/folder/dirut.h> +#include <util/generic/singleton.h> + +static const char* Argv0; -#include <util/folder/dirut.h> -#include <util/generic/singleton.h> - -static const char* Argv0; - -namespace { - struct TProgramNameHolder { - inline TProgramNameHolder() +namespace { + struct TProgramNameHolder { + inline TProgramNameHolder() : ProgName(GetFileNameComponent(Argv0 ? Argv0 : GetExecPath().data())) - { - } - + { + } + TString ProgName; - }; -} - + }; +} + const TString& GetProgramName() { return Singleton<TProgramNameHolder>()->ProgName; -} +} -void SetProgramName(const char* argv0) { +void SetProgramName(const char* argv0) { Argv0 = argv0; } diff --git a/util/system/progname.h b/util/system/progname.h index e5e2a0eee2..4cb2189556 100644 --- a/util/system/progname.h +++ b/util/system/progname.h @@ -1,13 +1,13 @@ #pragma once - + #include <util/generic/fwd.h> + +void SetProgramName(const char* argv0); -void SetProgramName(const char* argv0); - -#define SAVE_PROGRAM_NAME \ - do { \ - SetProgramName(argv[0]); \ - } while (0) +#define SAVE_PROGRAM_NAME \ + do { \ + SetProgramName(argv[0]); \ + } while (0) /// guaranted return the same immutable instance of TString const TString& GetProgramName(); diff --git a/util/system/progname_ut.cpp b/util/system/progname_ut.cpp index 11f3d9308b..08111984a0 100644 --- a/util/system/progname_ut.cpp +++ b/util/system/progname_ut.cpp @@ -1,18 +1,18 @@ -#include "progname.h" - +#include "progname.h" + #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TProgramNameTest) { Y_UNIT_TEST(TestIt) { TString progName = GetProgramName(); - - try { + + try { UNIT_ASSERT( progName.find("ut_util") != TString::npos || progName.find("util-system_ut") != TString::npos || progName.find("util-system-ut") != TString::npos); - } catch (...) { - Cerr << progName << Endl; - - throw; - } - } -} + } catch (...) { + Cerr << progName << Endl; + + throw; + } + } +} diff --git a/util/system/protect.cpp b/util/system/protect.cpp index bbb8d410df..1d4ce2b614 100644 --- a/util/system/protect.cpp +++ b/util/system/protect.cpp @@ -6,29 +6,29 @@ #include "yassert.h" -#if defined(_unix_) || defined(_darwin_) - #include <sys/mman.h> +#if defined(_unix_) || defined(_darwin_) + #include <sys/mman.h> #endif #ifdef _win_ - #include <Windows.h> + #include <Windows.h> #endif static TString ModeToString(const EProtectMemory mode) { TString strMode; - if (mode == PM_NONE) { + if (mode == PM_NONE) { return "PM_NONE"; - } + } - if (mode & PM_READ) { + if (mode & PM_READ) { strMode += "PM_READ|"; - } - if (mode & PM_WRITE) { + } + if (mode & PM_WRITE) { strMode += "PM_WRITE|"; - } - if (mode & PM_EXEC) { + } + if (mode & PM_EXEC) { strMode += "PM_EXEC|"; - } + } return strMode.substr(0, strMode.size() - 1); } @@ -37,19 +37,19 @@ void ProtectMemory(void* addr, const size_t length, const EProtectMemory mode) { #if defined(_unix_) || defined(_darwin_) int mpMode = PROT_NONE; - if (mode & PM_READ) { + if (mode & PM_READ) { mpMode |= PROT_READ; - } - if (mode & PM_WRITE) { + } + if (mode & PM_WRITE) { mpMode |= PROT_WRITE; - } - if (mode & PM_EXEC) { + } + if (mode & PM_EXEC) { mpMode |= PROT_EXEC; - } + } // some old manpages for mprotect say 'const void* addr', but that's wrong - if (mprotect(addr, length, mpMode) == -1) { + if (mprotect(addr, length, mpMode) == -1) { ythrow TSystemError() << "Memory protection failed for mode " << ModeToString(mode) << ". "; - } + } #endif #ifdef _win_ @@ -62,31 +62,31 @@ void ProtectMemory(void* addr, const size_t length, const EProtectMemory mode) { * one of them. A discussion was here: REVIEW: 39725 */ switch (mode.ToBaseType()) { - case PM_READ: - mpMode = PAGE_READONLY; - break; - case PM_WRITE: - mpMode = PAGE_READWRITE; - break; // BUG: no write-only support + case PM_READ: + mpMode = PAGE_READONLY; + break; + case PM_WRITE: + mpMode = PAGE_READWRITE; + break; // BUG: no write-only support /*case PM_WRITE: ythrow TSystemError() << "Write-only protection mode is not supported under Windows. ";*/ - case PM_READ | PM_WRITE: - mpMode = PAGE_READWRITE; - break; - case PM_EXEC: - mpMode = PAGE_EXECUTE; - break; - case PM_READ | PM_EXEC: - mpMode = PAGE_EXECUTE_READ; - break; - case PM_WRITE | PM_EXEC: - mpMode = PAGE_EXECUTE_READWRITE; - break; // BUG: no write-only support + case PM_READ | PM_WRITE: + mpMode = PAGE_READWRITE; + break; + case PM_EXEC: + mpMode = PAGE_EXECUTE; + break; + case PM_READ | PM_EXEC: + mpMode = PAGE_EXECUTE_READ; + break; + case PM_WRITE | PM_EXEC: + mpMode = PAGE_EXECUTE_READWRITE; + break; // BUG: no write-only support /*case PM_WRITE | PM_EXEC: ythrow TSystemError() << "Write-execute-only protection mode is not supported under Windows. ";*/ - case PM_READ | PM_WRITE | PM_EXEC: - mpMode = PAGE_EXECUTE_READWRITE; - break; + case PM_READ | PM_WRITE | PM_EXEC: + mpMode = PAGE_EXECUTE_READWRITE; + break; } DWORD oldMode = 0; if (!VirtualProtect(addr, length, mpMode, &oldMode)) diff --git a/util/system/protect.h b/util/system/protect.h index 26714f3e92..e524abc6ed 100644 --- a/util/system/protect.h +++ b/util/system/protect.h @@ -1,14 +1,14 @@ #pragma once -#include "defaults.h" +#include "defaults.h" #include <util/generic/flags.h> enum EProtectMemoryMode { - PM_NONE = 0x00, // no access allowed - PM_READ = 0x01, // read access allowed + PM_NONE = 0x00, // no access allowed + PM_READ = 0x01, // read access allowed PM_WRITE = 0x02, // write access allowed - PM_EXEC = 0x04 // execute access allowed + PM_EXEC = 0x04 // execute access allowed }; Y_DECLARE_FLAGS(EProtectMemory, EProtectMemoryMode) diff --git a/util/system/rusage.cpp b/util/system/rusage.cpp index 2befeca875..19d13d6c19 100644 --- a/util/system/rusage.cpp +++ b/util/system/rusage.cpp @@ -1,20 +1,20 @@ -#include "platform.h" +#include "platform.h" #if defined(__APPLE__) && defined(__MACH__) - #include <mach/mach.h> + #include <mach/mach.h> #endif #ifdef _win_ - #include "winint.h" - #include <psapi.h> + #include "winint.h" + #include <psapi.h> #else - #include <sys/time.h> - #include <sys/resource.h> + #include <sys/time.h> + #include <sys/resource.h> #endif @@ -26,10 +26,10 @@ #ifdef _win_ TDuration FiletimeToDuration(const FILETIME& ft) { - union { - ui64 ft_scalar; - FILETIME ft_struct; - } nt_time; + union { + ui64 ft_scalar; + FILETIME ft_struct; + } nt_time; nt_time.ft_struct = ft; return TDuration::MicroSeconds(nt_time.ft_scalar / 10); } @@ -59,9 +59,9 @@ size_t TRusage::GetCurrentRSS() { /* Linux ---------------------------------------------------- */ long rss = 0L; FILE* fp = nullptr; - if ((fp = fopen("/proc/self/statm", "r")) == nullptr) { + if ((fp = fopen("/proc/self/statm", "r")) == nullptr) { return (size_t)0L; /* Can't open? */ - } + } if (fscanf(fp, "%*s%ld", &rss) != 1) { fclose(fp); return (size_t)0L; /* Can't read? */ @@ -108,12 +108,12 @@ void TRusage::Fill() { ythrow TSystemError() << "rusage failed"; } - #if defined(_darwin_) + #if defined(_darwin_) // see https://lists.apple.com/archives/darwin-kernel/2009/Mar/msg00005.html MaxRss = ru.ru_maxrss; - #else + #else MaxRss = ru.ru_maxrss * 1024LL; - #endif + #endif MajorPageFaults = ru.ru_majflt; Utime = ru.ru_utime; Stime = ru.ru_stime; diff --git a/util/system/rusage.h b/util/system/rusage.h index 61aeca83f2..05d382b8ca 100644 --- a/util/system/rusage.h +++ b/util/system/rusage.h @@ -1,6 +1,6 @@ -#pragma once +#pragma once -#include "defaults.h" +#include "defaults.h" #include <util/generic/utility.h> #include <util/datetime/base.h> @@ -15,7 +15,7 @@ struct TRusage { TDuration Stime; void Fill(); - + static size_t GetCurrentRSS(); static TRusage Get() { diff --git a/util/system/rusage_ut.cpp b/util/system/rusage_ut.cpp index 0d4e0fe54b..8ebd805ec7 100644 --- a/util/system/rusage_ut.cpp +++ b/util/system/rusage_ut.cpp @@ -1,5 +1,5 @@ -#include "rusage.h" - +#include "rusage.h" + #include <library/cpp/testing/unittest/registar.h> Y_UNIT_TEST_SUITE(TRusageTest) { diff --git a/util/system/rwlock.cpp b/util/system/rwlock.cpp index bb3dcbf188..6b37031f15 100644 --- a/util/system/rwlock.cpp +++ b/util/system/rwlock.cpp @@ -1,19 +1,19 @@ #include "rwlock.h" -#include "mutex.h" -#include "condvar.h" +#include "mutex.h" +#include "condvar.h" #include <util/generic/yexception.h> -#if defined(_unix_) - #include <errno.h> - #include <pthread.h> +#if defined(_unix_) + #include <errno.h> + #include <pthread.h> #endif -#if defined(_win_) || defined(_darwin_) -//darwin rwlocks not recursive +#if defined(_win_) || defined(_darwin_) +//darwin rwlocks not recursive class TRWMutex::TImpl { -public: - TImpl(); +public: + TImpl(); ~TImpl(); void AcquireRead() noexcept; @@ -26,19 +26,19 @@ public: void Release() noexcept; -private: - TMutex Lock_; - int State_; - TCondVar ReadCond_; - TCondVar WriteCond_; - int BlockedWriters_; +private: + TMutex Lock_; + int State_; + TCondVar ReadCond_; + TCondVar WriteCond_; + int BlockedWriters_; }; TRWMutex::TImpl::TImpl() - : State_(0) - , BlockedWriters_(0) -{ -} + : State_(0) + , BlockedWriters_(0) +{ +} TRWMutex::TImpl::~TImpl() { Y_VERIFY(State_ == 0, "failure, State_ != 0"); @@ -46,98 +46,98 @@ TRWMutex::TImpl::~TImpl() { } void TRWMutex::TImpl::AcquireRead() noexcept { - with_lock (Lock_) { - while (BlockedWriters_ || State_ < 0) { - ReadCond_.Wait(Lock_); - } - + with_lock (Lock_) { + while (BlockedWriters_ || State_ < 0) { + ReadCond_.Wait(Lock_); + } + ++State_; } - - ReadCond_.Signal(); -} + + ReadCond_.Signal(); +} bool TRWMutex::TImpl::TryAcquireRead() noexcept { - with_lock (Lock_) { - if (BlockedWriters_ || State_ < 0) { - return false; - } - + with_lock (Lock_) { + if (BlockedWriters_ || State_ < 0) { + return false; + } + ++State_; - } - - return true; -} - + } + + return true; +} + void TRWMutex::TImpl::ReleaseRead() noexcept { - Lock_.Acquire(); - - if (--State_ > 0) { - Lock_.Release(); - } else if (BlockedWriters_) { - Lock_.Release(); - WriteCond_.Signal(); - } else { - Lock_.Release(); - } -} - + Lock_.Acquire(); + + if (--State_ > 0) { + Lock_.Release(); + } else if (BlockedWriters_) { + Lock_.Release(); + WriteCond_.Signal(); + } else { + Lock_.Release(); + } +} + void TRWMutex::TImpl::AcquireWrite() noexcept { - with_lock (Lock_) { - while (State_ != 0) { - ++BlockedWriters_; - WriteCond_.Wait(Lock_); - --BlockedWriters_; - } - - State_ = -1; - } -} - + with_lock (Lock_) { + while (State_ != 0) { + ++BlockedWriters_; + WriteCond_.Wait(Lock_); + --BlockedWriters_; + } + + State_ = -1; + } +} + bool TRWMutex::TImpl::TryAcquireWrite() noexcept { - with_lock (Lock_) { - if (State_ != 0) { - return false; - } - - State_ = -1; - } - - return true; -} - + with_lock (Lock_) { + if (State_ != 0) { + return false; + } + + State_ = -1; + } + + return true; +} + void TRWMutex::TImpl::ReleaseWrite() noexcept { - Lock_.Acquire(); - State_ = 0; - - if (BlockedWriters_) { - Lock_.Release(); - WriteCond_.Signal(); - } else { - Lock_.Release(); - ReadCond_.Signal(); - } -} - + Lock_.Acquire(); + State_ = 0; + + if (BlockedWriters_) { + Lock_.Release(); + WriteCond_.Signal(); + } else { + Lock_.Release(); + ReadCond_.Signal(); + } +} + void TRWMutex::TImpl::Release() noexcept { - Lock_.Acquire(); - - if (State_ > 0) { - if (--State_ > 0) { - Lock_.Release(); - } else if (BlockedWriters_) { - Lock_.Release(); - WriteCond_.Signal(); + Lock_.Acquire(); + + if (State_ > 0) { + if (--State_ > 0) { + Lock_.Release(); + } else if (BlockedWriters_) { + Lock_.Release(); + WriteCond_.Signal(); } - } else { - State_ = 0; - - if (BlockedWriters_) { - Lock_.Release(); - WriteCond_.Signal(); + } else { + State_ = 0; + + if (BlockedWriters_) { + Lock_.Release(); + WriteCond_.Signal(); } else { - Lock_.Release(); - ReadCond_.Signal(); + Lock_.Release(); + ReadCond_.Signal(); } } } @@ -145,8 +145,8 @@ void TRWMutex::TImpl::Release() noexcept { #else /* POSIX threads */ class TRWMutex::TImpl { -public: - TImpl(); +public: + TImpl(); ~TImpl(); void AcquireRead() noexcept; @@ -159,14 +159,14 @@ public: void Release() noexcept; -private: - pthread_rwlock_t Lock_; +private: + pthread_rwlock_t Lock_; }; TRWMutex::TImpl::TImpl() { int result = pthread_rwlock_init(&Lock_, nullptr); if (result != 0) { - ythrow yexception() << "rwlock init failed (" << LastSystemErrorText(result) << ")"; + ythrow yexception() << "rwlock init failed (" << LastSystemErrorText(result) << ")"; } } @@ -189,7 +189,7 @@ bool TRWMutex::TImpl::TryAcquireRead() noexcept { void TRWMutex::TImpl::ReleaseRead() noexcept { const int result = pthread_rwlock_unlock(&Lock_); Y_VERIFY(result == 0, "rwlock (read) unlock failed (%s)", LastSystemErrorText(result)); -} +} void TRWMutex::TImpl::AcquireWrite() noexcept { const int result = pthread_rwlock_wrlock(&Lock_); @@ -224,11 +224,11 @@ TRWMutex::~TRWMutex() = default; void TRWMutex::AcquireRead() noexcept { Impl_->AcquireRead(); } - + bool TRWMutex::TryAcquireRead() noexcept { return Impl_->TryAcquireRead(); } - + void TRWMutex::ReleaseRead() noexcept { Impl_->ReleaseRead(); } @@ -236,11 +236,11 @@ void TRWMutex::ReleaseRead() noexcept { void TRWMutex::AcquireWrite() noexcept { Impl_->AcquireWrite(); } - + bool TRWMutex::TryAcquireWrite() noexcept { return Impl_->TryAcquireWrite(); } - + void TRWMutex::ReleaseWrite() noexcept { Impl_->ReleaseWrite(); } diff --git a/util/system/rwlock.h b/util/system/rwlock.h index 0bb9b3fe1c..d603f5debd 100644 --- a/util/system/rwlock.h +++ b/util/system/rwlock.h @@ -1,13 +1,13 @@ #pragma once -#include "guard.h" -#include "defaults.h" +#include "guard.h" +#include "defaults.h" #include <util/generic/ptr.h> -class TRWMutex { -public: - TRWMutex(); +class TRWMutex { +public: + TRWMutex(); ~TRWMutex(); void AcquireRead() noexcept; @@ -17,44 +17,44 @@ public: void AcquireWrite() noexcept; bool TryAcquireWrite() noexcept; void ReleaseWrite() noexcept; - + void Release() noexcept; -private: - class TImpl; - THolder<TImpl> Impl_; -}; - -template <class T> -struct TReadGuardOps { +private: + class TImpl; + THolder<TImpl> Impl_; +}; + +template <class T> +struct TReadGuardOps { static inline void Acquire(T* t) noexcept { - t->AcquireRead(); - } - + t->AcquireRead(); + } + static inline void Release(T* t) noexcept { - t->ReleaseRead(); - } + t->ReleaseRead(); + } }; -template <class T> -struct TTryReadGuardOps: public TReadGuardOps<T> { +template <class T> +struct TTryReadGuardOps: public TReadGuardOps<T> { static inline bool TryAcquire(T* t) noexcept { return t->TryAcquireRead(); } }; template <class T> -struct TWriteGuardOps { +struct TWriteGuardOps { static inline void Acquire(T* t) noexcept { - t->AcquireWrite(); - } - + t->AcquireWrite(); + } + static inline void Release(T* t) noexcept { - t->ReleaseWrite(); - } + t->ReleaseWrite(); + } }; -template <class T> +template <class T> struct TTryWriteGuardOps: public TWriteGuardOps<T> { static inline bool TryAcquire(T* t) noexcept { return t->TryAcquireWrite(); @@ -62,17 +62,17 @@ struct TTryWriteGuardOps: public TWriteGuardOps<T> { }; template <class T> -using TReadGuardBase = TGuard<T, TReadGuardOps<T>>; +using TReadGuardBase = TGuard<T, TReadGuardOps<T>>; template <class T> using TTryReadGuardBase = TTryGuard<T, TTryReadGuardOps<T>>; - -template <class T> -using TWriteGuardBase = TGuard<T, TWriteGuardOps<T>>; + +template <class T> +using TWriteGuardBase = TGuard<T, TWriteGuardOps<T>>; template <class T> using TTryWriteGuardBase = TTryGuard<T, TTryWriteGuardOps<T>>; - -using TReadGuard = TReadGuardBase<TRWMutex>; + +using TReadGuard = TReadGuardBase<TRWMutex>; using TTryReadGuard = TTryReadGuardBase<TRWMutex>; -using TWriteGuard = TWriteGuardBase<TRWMutex>; +using TWriteGuard = TWriteGuardBase<TRWMutex>; using TTryWriteGuard = TTryWriteGuardBase<TRWMutex>; diff --git a/util/system/rwlock_ut.cpp b/util/system/rwlock_ut.cpp index 2b384c05b3..8763f46cbd 100644 --- a/util/system/rwlock_ut.cpp +++ b/util/system/rwlock_ut.cpp @@ -1,15 +1,15 @@ -#include "rwlock.h" -#include "atomic.h" - +#include "rwlock.h" +#include "atomic.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/thread/pool.h> #include <util/random/random.h> -class TRWMutexTest: public TTestBase { +class TRWMutexTest: public TTestBase { UNIT_TEST_SUITE(TRWMutexTest); - UNIT_TEST(TestReaders) - UNIT_TEST(TestReadersWriters) + UNIT_TEST(TestReaders) + UNIT_TEST(TestReadersWriters) UNIT_TEST_SUITE_END(); struct TSharedData { @@ -20,104 +20,104 @@ class TRWMutexTest: public TTestBase { { } - TAtomic writersIn; - TAtomic readersIn; + TAtomic writersIn; + TAtomic readersIn; bool failed; TRWMutex mutex; }; - - class TThreadTask: public IObjectInQueue { - public: + + class TThreadTask: public IObjectInQueue { + public: using PFunc = void (TThreadTask::*)(void); - TThreadTask(PFunc func, TSharedData& data, size_t id, size_t total) - : Func_(func) - , Data_(data) - , Id_(id) - , Total_(total) - { - } + TThreadTask(PFunc func, TSharedData& data, size_t id, size_t total) + : Func_(func) + , Data_(data) + , Id_(id) + , Total_(total) + { + } void Process(void*) override { - THolder<TThreadTask> This(this); - - (this->*Func_)(); - } - -#define FAIL_ASSERT(cond) \ - if (!(cond)) { \ - Data_.failed = true; \ + THolder<TThreadTask> This(this); + + (this->*Func_)(); + } + +#define FAIL_ASSERT(cond) \ + if (!(cond)) { \ + Data_.failed = true; \ } - void RunReaders() { - Data_.mutex.AcquireRead(); - - AtomicIncrement(Data_.readersIn); - usleep(100); - FAIL_ASSERT(Data_.readersIn == long(Total_)); - usleep(100); - AtomicDecrement(Data_.readersIn); - - Data_.mutex.ReleaseRead(); - } - - void RunReadersWriters() { - if (Id_ % 2 == 0) { - for (size_t i = 0; i < 10; ++i) { - Data_.mutex.AcquireRead(); - - AtomicIncrement(Data_.readersIn); - FAIL_ASSERT(Data_.writersIn == 0); - usleep(RandomNumber<ui32>() % 5); - AtomicDecrement(Data_.readersIn); - - Data_.mutex.ReleaseRead(); - } - } else { - for (size_t i = 0; i < 10; ++i) { - Data_.mutex.AcquireWrite(); - - AtomicIncrement(Data_.writersIn); - FAIL_ASSERT(Data_.readersIn == 0 && Data_.writersIn == 1); - usleep(RandomNumber<ui32>() % 5); - AtomicDecrement(Data_.writersIn); - - Data_.mutex.ReleaseWrite(); + void RunReaders() { + Data_.mutex.AcquireRead(); + + AtomicIncrement(Data_.readersIn); + usleep(100); + FAIL_ASSERT(Data_.readersIn == long(Total_)); + usleep(100); + AtomicDecrement(Data_.readersIn); + + Data_.mutex.ReleaseRead(); + } + + void RunReadersWriters() { + if (Id_ % 2 == 0) { + for (size_t i = 0; i < 10; ++i) { + Data_.mutex.AcquireRead(); + + AtomicIncrement(Data_.readersIn); + FAIL_ASSERT(Data_.writersIn == 0); + usleep(RandomNumber<ui32>() % 5); + AtomicDecrement(Data_.readersIn); + + Data_.mutex.ReleaseRead(); + } + } else { + for (size_t i = 0; i < 10; ++i) { + Data_.mutex.AcquireWrite(); + + AtomicIncrement(Data_.writersIn); + FAIL_ASSERT(Data_.readersIn == 0 && Data_.writersIn == 1); + usleep(RandomNumber<ui32>() % 5); + AtomicDecrement(Data_.writersIn); + + Data_.mutex.ReleaseWrite(); } } - } + } #undef FAIL_ASSERT - private: - PFunc Func_; - TSharedData& Data_; - size_t Id_; - size_t Total_; + private: + PFunc Func_; + TSharedData& Data_; + size_t Id_; + size_t Total_; }; - -private: -#define RUN_CYCLE(what, count) \ - Q_.Start(count); \ - for (size_t i = 0; i < count; ++i) { \ - UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i, count))); \ - } \ - Q_.Stop(); \ - bool b = Data_.failed; \ - Data_.failed = false; \ - UNIT_ASSERT(!b); - - void TestReaders() { - RUN_CYCLE(RunReaders, 1); - } - - void TestReadersWriters() { - RUN_CYCLE(RunReadersWriters, 1); - } + +private: +#define RUN_CYCLE(what, count) \ + Q_.Start(count); \ + for (size_t i = 0; i < count; ++i) { \ + UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i, count))); \ + } \ + Q_.Stop(); \ + bool b = Data_.failed; \ + Data_.failed = false; \ + UNIT_ASSERT(!b); + + void TestReaders() { + RUN_CYCLE(RunReaders, 1); + } + + void TestReadersWriters() { + RUN_CYCLE(RunReadersWriters, 1); + } #undef RUN_CYCLE -private: - TSharedData Data_; +private: + TSharedData Data_; TThreadPool Q_; }; diff --git a/util/system/sanitizers.cpp b/util/system/sanitizers.cpp index bb799a9e2e..f972e649bf 100644 --- a/util/system/sanitizers.cpp +++ b/util/system/sanitizers.cpp @@ -1,76 +1,76 @@ #include "sanitizers.h" -#include "thread.h" - -#if defined(_asan_enabled_) -extern "C" { - void __sanitizer_start_switch_fiber(void** fake_stack_save, const void* bottom, size_t size); - void __sanitizer_finish_switch_fiber(void* fake_stack_save, const void** old_bottom, size_t* old_size); -} -#endif - +#include "thread.h" + +#if defined(_asan_enabled_) +extern "C" { + void __sanitizer_start_switch_fiber(void** fake_stack_save, const void* bottom, size_t size); + void __sanitizer_finish_switch_fiber(void* fake_stack_save, const void** old_bottom, size_t* old_size); +} +#endif + #if defined(_tsan_enabled_) - #if defined(__clang_major__) && (__clang_major__ >= 9) + #if defined(__clang_major__) && (__clang_major__ >= 9) extern "C" { - void* __tsan_get_current_fiber(void); - void* __tsan_create_fiber(unsigned flags); - void __tsan_destroy_fiber(void* fiber); - void __tsan_switch_to_fiber(void* fiber, unsigned flags); - void __tsan_set_fiber_name(void* fiber, const char* name); + void* __tsan_get_current_fiber(void); + void* __tsan_create_fiber(unsigned flags); + void __tsan_destroy_fiber(void* fiber); + void __tsan_switch_to_fiber(void* fiber, unsigned flags); + void __tsan_set_fiber_name(void* fiber, const char* name); } - #else + #else namespace { - void* __tsan_get_current_fiber(void) { - return nullptr; - } - void* __tsan_create_fiber(unsigned) { - return nullptr; - } - void __tsan_destroy_fiber(void*) { - } - void __tsan_switch_to_fiber(void*, unsigned) { - } - void __tsan_set_fiber_name(void*, const char*) { - } + void* __tsan_get_current_fiber(void) { + return nullptr; + } + void* __tsan_create_fiber(unsigned) { + return nullptr; + } + void __tsan_destroy_fiber(void*) { + } + void __tsan_switch_to_fiber(void*, unsigned) { + } + void __tsan_set_fiber_name(void*, const char*) { + } } - #endif + #endif #endif -using namespace NSan; - -TFiberContext::TFiberContext() noexcept - : Token_(nullptr) +using namespace NSan; + +TFiberContext::TFiberContext() noexcept + : Token_(nullptr) , IsMainFiber_(true) #if defined(_tsan_enabled_) , CurrentTSanFiberContext_(__tsan_get_current_fiber()) #endif -{ - TCurrentThreadLimits sl; - - Stack_ = sl.StackBegin; - Len_ = sl.StackLength; +{ + TCurrentThreadLimits sl; + + Stack_ = sl.StackBegin; + Len_ = sl.StackLength; #if defined(_tsan_enabled_) static constexpr char MainFiberName[] = "main_fiber"; __tsan_set_fiber_name(CurrentTSanFiberContext_, MainFiberName); #endif -} - +} + TFiberContext::TFiberContext(const void* stack, size_t len, const char* contName) noexcept - : Token_(nullptr) - , Stack_(stack) - , Len_(len) + : Token_(nullptr) + , Stack_(stack) + , Len_(len) , IsMainFiber_(false) #if defined(_tsan_enabled_) - , CurrentTSanFiberContext_(__tsan_create_fiber(/*flags =*/0)) + , CurrentTSanFiberContext_(__tsan_create_fiber(/*flags =*/0)) #endif -{ +{ (void)contName; #if defined(_tsan_enabled_) __tsan_set_fiber_name(CurrentTSanFiberContext_, contName); #endif -} - -TFiberContext::~TFiberContext() noexcept { +} + +TFiberContext::~TFiberContext() noexcept { if (!IsMainFiber_) { #if defined(_asan_enabled_) if (Token_) { @@ -88,35 +88,35 @@ TFiberContext::~TFiberContext() noexcept { __tsan_destroy_fiber(CurrentTSanFiberContext_); #endif } -} - -void TFiberContext::BeforeFinish() noexcept { -#if defined(_asan_enabled_) - __sanitizer_start_switch_fiber(nullptr, nullptr, 0); -#else - (void)Token_; - (void)Stack_; - (void)Len_; -#endif -} - +} + +void TFiberContext::BeforeFinish() noexcept { +#if defined(_asan_enabled_) + __sanitizer_start_switch_fiber(nullptr, nullptr, 0); +#else + (void)Token_; + (void)Stack_; + (void)Len_; +#endif +} + void TFiberContext::BeforeSwitch(TFiberContext* old) noexcept { -#if defined(_asan_enabled_) - __sanitizer_start_switch_fiber(old ? &old->Token_ : nullptr, (char*)Stack_, Len_); +#if defined(_asan_enabled_) + __sanitizer_start_switch_fiber(old ? &old->Token_ : nullptr, (char*)Stack_, Len_); #else (void)old; -#endif +#endif #if defined(_tsan_enabled_) - __tsan_switch_to_fiber(CurrentTSanFiberContext_, /*flags =*/0); + __tsan_switch_to_fiber(CurrentTSanFiberContext_, /*flags =*/0); #endif -} - -void TFiberContext::AfterSwitch() noexcept { -#if defined(_asan_enabled_) +} + +void TFiberContext::AfterSwitch() noexcept { +#if defined(_asan_enabled_) __sanitizer_finish_switch_fiber(Token_, nullptr, nullptr); -#endif -} +#endif +} void TFiberContext::AfterStart() noexcept { #if defined(_asan_enabled_) @@ -128,15 +128,15 @@ void TFiberContext::AfterStart() noexcept { extern "C" { // This function should not be directly exposed in headers // due to signature variations among contrib headers. - void AnnotateBenignRaceSized(const char* file, int line, - const volatile void* address, + void AnnotateBenignRaceSized(const char* file, int line, + const volatile void* address, size_t size, - const char* description); + const char* description); } -void NSan::AnnotateBenignRaceSized(const char* file, int line, - const volatile void* address, +void NSan::AnnotateBenignRaceSized(const char* file, int line, + const volatile void* address, size_t size, - const char* description) noexcept { + const char* description) noexcept { ::AnnotateBenignRaceSized(file, line, address, size, description); } #endif diff --git a/util/system/sanitizers.h b/util/system/sanitizers.h index 965e5c751e..a8c92a17ec 100644 --- a/util/system/sanitizers.h +++ b/util/system/sanitizers.h @@ -5,42 +5,42 @@ extern "C" { // sanitizers API #if defined(_asan_enabled_) - void __lsan_ignore_object(const void* p); + void __lsan_ignore_object(const void* p); #endif #if defined(_msan_enabled_) - void __msan_unpoison(const volatile void* a, size_t size); - void __msan_poison(const volatile void* a, size_t size); - void __msan_check_mem_is_initialized(const volatile void* x, size_t size); + void __msan_unpoison(const volatile void* a, size_t size); + void __msan_poison(const volatile void* a, size_t size); + void __msan_check_mem_is_initialized(const volatile void* x, size_t size); #endif }; // sanitizers API namespace NSan { - class TFiberContext { - public: - TFiberContext() noexcept; + class TFiberContext { + public: + TFiberContext() noexcept; TFiberContext(const void* stack, size_t len, const char* contName) noexcept; - ~TFiberContext() noexcept; - - void BeforeFinish() noexcept; + ~TFiberContext() noexcept; + + void BeforeFinish() noexcept; void BeforeSwitch(TFiberContext* old) noexcept; - void AfterSwitch() noexcept; - + void AfterSwitch() noexcept; + static void AfterStart() noexcept; - private: - void* Token_; - const void* Stack_; - size_t Len_; + private: + void* Token_; + const void* Stack_; + size_t Len_; const bool IsMainFiber_; #if defined(_tsan_enabled_) void* const CurrentTSanFiberContext_; #endif - }; - + }; + // Returns plain if no sanitizer enabled or sanitized otherwise // Ment to be used in test code for constants (timeouts, etc) template <typename T> @@ -122,15 +122,15 @@ namespace NSan { #if defined(_tsan_enabled_) // defined in .cpp to avoid exposing problematic C-linkage version of AnnotateBenignRaceSized(...) - void AnnotateBenignRaceSized(const char* file, int line, - const volatile void* address, + void AnnotateBenignRaceSized(const char* file, int line, + const volatile void* address, size_t size, - const char* description) noexcept; + const char* description) noexcept; #else - inline static void AnnotateBenignRaceSized(const char* file, int line, - const volatile void* address, + inline static void AnnotateBenignRaceSized(const char* file, int line, + const volatile void* address, size_t size, - const char* description) noexcept { + const char* description) noexcept { Y_UNUSED(file); Y_UNUSED(line); Y_UNUSED(address); @@ -138,4 +138,4 @@ namespace NSan { Y_UNUSED(description); } #endif -} +} diff --git a/util/system/sem.cpp b/util/system/sem.cpp index 4a93b903b5..88e74fd6bc 100644 --- a/util/system/sem.cpp +++ b/util/system/sem.cpp @@ -1,137 +1,137 @@ -#include "sem.h" - +#include "sem.h" + #ifdef _win_ - #include <malloc.h> + #include <malloc.h> #elif defined(_sun) - #include <alloca.h> + #include <alloca.h> #endif - + #include <cerrno> #include <cstring> -#ifdef _win_ - #include "winint.h" -#else - #include <signal.h> - #include <unistd.h> - #include <semaphore.h> - - #if defined(_bionic_) || defined(_darwin_) && defined(_arm_) - #include <fcntl.h> - #else - #define USE_SYSV_SEMAPHORES //unixoids declared the standard but not implemented it... - #endif -#endif - +#ifdef _win_ + #include "winint.h" +#else + #include <signal.h> + #include <unistd.h> + #include <semaphore.h> + + #if defined(_bionic_) || defined(_darwin_) && defined(_arm_) + #include <fcntl.h> + #else + #define USE_SYSV_SEMAPHORES //unixoids declared the standard but not implemented it... + #endif +#endif + #ifdef USE_SYSV_SEMAPHORES - #include <errno.h> - #include <sys/types.h> - #include <sys/ipc.h> - #include <sys/sem.h> - - #if defined(_linux_) || defined(_sun_) || defined(_cygwin_) -union semun { - int val; - struct semid_ds* buf; - unsigned short* array; -} arg; - #else -union semun arg; - #endif + #include <errno.h> + #include <sys/types.h> + #include <sys/ipc.h> + #include <sys/sem.h> + + #if defined(_linux_) || defined(_sun_) || defined(_cygwin_) +union semun { + int val; + struct semid_ds* buf; + unsigned short* array; +} arg; + #else +union semun arg; + #endif #endif - -#include <util/digest/city.h> -#include <util/string/cast.h> -#include <util/random/random.h> -#include <util/random/fast.h> - -namespace { - class TSemaphoreImpl { - private: + +#include <util/digest/city.h> +#include <util/string/cast.h> +#include <util/random/random.h> +#include <util/random/fast.h> + +namespace { + class TSemaphoreImpl { + private: #ifdef _win_ using SEMHANDLE = HANDLE; #else - #ifdef USE_SYSV_SEMAPHORES + #ifdef USE_SYSV_SEMAPHORES using SEMHANDLE = int; - #else + #else using SEMHANDLE = sem_t*; - #endif -#endif - - SEMHANDLE Handle; - - public: - inline TSemaphoreImpl(const char* name, ui32 max_free_count) - : Handle(0) - { -#ifdef _win_ - char* key = (char*)name; - if (name) { - size_t len = strlen(name); - key = (char*)alloca(len + 1); - strcpy(key, name); - if (len > MAX_PATH) - *(key + MAX_PATH) = 0; - char* p = key; - while (*p) { - if (*p == '\\') - *p = '/'; + #endif +#endif + + SEMHANDLE Handle; + + public: + inline TSemaphoreImpl(const char* name, ui32 max_free_count) + : Handle(0) + { +#ifdef _win_ + char* key = (char*)name; + if (name) { + size_t len = strlen(name); + key = (char*)alloca(len + 1); + strcpy(key, name); + if (len > MAX_PATH) + *(key + MAX_PATH) = 0; + char* p = key; + while (*p) { + if (*p == '\\') + *p = '/'; ++p; - } - } - // non-blocking on init - Handle = ::CreateSemaphore(0, max_free_count, max_free_count, key); -#else - #ifdef USE_SYSV_SEMAPHORES - key_t key = TPCGMixer::Mix(CityHash64(name, strlen(name))); //32 bit hash - Handle = semget(key, 0, 0); // try to open exist semaphore - if (Handle == -1) { // create new semaphore - Handle = semget(key, 1, 0666 | IPC_CREAT); - if (Handle != -1) { - union semun arg; - arg.val = max_free_count; - semctl(Handle, 0, SETVAL, arg); - } else { - ythrow TSystemError() << "can not init sempahore"; - } - } - #else - Handle = sem_open(name, O_CREAT, 0666, max_free_count); - if (Handle == SEM_FAILED) { - ythrow TSystemError() << "can not init sempahore"; - } - #endif -#endif + } + } + // non-blocking on init + Handle = ::CreateSemaphore(0, max_free_count, max_free_count, key); +#else + #ifdef USE_SYSV_SEMAPHORES + key_t key = TPCGMixer::Mix(CityHash64(name, strlen(name))); //32 bit hash + Handle = semget(key, 0, 0); // try to open exist semaphore + if (Handle == -1) { // create new semaphore + Handle = semget(key, 1, 0666 | IPC_CREAT); + if (Handle != -1) { + union semun arg; + arg.val = max_free_count; + semctl(Handle, 0, SETVAL, arg); + } else { + ythrow TSystemError() << "can not init sempahore"; + } + } + #else + Handle = sem_open(name, O_CREAT, 0666, max_free_count); + if (Handle == SEM_FAILED) { + ythrow TSystemError() << "can not init sempahore"; + } + #endif +#endif } inline ~TSemaphoreImpl() { #ifdef _win_ - ::CloseHandle(Handle); + ::CloseHandle(Handle); #else - #ifdef USE_SYSV_SEMAPHORES - // we DO NOT want 'semctl(Handle, 0, IPC_RMID)' for multiprocess tasks; - //struct sembuf ops[] = {{0, 0, IPC_NOWAIT}}; - //if (semop(Handle, ops, 1) != 0) // close only if semaphore's value is zero - // semctl(Handle, 0, IPC_RMID); - #else - sem_close(Handle); // we DO NOT want sem_unlink(...) - #endif + #ifdef USE_SYSV_SEMAPHORES + // we DO NOT want 'semctl(Handle, 0, IPC_RMID)' for multiprocess tasks; + //struct sembuf ops[] = {{0, 0, IPC_NOWAIT}}; + //if (semop(Handle, ops, 1) != 0) // close only if semaphore's value is zero + // semctl(Handle, 0, IPC_RMID); + #else + sem_close(Handle); // we DO NOT want sem_unlink(...) + #endif #endif - } + } inline void Release() noexcept { #ifdef _win_ - ::ReleaseSemaphore(Handle, 1, 0); + ::ReleaseSemaphore(Handle, 1, 0); #else - #ifdef USE_SYSV_SEMAPHORES - struct sembuf ops[] = {{0, 1, SEM_UNDO}}; - int ret = semop(Handle, ops, 1); - #else - int ret = sem_post(Handle); - #endif + #ifdef USE_SYSV_SEMAPHORES + struct sembuf ops[] = {{0, 1, SEM_UNDO}}; + int ret = semop(Handle, ops, 1); + #else + int ret = sem_post(Handle); + #endif Y_VERIFY(ret == 0, "can not release semaphore"); #endif - } + } //The UNIX semaphore object does not support a timed "wait", and //hence to maintain consistancy, for win32 case we use INFINITE or 0 timeout. @@ -139,140 +139,140 @@ namespace { #ifdef _win_ Y_VERIFY(::WaitForSingleObject(Handle, INFINITE) == WAIT_OBJECT_0, "can not acquire semaphore"); #else - #ifdef USE_SYSV_SEMAPHORES - struct sembuf ops[] = {{0, -1, SEM_UNDO}}; - int ret = semop(Handle, ops, 1); - #else - int ret = sem_wait(Handle); - #endif + #ifdef USE_SYSV_SEMAPHORES + struct sembuf ops[] = {{0, -1, SEM_UNDO}}; + int ret = semop(Handle, ops, 1); + #else + int ret = sem_wait(Handle); + #endif Y_VERIFY(ret == 0, "can not acquire semaphore"); #endif - } + } inline bool TryAcquire() noexcept { #ifdef _win_ - // zero-second time-out interval - // WAIT_OBJECT_0: current free count > 0 - // WAIT_TIMEOUT: current free count == 0 + // zero-second time-out interval + // WAIT_OBJECT_0: current free count > 0 + // WAIT_TIMEOUT: current free count == 0 return ::WaitForSingleObject(Handle, 0) == WAIT_OBJECT_0; #else - #ifdef USE_SYSV_SEMAPHORES - struct sembuf ops[] = {{0, -1, SEM_UNDO | IPC_NOWAIT}}; - int ret = semop(Handle, ops, 1); - #else - int ret = sem_trywait(Handle); - #endif - return ret == 0; + #ifdef USE_SYSV_SEMAPHORES + struct sembuf ops[] = {{0, -1, SEM_UNDO | IPC_NOWAIT}}; + int ret = semop(Handle, ops, 1); + #else + int ret = sem_trywait(Handle); + #endif + return ret == 0; #endif - } - }; + } + }; -#if defined(_unix_) - /* +#if defined(_unix_) + /* Disable errors/warnings about deprecated sem_* in Darwin */ - #ifdef _darwin_ - Y_PRAGMA_DIAGNOSTIC_PUSH - Y_PRAGMA_NO_DEPRECATED - #endif - struct TPosixSemaphore { - inline TPosixSemaphore(ui32 maxFreeCount) { - if (sem_init(&S_, 0, maxFreeCount)) { - ythrow TSystemError() << "can not init semaphore"; - } - } - + #ifdef _darwin_ + Y_PRAGMA_DIAGNOSTIC_PUSH + Y_PRAGMA_NO_DEPRECATED + #endif + struct TPosixSemaphore { + inline TPosixSemaphore(ui32 maxFreeCount) { + if (sem_init(&S_, 0, maxFreeCount)) { + ythrow TSystemError() << "can not init semaphore"; + } + } + inline ~TPosixSemaphore() { Y_VERIFY(sem_destroy(&S_) == 0, "semaphore destroy failed"); - } - + } + inline void Acquire() noexcept { Y_VERIFY(sem_wait(&S_) == 0, "semaphore acquire failed"); - } - + } + inline void Release() noexcept { Y_VERIFY(sem_post(&S_) == 0, "semaphore release failed"); - } - + } + inline bool TryAcquire() noexcept { - if (sem_trywait(&S_)) { + if (sem_trywait(&S_)) { Y_VERIFY(errno == EAGAIN, "semaphore try wait failed"); - - return false; - } - - return true; - } - - sem_t S_; - }; - #ifdef _darwin_ - Y_PRAGMA_DIAGNOSTIC_POP - #endif + + return false; + } + + return true; + } + + sem_t S_; + }; + #ifdef _darwin_ + Y_PRAGMA_DIAGNOSTIC_POP + #endif #endif +} + +class TSemaphore::TImpl: public TSemaphoreImpl { +public: + inline TImpl(const char* name, ui32 maxFreeCount) + : TSemaphoreImpl(name, maxFreeCount) + { + } +}; + +TSemaphore::TSemaphore(const char* name, ui32 maxFreeCount) + : Impl_(new TImpl(name, maxFreeCount)) +{ } - -class TSemaphore::TImpl: public TSemaphoreImpl { -public: - inline TImpl(const char* name, ui32 maxFreeCount) - : TSemaphoreImpl(name, maxFreeCount) - { - } -}; - -TSemaphore::TSemaphore(const char* name, ui32 maxFreeCount) - : Impl_(new TImpl(name, maxFreeCount)) -{ -} - + TSemaphore::~TSemaphore() = default; - + void TSemaphore::Release() noexcept { - Impl_->Release(); -} - + Impl_->Release(); +} + void TSemaphore::Acquire() noexcept { - Impl_->Acquire(); -} - + Impl_->Acquire(); +} + bool TSemaphore::TryAcquire() noexcept { - return Impl_->TryAcquire(); -} - + return Impl_->TryAcquire(); +} + #if defined(_unix_) && !defined(_darwin_) -class TFastSemaphore::TImpl: public TPosixSemaphore { -public: - inline TImpl(ui32 n) - : TPosixSemaphore(n) - { - } -}; -#else +class TFastSemaphore::TImpl: public TPosixSemaphore { +public: + inline TImpl(ui32 n) + : TPosixSemaphore(n) + { + } +}; +#else class TFastSemaphore::TImpl: public TString, public TSemaphoreImpl { -public: - inline TImpl(ui32 n) +public: + inline TImpl(ui32 n) : TString(ToString(RandomNumber<ui64>())) , TSemaphoreImpl(c_str(), n) - { - } -}; -#endif - -TFastSemaphore::TFastSemaphore(ui32 maxFreeCount) - : Impl_(new TImpl(maxFreeCount)) -{ -} - + { + } +}; +#endif + +TFastSemaphore::TFastSemaphore(ui32 maxFreeCount) + : Impl_(new TImpl(maxFreeCount)) +{ +} + TFastSemaphore::~TFastSemaphore() = default; - + void TFastSemaphore::Release() noexcept { - Impl_->Release(); -} - + Impl_->Release(); +} + void TFastSemaphore::Acquire() noexcept { - Impl_->Acquire(); -} - + Impl_->Acquire(); +} + bool TFastSemaphore::TryAcquire() noexcept { - return Impl_->TryAcquire(); -} + return Impl_->TryAcquire(); +} diff --git a/util/system/sem.h b/util/system/sem.h index 0c964ad6b6..f18e1dff86 100644 --- a/util/system/sem.h +++ b/util/system/sem.h @@ -2,40 +2,40 @@ #include "defaults.h" -#include <util/generic/ptr.h> - -//named sempahore -class TSemaphore { -public: - TSemaphore(const char* name, ui32 maxFreeCount); +#include <util/generic/ptr.h> + +//named sempahore +class TSemaphore { +public: + TSemaphore(const char* name, ui32 maxFreeCount); ~TSemaphore(); - //Increase the semaphore counter. + //Increase the semaphore counter. void Release() noexcept; - //Keep a thread held while the semaphore counter is equal 0. + //Keep a thread held while the semaphore counter is equal 0. void Acquire() noexcept; - //Try to enter the semaphore gate. A non-blocking variant of Acquire. - //Returns 'true' if the semaphore counter decreased + //Try to enter the semaphore gate. A non-blocking variant of Acquire. + //Returns 'true' if the semaphore counter decreased bool TryAcquire() noexcept; -private: - class TImpl; - THolder<TImpl> Impl_; +private: + class TImpl; + THolder<TImpl> Impl_; }; - -//unnamed semaphore, faster, than previous -class TFastSemaphore { -public: - TFastSemaphore(ui32 maxFreeCount); + +//unnamed semaphore, faster, than previous +class TFastSemaphore { +public: + TFastSemaphore(ui32 maxFreeCount); ~TFastSemaphore(); - + void Release() noexcept; void Acquire() noexcept; bool TryAcquire() noexcept; - -private: - class TImpl; - THolder<TImpl> Impl_; -}; + +private: + class TImpl; + THolder<TImpl> Impl_; +}; diff --git a/util/system/shellcommand.cpp b/util/system/shellcommand.cpp index b1989b5c8c..b9dd78a994 100644 --- a/util/system/shellcommand.cpp +++ b/util/system/shellcommand.cpp @@ -1,7 +1,7 @@ #include "shellcommand.h" -#include "user.h" -#include "nice.h" -#include "sigset.h" +#include "user.h" +#include "nice.h" +#include "sigset.h" #include "atomic.h" #include <util/folder/dirut.h> @@ -19,38 +19,38 @@ #include <errno.h> #if defined(_unix_) - #include <unistd.h> - #include <fcntl.h> - #include <grp.h> - #include <sys/wait.h> + #include <unistd.h> + #include <fcntl.h> + #include <grp.h> + #include <sys/wait.h> using TPid = pid_t; using TWaitResult = pid_t; using TExitStatus = int; - #define WAIT_PROCEED 0 + #define WAIT_PROCEED 0 - #if defined(_darwin_) + #if defined(_darwin_) using TGetGroupListGid = int; - #else + #else using TGetGroupListGid = gid_t; - #endif + #endif #elif defined(_win_) - #include <string> + #include <string> - #include "winint.h" + #include "winint.h" using TPid = HANDLE; using TWaitResult = DWORD; using TExitStatus = DWORD; - #define WAIT_PROCEED WAIT_TIMEOUT + #define WAIT_PROCEED WAIT_TIMEOUT - #pragma warning(disable : 4296) // 'wait_result >= WAIT_OBJECT_0' : expression is always tru + #pragma warning(disable : 4296) // 'wait_result >= WAIT_OBJECT_0' : expression is always tru #else - #error("unknown os, shell command is not implemented") + #error("unknown os, shell command is not implemented") #endif -#define DBG(stmt) \ - {} +#define DBG(stmt) \ + {} // #define DBG(stmt) stmt namespace { @@ -89,7 +89,7 @@ namespace { #elif defined(_win_) constexpr static size_t MAX_COMMAND_LINE = 32 * 1024; - std::wstring GetWString(const char* astring) { + std::wstring GetWString(const char* astring) { if (!astring) return std::wstring(); @@ -97,7 +97,7 @@ namespace { return std::wstring(str.begin(), str.end()); } - std::string GetAString(const wchar_t* wstring) { + std::string GetAString(const wchar_t* wstring) { if (!wstring) return std::string(); @@ -110,10 +110,10 @@ namespace { // temporary measure to avoid rewriting all poll calls on win TPipeHandle #if defined(_win_) using REALPIPEHANDLE = HANDLE; - #define INVALID_REALPIPEHANDLE INVALID_HANDLE_VALUE + #define INVALID_REALPIPEHANDLE INVALID_HANDLE_VALUE class TRealPipeHandle - : public TNonCopyable { + : public TNonCopyable { public: inline TRealPipeHandle() noexcept : Fd_(INVALID_REALPIPEHANDLE) @@ -184,17 +184,17 @@ private: #else using TRealPipeHandle = TPipeHandle; using REALPIPEHANDLE = PIPEHANDLE; - #define INVALID_REALPIPEHANDLE INVALID_PIPEHANDLE + #define INVALID_REALPIPEHANDLE INVALID_PIPEHANDLE #endif class TShellCommand::TImpl - : public TAtomicRefCount<TShellCommand::TImpl> { + : public TAtomicRefCount<TShellCommand::TImpl> { private: TPid Pid; TString Command; TList<TString> Arguments; TString WorkDir; - TAtomic ExecutionStatus; // TShellCommand::ECommandStatus + TAtomic ExecutionStatus; // TShellCommand::ECommandStatus TMaybe<int> ExitCode; IInputStream* InputStream; IOutputStream* OutputStream; @@ -202,7 +202,7 @@ private: TString CollectedOutput; TString CollectedError; TString InternalError; - TThread* WatchThread; + TThread* WatchThread; TMutex TerminateMutex; TFileHandle InputHandle; TFileHandle OutputHandle; @@ -229,16 +229,16 @@ private: std::function<void()> FuncAfterFork = {}; struct TProcessInfo { - TImpl* Parent; + TImpl* Parent; TRealPipeHandle InputFd; TRealPipeHandle OutputFd; TRealPipeHandle ErrorFd; - TProcessInfo(TImpl* parent, REALPIPEHANDLE inputFd, REALPIPEHANDLE outputFd, REALPIPEHANDLE errorFd) - : Parent(parent) - , InputFd(inputFd) - , OutputFd(outputFd) - , ErrorFd(errorFd) - { + TProcessInfo(TImpl* parent, REALPIPEHANDLE inputFd, REALPIPEHANDLE outputFd, REALPIPEHANDLE errorFd) + : Parent(parent) + , InputFd(inputFd) + , OutputFd(outputFd) + , ErrorFd(errorFd) + { } }; @@ -281,31 +281,31 @@ private: public: inline TImpl(const TStringBuf cmd, const TList<TString>& args, const TShellCommandOptions& options, const TString& workdir) - : Pid(0) + : Pid(0) , Command(ToString(cmd)) - , Arguments(args) - , WorkDir(workdir) - , ExecutionStatus(SHELL_NONE) - , InputStream(options.InputStream) - , OutputStream(options.OutputStream) - , ErrorStream(options.ErrorStream) + , Arguments(args) + , WorkDir(workdir) + , ExecutionStatus(SHELL_NONE) + , InputStream(options.InputStream) + , OutputStream(options.OutputStream) + , ErrorStream(options.ErrorStream) , WatchThread(nullptr) - , TerminateFlag(false) + , TerminateFlag(false) , ClearSignalMask(options.ClearSignalMask) , CloseAllFdsOnExec(options.CloseAllFdsOnExec) - , AsyncMode(options.AsyncMode) - , PollDelayMs(options.PollDelayMs) - , UseShell(options.UseShell) - , QuoteArguments(options.QuoteArguments) - , DetachSession(options.DetachSession) + , AsyncMode(options.AsyncMode) + , PollDelayMs(options.PollDelayMs) + , UseShell(options.UseShell) + , QuoteArguments(options.QuoteArguments) + , DetachSession(options.DetachSession) , CloseStreams(options.CloseStreams) , ShouldCloseInput(options.ShouldCloseInput) , InputMode(options.InputMode) , OutputMode(options.OutputMode) , ErrorMode(options.ErrorMode) - , User(options.User) - , Environment(options.Environment) - , Nice(options.Nice) + , User(options.User) + , Environment(options.Environment) + , Nice(options.Nice) , FuncAfterFork(options.FuncAfterFork) { if (InputStream) { @@ -316,10 +316,10 @@ public: inline ~TImpl() { if (WatchThread) { - with_lock (TerminateMutex) { + with_lock (TerminateMutex) { TerminateFlag = true; } - + delete WatchThread; } @@ -393,7 +393,7 @@ public: if (!!Pid && (AtomicGet(ExecutionStatus) == SHELL_RUNNING)) { bool ok = #if defined(_unix_) - kill(DetachSession ? -1 * Pid : Pid, SIGTERM) == 0; + kill(DetachSession ? -1 * Pid : Pid, SIGTERM) == 0; if (!ok && (errno == ESRCH) && DetachSession) { // this could fail when called before child proc completes setsid(). ok = kill(Pid, SIGTERM) == 0; @@ -402,24 +402,24 @@ public: #else TerminateProcess(Pid, 1 /* exit code */); #endif - if (!ok) { + if (!ok) { ythrow TSystemError() << "cannot terminate " << Pid; - } + } } } inline void Wait() { - if (WatchThread) { + if (WatchThread) { WatchThread->Join(); - } + } } inline void CloseInput() { AtomicSet(ShouldCloseInput, true); } - inline static bool TerminateIsRequired(void* processInfo) { - TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(processInfo); + inline static bool TerminateIsRequired(void* processInfo) { + TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(processInfo); if (!pi->Parent->TerminateFlag) { return false; } @@ -428,12 +428,12 @@ public: pi->OutputFd.Close(); if (pi->Parent->CloseStreams) { - if (pi->Parent->ErrorStream) { + if (pi->Parent->ErrorStream) { pi->Parent->ErrorStream->Finish(); - } - if (pi->Parent->OutputStream) { + } + if (pi->Parent->OutputStream) { pi->Parent->OutputStream->Finish(); - } + } } delete pi; @@ -441,10 +441,10 @@ public: } // interchange io while process is alive - inline static void Communicate(TProcessInfo* pi); + inline static void Communicate(TProcessInfo* pi); - inline static void* WatchProcess(void* data) { - TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(data); + inline static void* WatchProcess(void* data) { + TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(data); Communicate(pi); return nullptr; } @@ -457,15 +457,15 @@ public: while (true) { bytes = pump->Pipe->Read(buffer.Data(), buffer.Capacity()); - if (bytes > 0) { + if (bytes > 0) { pump->OutputStream->Write(buffer.Data(), bytes); - } else { + } else { break; - } + } } - if (pump->Pipe->IsOpen()) { + if (pump->Pipe->IsOpen()) { pump->Pipe->Close(); - } + } } catch (...) { pump->InternalError = CurrentExceptionMessage(); } @@ -484,9 +484,9 @@ public: if (!bytesToWrite) { bytesToWrite = pump->InputStream->Read(buffer.Data(), buffer.Capacity()); if (bytesToWrite == 0) { - if (AtomicGet(pump->ShouldClosePipe)) { + if (AtomicGet(pump->ShouldClosePipe)) { break; - } + } continue; } bufPos = buffer.Data(); @@ -500,9 +500,9 @@ public: break; } } - if (pump->Pipe->IsOpen()) { + if (pump->Pipe->IsOpen()) { pump->Pipe->Close(); - } + } } catch (...) { pump->InternalError = CurrentExceptionMessage(); } @@ -576,43 +576,43 @@ void TShellCommand::TImpl::StartProcess(TShellCommand::TImpl::TPipes& pipes) { void* lpEnvironment = nullptr; TString env; if (!Environment.empty()) { - for (auto e = Environment.begin(); e != Environment.end(); ++e) { + for (auto e = Environment.begin(); e != Environment.end(); ++e) { env += e->first + '=' + e->second + '\0'; } env += '\0'; lpEnvironment = const_cast<char*>(env.data()); } - // disable messagebox (may be in debug too) - #ifndef NDEBUG - SetErrorMode(GetErrorMode() | SEM_NOGPFAULTERRORBOX); - #endif + // disable messagebox (may be in debug too) + #ifndef NDEBUG + SetErrorMode(GetErrorMode() | SEM_NOGPFAULTERRORBOX); + #endif BOOL res = 0; if (User.Name.empty() || GetUsername() == User.Name) { res = CreateProcessW( nullptr, // image name cmdcopy.Data(), - nullptr, // process security attributes - nullptr, // thread security attributes - TRUE, // inherit handles - needed for IO, CloseAllFdsOnExec not respected - 0, // obscure creation flags - lpEnvironment, // environment - cwd, // current directory - &startup_info, - &process_info); + nullptr, // process security attributes + nullptr, // thread security attributes + TRUE, // inherit handles - needed for IO, CloseAllFdsOnExec not respected + 0, // obscure creation flags + lpEnvironment, // environment + cwd, // current directory + &startup_info, + &process_info); } else { res = CreateProcessWithLogonW( GetWString(User.Name.data()).c_str(), nullptr, // domain (if this parameter is NULL, the user name must be specified in UPN format) GetWString(User.Password.data()).c_str(), - 0, // logon flags - NULL, // image name + 0, // logon flags + NULL, // image name cmdcopy.Data(), - 0, // obscure creation flags - lpEnvironment, // environment - cwd, // current directory - &startup_info, - &process_info); + 0, // obscure creation flags + lpEnvironment, // environment + cwd, // current directory + &startup_info, + &process_info); } if (!res) { @@ -645,9 +645,9 @@ void ShellQuoteArgSp(TString& dst, TStringBuf argument) { } bool ArgNeedsQuotes(TStringBuf arg) noexcept { - if (arg.empty()) { + if (arg.empty()) { return true; - } + } return arg.find_first_of(" \"\'\t&()*<>\\`^|") != TString::npos; } @@ -667,9 +667,9 @@ TString TShellCommand::TImpl::GetQuotedCommand() const { #if defined(_unix_) void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* argv, char* const* envp, const std::function<void()>& afterFork) const { try { - if (DetachSession) { + if (DetachSession) { setsid(); - } + } // reset signal handlers from parent struct sigaction sa; @@ -688,13 +688,13 @@ void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* ythrow TSystemError() << "Cannot " << (ClearSignalMask ? "clear" : "restore") << " signal mask in child"; } - TFileHandle sIn(0); - TFileHandle sOut(1); - TFileHandle sErr(2); + TFileHandle sIn(0); + TFileHandle sOut(1); + TFileHandle sErr(2); if (InputMode != TShellCommandOptions::HANDLE_INHERIT) { pipes.InputPipeFd[1].Close(); - TFileHandle sInNew(pipes.InputPipeFd[0]); - sIn.LinkTo(sInNew); + TFileHandle sInNew(pipes.InputPipeFd[0]); + sIn.LinkTo(sInNew); sIn.Release(); sInNew.Release(); } else { @@ -716,9 +716,9 @@ void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* sErrNew.Release(); } - if (WorkDir.size()) { + if (WorkDir.size()) { NFs::SetCurrentWorkingDirectory(WorkDir); - } + } if (CloseAllFdsOnExec) { for (int fd = NSystemInfo::MaxOpenFiles(); fd > STDERR_FILENO; --fd) { @@ -737,7 +737,7 @@ void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* if (afterFork) { afterFork(); } - + if (envp == nullptr) { execvp(argv[0], argv); } else { @@ -747,8 +747,8 @@ void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* } catch (const std::exception& error) { Cerr << "Process was not created: " << error.what() << Endl; } catch (...) { - Cerr << "Process was not created: " - << "unknown error" << Endl; + Cerr << "Process was not created: " + << "unknown error" << Endl; } _exit(-1); @@ -800,7 +800,7 @@ void TShellCommand::TImpl::Run() { } else { qargv.reserve(Arguments.size() + 2); qargv.push_back(const_cast<char*>(Command.data())); - for (auto& i : Arguments) { + for (auto& i : Arguments) { qargv.push_back(const_cast<char*>(i.data())); } } @@ -810,7 +810,7 @@ void TShellCommand::TImpl::Run() { TVector<TString> envHolder; TVector<char*> envp; if (!Environment.empty()) { - for (auto& env : Environment) { + for (auto& env : Environment) { envHolder.emplace_back(env.first + '=' + env.second); envp.push_back(const_cast<char*>(envHolder.back().data())); } @@ -840,9 +840,9 @@ void TShellCommand::TImpl::Run() { #endif pipes.PrepareParents(); - if (AtomicGet(ExecutionStatus) != SHELL_RUNNING) { + if (AtomicGet(ExecutionStatus) != SHELL_RUNNING) { return; - } + } if (InputMode == TShellCommandOptions::HANDLE_PIPE) { TFileHandle inputHandle(pipes.InputPipeFd[1].Release()); @@ -859,13 +859,13 @@ void TShellCommand::TImpl::Run() { ErrorHandle.Swap(errorHandle); } - TProcessInfo* processInfo = new TProcessInfo(this, - pipes.InputPipeFd[1].Release(), pipes.OutputPipeFd[0].Release(), pipes.ErrorPipeFd[0].Release()); + TProcessInfo* processInfo = new TProcessInfo(this, + pipes.InputPipeFd[1].Release(), pipes.OutputPipeFd[0].Release(), pipes.ErrorPipeFd[0].Release()); if (AsyncMode) { - WatchThread = new TThread(&TImpl::WatchProcess, processInfo); + WatchThread = new TThread(&TImpl::WatchProcess, processInfo); WatchThread->Start(); /// @todo wait for child to start its process session (if options.Detach) - } else { + } else { Communicate(processInfo); } @@ -875,15 +875,15 @@ void TShellCommand::TImpl::Run() { void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { THolder<IOutputStream> outputHolder; IOutputStream* output = pi->Parent->OutputStream; - if (!output) { + if (!output) { outputHolder.Reset(output = new TStringOutput(pi->Parent->CollectedOutput)); - } + } THolder<IOutputStream> errorHolder; IOutputStream* error = pi->Parent->ErrorStream; - if (!error) { + if (!error) { errorHolder.Reset(error = new TStringOutput(pi->Parent->CollectedError)); - } + } IInputStream*& input = pi->Parent->InputStream; @@ -929,23 +929,23 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { while (true) { { - with_lock (pi->Parent->TerminateMutex) { - if (TerminateIsRequired(pi)) { + with_lock (pi->Parent->TerminateMutex) { + if (TerminateIsRequired(pi)) { return; - } + } } - + waitPidResult = #if defined(_unix_) - waitpid(pi->Parent->Pid, &status, WNOHANG); + waitpid(pi->Parent->Pid, &status, WNOHANG); #else WaitForSingleObject(pi->Parent->Pid /* process_info.hProcess */, pi->Parent->PollDelayMs /* ms */); Y_UNUSED(status); #endif // DBG(Cerr << "wait result: " << waitPidResult << Endl); - if (waitPidResult != WAIT_PROCEED) { + if (waitPidResult != WAIT_PROCEED) { break; - } + } } /// @todo factor out (poll + wfmo) #if defined(_unix_) @@ -966,69 +966,69 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { pi->ErrorFd.Close(); } - if (!input && !output && !error) { + if (!input && !output && !error) { continue; - } + } struct pollfd fds[] = { {REALPIPEHANDLE(pi->InputFd), POLLOUT, 0}, {REALPIPEHANDLE(pi->OutputFd), POLLIN, 0}, - {REALPIPEHANDLE(pi->ErrorFd), POLLIN, 0}}; + {REALPIPEHANDLE(pi->ErrorFd), POLLIN, 0}}; int res; - if (!input) { + if (!input) { fds[0].events = 0; - } - if (!output) { + } + if (!output) { fds[1].events = 0; - } - if (!error) { + } + if (!error) { fds[2].events = 0; - } + } res = PollD(fds, 3, TInstant::Now() + TDuration::MilliSeconds(pi->Parent->PollDelayMs)); // DBG(Cerr << "poll result: " << res << Endl); - if (-res == ETIMEDOUT || res == 0) { + if (-res == ETIMEDOUT || res == 0) { // DBG(Cerr << "poll again..." << Endl); continue; } - if (res < 0) { + if (res < 0) { ythrow yexception() << "poll failed: " << LastSystemErrorText(); - } + } - if ((fds[1].revents & POLLIN) == POLLIN) { + if ((fds[1].revents & POLLIN) == POLLIN) { haveOut = true; - } else if (fds[1].revents & (POLLERR | POLLHUP)) { + } else if (fds[1].revents & (POLLERR | POLLHUP)) { output = nullptr; - } + } - if ((fds[2].revents & POLLIN) == POLLIN) { + if ((fds[2].revents & POLLIN) == POLLIN) { haveErr = true; - } else if (fds[2].revents & (POLLERR | POLLHUP)) { + } else if (fds[2].revents & (POLLERR | POLLHUP)) { error = nullptr; - } + } - if (input && ((fds[0].revents & POLLOUT) == POLLOUT)) { + if (input && ((fds[0].revents & POLLOUT) == POLLOUT)) { haveIn = true; - } + } if (haveOut) { bytes = pi->OutputFd.Read(buffer.Data(), buffer.Capacity()); DBG(Cerr << "transferred " << bytes << " bytes of output" << Endl); - if (bytes > 0) { - output->Write(buffer.Data(), bytes); - } else { + if (bytes > 0) { + output->Write(buffer.Data(), bytes); + } else { output = nullptr; - } + } } if (haveErr) { bytes = pi->ErrorFd.Read(buffer.Data(), buffer.Capacity()); DBG(Cerr << "transferred " << bytes << " bytes of error" << Endl); - if (bytes > 0) { - error->Write(buffer.Data(), bytes); - } else { + if (bytes > 0) { + error->Write(buffer.Data(), bytes); + } else { error = nullptr; - } + } } if (haveIn) { @@ -1043,7 +1043,7 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { bufPos = inputBuffer.Data(); } - bytes = pi->InputFd.Write(bufPos, bytesToWrite); + bytes = pi->InputFd.Write(bufPos, bytesToWrite); if (bytes > 0) { bytesToWrite -= bytes; bufPos += bytes; @@ -1065,11 +1065,11 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { TMaybe<int> processExitCode; #if defined(_unix_) processExitCode = WEXITSTATUS(status); - if (WIFEXITED(status) && processExitCode == 0) { + if (WIFEXITED(status) && processExitCode == 0) { cleanExit = true; - } else if (WIFSIGNALED(status)) { + } else if (WIFSIGNALED(status)) { processExitCode = -WTERMSIG(status); - } + } #else if (waitPidResult == WAIT_OBJECT_0) { DWORD exitCode = STILL_ACTIVE; @@ -1107,23 +1107,23 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) { error->Write(buffer.Data(), bytes); } #endif - } catch (const yexception& e) { + } catch (const yexception& e) { // Some error in watch occured, set result to error AtomicSet(pi->Parent->ExecutionStatus, SHELL_INTERNAL_ERROR); pi->Parent->InternalError = e.what(); - if (input) { + if (input) { pi->InputFd.Close(); - } + } Cdbg << "shell command internal error: " << pi->Parent->InternalError << Endl; } // Now we can safely delete process info struct and other data pi->Parent->TerminateFlag = true; - TerminateIsRequired(pi); + TerminateIsRequired(pi); } TShellCommand::TShellCommand(const TStringBuf cmd, const TList<TString>& args, const TShellCommandOptions& options, const TString& workdir) - : Impl(new TImpl(cmd, args, options, workdir)) + : Impl(new TImpl(cmd, args, options, workdir)) { } @@ -1135,7 +1135,7 @@ TShellCommand::TShellCommand(const TStringBuf cmd, const TShellCommandOptions& o TShellCommand::~TShellCommand() = default; TShellCommand& TShellCommand::operator<<(const TStringBuf argument) { - Impl->AppendArgument(argument); + Impl->AppendArgument(argument); return *this; } @@ -1151,7 +1151,7 @@ const TString& TShellCommand::GetInternalError() const { return Impl->GetInternalError(); } -TShellCommand::ECommandStatus TShellCommand::GetStatus() const { +TShellCommand::ECommandStatus TShellCommand::GetStatus() const { return Impl->GetStatus(); } @@ -1175,17 +1175,17 @@ TFileHandle& TShellCommand::GetErrorHandle() { return Impl->GetErrorHandle(); } -TShellCommand& TShellCommand::Run() { +TShellCommand& TShellCommand::Run() { Impl->Run(); return *this; } -TShellCommand& TShellCommand::Terminate() { +TShellCommand& TShellCommand::Terminate() { Impl->Terminate(); return *this; } -TShellCommand& TShellCommand::Wait() { +TShellCommand& TShellCommand::Wait() { Impl->Wait(); return *this; } diff --git a/util/system/shellcommand.h b/util/system/shellcommand.h index 8730627fe5..a28d55d2e5 100644 --- a/util/system/shellcommand.h +++ b/util/system/shellcommand.h @@ -9,12 +9,12 @@ #include <util/stream/input.h> #include <util/stream/output.h> #include "file.h" -#include "getpid.h" -#include "thread.h" -#include "mutex.h" +#include "getpid.h" +#include "thread.h" +#include "mutex.h" #include <sys/types.h> -class TShellCommandOptions { +class TShellCommandOptions { public: struct TUserOptions { TString Name; @@ -39,32 +39,32 @@ public: public: inline TShellCommandOptions() noexcept - : ClearSignalMask(false) - , CloseAllFdsOnExec(false) - , AsyncMode(false) - , PollDelayMs(DefaultSyncPollDelay) - , UseShell(true) - , QuoteArguments(true) - , DetachSession(true) - , CloseStreams(false) - , ShouldCloseInput(true) + : ClearSignalMask(false) + , CloseAllFdsOnExec(false) + , AsyncMode(false) + , PollDelayMs(DefaultSyncPollDelay) + , UseShell(true) + , QuoteArguments(true) + , DetachSession(true) + , CloseStreams(false) + , ShouldCloseInput(true) , InputMode(HANDLE_INHERIT) , OutputMode(HANDLE_STREAM) , ErrorMode(HANDLE_STREAM) - , InputStream(nullptr) - , OutputStream(nullptr) - , ErrorStream(nullptr) - , Nice(0) + , InputStream(nullptr) + , OutputStream(nullptr) + , ErrorStream(nullptr) + , Nice(0) , FuncAfterFork(std::function<void()>()) - { + { } inline TShellCommandOptions& SetNice(int value) noexcept { - Nice = value; - - return *this; - } - + Nice = value; + + return *this; + } + /** * @brief clear signal mask from parent process. If true, child process * clears the signal mask inherited from the parent process; otherwise @@ -329,10 +329,10 @@ public: * @brief Execute command in shell and provide its results * @attention Not thread-safe */ -class TShellCommand: public TNonCopyable { +class TShellCommand: public TNonCopyable { private: TShellCommand(); - + public: enum ECommandStatus { SHELL_NONE, @@ -341,7 +341,7 @@ public: SHELL_INTERNAL_ERROR, SHELL_ERROR }; - + public: /** * @brief create the command with initial arguments list @@ -355,7 +355,7 @@ public: const TString& workdir = TString()); TShellCommand(const TStringBuf cmd, const TShellCommandOptions& options = TShellCommandOptions(), const TString& workdir = TString()); ~TShellCommand(); - + public: /** * @brief append argument to the args list @@ -406,7 +406,7 @@ public: */ TMaybe<int> GetExitCode() const; - /** + /** * @brief get id of underlying process * @note depends on os: pid_t on UNIX, HANDLE on win * @@ -456,7 +456,7 @@ public: * @return self */ TShellCommand& Wait(); - + /** * @brief close process' stdin * diff --git a/util/system/shellcommand_ut.cpp b/util/system/shellcommand_ut.cpp index 9d849279d2..8e5af4c7d4 100644 --- a/util/system/shellcommand_ut.cpp +++ b/util/system/shellcommand_ut.cpp @@ -1,9 +1,9 @@ -#include "shellcommand.h" +#include "shellcommand.h" #include "compat.h" -#include "defaults.h" +#include "defaults.h" #include "fs.h" -#include "sigset.h" +#include "sigset.h" #include "spinlock.h" #include <library/cpp/testing/unittest/env.h> @@ -18,13 +18,13 @@ #include <util/folder/tempdir.h> #if defined(_win_) - #define NL "\r\n" -const char catCommand[] = "sort"; // not really cat but ok -const size_t textSize = 1; + #define NL "\r\n" +const char catCommand[] = "sort"; // not really cat but ok +const size_t textSize = 1; #else - #define NL "\n" -const char catCommand[] = "/bin/cat"; -const size_t textSize = 20000; + #define NL "\n" +const char catCommand[] = "/bin/cat"; +const size_t textSize = 20000; #endif class TGuardedStringStream: public IInputStream, public IOutputStream { @@ -88,8 +88,8 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { TShellCommandOptions options; options.SetQuoteArguments(true); TShellCommand cmd("echo"); - cmd << "hey" - << "hello&world"; + cmd << "hey" + << "hello&world"; cmd.Run(); UNIT_ASSERT_VALUES_EQUAL(cmd.GetError(), ""); UNIT_ASSERT_VALUES_EQUAL(cmd.GetOutput(), "hey hello&world" NL); @@ -125,8 +125,8 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { { options.SetUseShell(false); TShellCommand cmd(dir, options); - cmd << "|" - << "sort"; + cmd << "|" + << "sort"; cmd.Run(); UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus()); @@ -135,8 +135,8 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { { options.SetUseShell(true); TShellCommand cmd(dir, options); - cmd << "|" - << "sort"; + cmd << "|" + << "sort"; cmd.Run(); UNIT_ASSERT(TShellCommand::SHELL_FINISHED == cmd.GetStatus()); UNIT_ASSERT_VALUES_EQUAL(cmd.GetError().size(), 0u); @@ -304,7 +304,7 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { options.SetQuoteArguments(false); { TShellCommand cmd("/bin/sleep", options); - cmd << " 1300 & wait; /usr/bin/touch " << tmpfile; + cmd << " 1300 & wait; /usr/bin/touch " << tmpfile; cmd.Run(); sleep(1); UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); @@ -337,13 +337,13 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { { TShellCommand cmd("/bin/sleep", options); // touch file only if sleep not interrupted by SIGTERM - cmd << " 10 & wait; [ $? == 0 ] || /usr/bin/touch " << tmpfile; + cmd << " 10 & wait; [ $? == 0 ] || /usr/bin/touch " << tmpfile; cmd.Run(); sleep(1); UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); cmd.Terminate(); cmd.Wait(); - UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus() || TShellCommand::SHELL_FINISHED == cmd.GetStatus()); + UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus() || TShellCommand::SHELL_FINISHED == cmd.GetStatus()); } sleep(1); UNIT_ASSERT(!NFs::Exists(tmpfile)); @@ -353,7 +353,7 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) { { TShellCommand cmd("/bin/sleep", options); // touch file regardless -- it will be interrupted - cmd << " 10 & wait; /usr/bin/touch " << tmpfile; + cmd << " 10 & wait; /usr/bin/touch " << tmpfile; cmd.Run(); sleep(1); UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); diff --git a/util/system/shmat.cpp b/util/system/shmat.cpp index 07ff0d6caa..52cf01f6e0 100644 --- a/util/system/shmat.cpp +++ b/util/system/shmat.cpp @@ -1,72 +1,72 @@ #include "shmat.h" - + #include <util/generic/guid.h> - -#if defined(_win_) - #include <stdio.h> - #include "winint.h" -#elif defined(_bionic_) - #include <sys/types.h> - #include <sys/ipc.h> - #include <sys/syscall.h> -#elif defined(_unix_) - #include <sys/types.h> - #include <sys/ipc.h> - #include <sys/shm.h> -#endif - -#if defined(_cygwin_) - #define WINAPI __stdcall - #define FILE_MAP_ALL_ACCESS ((long)983071) - #define PAGE_READWRITE 4 - #define FALSE 0 - -extern "C" { - using HANDLE = OS_HANDLE; - using BOOL = int; - using DWORD = ui32; - using LPCTSTR = const char*; - using LPVOID = void*; - using LPCVOID = void const*; - using SIZE_T = size_t; - - BOOL WINAPI CloseHandle(HANDLE hObject); - HANDLE WINAPI OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName); - LPVOID WINAPI MapViewOfFile(HANDLE hFileMappingObject, DWORD DesiredAccess, DWORD FileOffsetHigh, DWORD FileOffsetLow, SIZE_T NumberOfBytesToMap); - HANDLE WINAPI CreateFileMappingA(HANDLE hFile, LPVOID lpAttributes, DWORD flProtect, DWORD MaximumSizeHigh, DWORD MaximumSizeLow, LPCTSTR lpName); - BOOL WINAPI UnmapViewOfFile(LPCVOID lpBaseAddress); - DWORD WINAPI GetLastError(void); -} + +#if defined(_win_) + #include <stdio.h> + #include "winint.h" +#elif defined(_bionic_) + #include <sys/types.h> + #include <sys/ipc.h> + #include <sys/syscall.h> +#elif defined(_unix_) + #include <sys/types.h> + #include <sys/ipc.h> + #include <sys/shm.h> +#endif + +#if defined(_cygwin_) + #define WINAPI __stdcall + #define FILE_MAP_ALL_ACCESS ((long)983071) + #define PAGE_READWRITE 4 + #define FALSE 0 + +extern "C" { + using HANDLE = OS_HANDLE; + using BOOL = int; + using DWORD = ui32; + using LPCTSTR = const char*; + using LPVOID = void*; + using LPCVOID = void const*; + using SIZE_T = size_t; + + BOOL WINAPI CloseHandle(HANDLE hObject); + HANDLE WINAPI OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName); + LPVOID WINAPI MapViewOfFile(HANDLE hFileMappingObject, DWORD DesiredAccess, DWORD FileOffsetHigh, DWORD FileOffsetLow, SIZE_T NumberOfBytesToMap); + HANDLE WINAPI CreateFileMappingA(HANDLE hFile, LPVOID lpAttributes, DWORD flProtect, DWORD MaximumSizeHigh, DWORD MaximumSizeLow, LPCTSTR lpName); + BOOL WINAPI UnmapViewOfFile(LPCVOID lpBaseAddress); + DWORD WINAPI GetLastError(void); +} #endif -#if defined(_bionic_) -namespace { - #if !defined(__i386__) - static int shmget(key_t key, size_t size, int flag) { - if (size > PTRDIFF_MAX) { - size = SIZE_MAX; - } - - return syscall(__NR_shmget, key, size, flag); - } - - static void* shmat(int id, const void* addr, int flag) { - return (void*)syscall(__NR_shmat, id, addr, flag); - } - - static int shmctl(int id, int cmd, void* buf) { - return syscall(__NR_shmctl, id, cmd | IPC_64, buf); - } - - static int shmdt(const void* addr) { - return syscall(__NR_shmdt, addr); - } - - #else - #define IPCOP_shmat 21 - #define IPCOP_shmdt 22 - #define IPCOP_shmget 23 - #define IPCOP_shmctl 24 +#if defined(_bionic_) +namespace { + #if !defined(__i386__) + static int shmget(key_t key, size_t size, int flag) { + if (size > PTRDIFF_MAX) { + size = SIZE_MAX; + } + + return syscall(__NR_shmget, key, size, flag); + } + + static void* shmat(int id, const void* addr, int flag) { + return (void*)syscall(__NR_shmat, id, addr, flag); + } + + static int shmctl(int id, int cmd, void* buf) { + return syscall(__NR_shmctl, id, cmd | IPC_64, buf); + } + + static int shmdt(const void* addr) { + return syscall(__NR_shmdt, addr); + } + + #else + #define IPCOP_shmat 21 + #define IPCOP_shmdt 22 + #define IPCOP_shmget 23 + #define IPCOP_shmctl 24 static int shmget(key_t key, size_t size, int flag) { return syscall(__NR_ipc, IPCOP_shmget, key, size, flag, 0); @@ -75,7 +75,7 @@ namespace { static void* shmat(int id, const void* addr, int flag) { void* retval; long res = syscall(__NR_ipc, IPCOP_shmat, id, flag, (long)&retval, addr); - return (res >= 0) ? retval : (void*)-1; + return (res >= 0) ? retval : (void*)-1; } static int shmctl(int id, int cmd, void* buf) { @@ -85,49 +85,49 @@ namespace { static int shmdt(const void* addr) { return syscall(__NR_ipc, IPCOP_shmdt, 0, 0, 0, addr); } - #endif -} -#endif - + #endif +} +#endif + TSharedMemory::TSharedMemory() - : Handle(INVALID_FHANDLE) + : Handle(INVALID_FHANDLE) , Data(nullptr) , Size(0) { } -#if defined(_win_) -static void FormatName(char* buf, const TGUID& id) { +#if defined(_win_) +static void FormatName(char* buf, const TGUID& id) { sprintf(buf, "Global\\shmat-%s", GetGuidAsString(id).c_str()); } -bool TSharedMemory::Open(const TGUID& id, int size) { +bool TSharedMemory::Open(const TGUID& id, int size) { //Y_ASSERT(Data == 0); Id = id; Size = size; char name[100]; FormatName(name, Id); - Handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name); - - if (Handle == 0) { + Handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name); + + if (Handle == 0) { return false; - } - - Data = MapViewOfFile(Handle, FILE_MAP_ALL_ACCESS, 0, 0, size); + } + Data = MapViewOfFile(Handle, FILE_MAP_ALL_ACCESS, 0, 0, size); + if (Data == 0) { //Y_ASSERT(0); - CloseHandle(Handle); - Handle = INVALID_OS_HANDLE; - + CloseHandle(Handle); + Handle = INVALID_OS_HANDLE; + return false; } - + return true; } -bool TSharedMemory::Create(int size) { +bool TSharedMemory::Create(int size) { //Y_ASSERT(Data == 0); Size = size; @@ -135,97 +135,97 @@ bool TSharedMemory::Create(int size) { char name[100]; FormatName(name, Id); - Handle = CreateFileMappingA(INVALID_OS_HANDLE, nullptr, PAGE_READWRITE, 0, size, name); - - if (Handle == 0) { + Handle = CreateFileMappingA(INVALID_OS_HANDLE, nullptr, PAGE_READWRITE, 0, size, name); + + if (Handle == 0) { //Y_ASSERT(0); return false; } - Data = MapViewOfFile(Handle, FILE_MAP_ALL_ACCESS, 0, 0, size); - + Data = MapViewOfFile(Handle, FILE_MAP_ALL_ACCESS, 0, 0, size); + if (Data == 0) { //Y_ASSERT(0); - CloseHandle(Handle); - Handle = INVALID_OS_HANDLE; - + CloseHandle(Handle); + Handle = INVALID_OS_HANDLE; + return false; } - + return true; } -TSharedMemory::~TSharedMemory() { - if (Data) { - UnmapViewOfFile(Handle); - } - - CloseHandle(Handle); +TSharedMemory::~TSharedMemory() { + if (Data) { + UnmapViewOfFile(Handle); + } + + CloseHandle(Handle); } #else -static key_t GetKey(const TGUID& id) { - i64 id64 = (ui64)(((ui64)id.dw[0] + (ui64)id.dw[2]) << 32) + (ui64)id.dw[1] + (ui64)id.dw[3]; - +static key_t GetKey(const TGUID& id) { + i64 id64 = (ui64)(((ui64)id.dw[0] + (ui64)id.dw[2]) << 32) + (ui64)id.dw[1] + (ui64)id.dw[3]; + return id64; } -bool TSharedMemory::Open(const TGUID& id, int size) { +bool TSharedMemory::Open(const TGUID& id, int size) { Y_VERIFY(id, "invalid shared memory guid: %s", GetGuidAsString(id).data()); //Y_ASSERT(Data == 0); Size = size; key_t k = GetKey(id); - int shmId = shmget(k, Size, 0777); // do not fill Handle, since IPC_RMID should be called by owner - - if (shmId < 0) { + int shmId = shmget(k, Size, 0777); // do not fill Handle, since IPC_RMID should be called by owner + + if (shmId < 0) { return false; - } + } Data = shmat(shmId, nullptr, 0); - + if (Data == nullptr) { //Y_ASSERT(0); return false; } - + return true; } -bool TSharedMemory::Create(int size) { +bool TSharedMemory::Create(int size) { //Y_ASSERT(Data == 0); Size = size; CreateGuid(&Id); key_t k = GetKey(Id); - Handle = shmget(k, Size, IPC_CREAT | IPC_EXCL | 0777); - - if (Handle < 0) { + Handle = shmget(k, Size, IPC_CREAT | IPC_EXCL | 0777); + + if (Handle < 0) { //Y_ASSERT(0); return false; } - Data = shmat(Handle, nullptr, 0); - - if (Data == (void*)-1) { + Data = shmat(Handle, nullptr, 0); + + if (Data == (void*)-1) { //Y_ASSERT(0); - shmctl(Handle, IPC_RMID, nullptr); - Handle = -1; - + shmctl(Handle, IPC_RMID, nullptr); + Handle = -1; + return false; } - + return true; } -TSharedMemory::~TSharedMemory() { - if (Data) { +TSharedMemory::~TSharedMemory() { + if (Data) { shmdt(Data); - } - - if (Handle >= 0) { - shmctl(Handle, IPC_RMID, nullptr); - } + } + + if (Handle >= 0) { + shmctl(Handle, IPC_RMID, nullptr); + } } #endif diff --git a/util/system/shmat.h b/util/system/shmat.h index d9da3c151a..acd6266a8e 100644 --- a/util/system/shmat.h +++ b/util/system/shmat.h @@ -1,32 +1,32 @@ #pragma once -#include "fhandle.h" - -#include <util/generic/ptr.h> +#include "fhandle.h" + +#include <util/generic/ptr.h> #include <util/generic/guid.h> -class TSharedMemory: public TThrRefBase { +class TSharedMemory: public TThrRefBase { TGUID Id; - FHANDLE Handle; - void* Data; + FHANDLE Handle; + void* Data; int Size; - + public: TSharedMemory(); ~TSharedMemory() override; - + bool Create(int Size); - bool Open(const TGUID& id, int size); - - const TGUID& GetId() { - return Id; - } - - void* GetPtr() { - return Data; - } - - int GetSize() const { - return Size; - } + bool Open(const TGUID& id, int size); + + const TGUID& GetId() { + return Id; + } + + void* GetPtr() { + return Data; + } + + int GetSize() const { + return Size; + } }; diff --git a/util/system/shmat_ut.cpp b/util/system/shmat_ut.cpp index 9d92243ae7..8940e30499 100644 --- a/util/system/shmat_ut.cpp +++ b/util/system/shmat_ut.cpp @@ -1,17 +1,17 @@ -#include "shmat.h" - +#include "shmat.h" + #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TTestSharedMemory) { Y_UNIT_TEST(TestInProc) { - TSharedMemory m1; - TSharedMemory m2; - - UNIT_ASSERT(m1.Create(128)); - UNIT_ASSERT(m2.Open(m1.GetId(), m1.GetSize())); - - *(ui32*)m1.GetPtr() = 123; - - UNIT_ASSERT_VALUES_EQUAL(*(ui32*)m2.GetPtr(), 123); - } -} + TSharedMemory m1; + TSharedMemory m2; + + UNIT_ASSERT(m1.Create(128)); + UNIT_ASSERT(m2.Open(m1.GetId(), m1.GetSize())); + + *(ui32*)m1.GetPtr() = 123; + + UNIT_ASSERT_VALUES_EQUAL(*(ui32*)m2.GetPtr(), 123); + } +} diff --git a/util/system/sigset.cpp b/util/system/sigset.cpp index 4d91538191..c19825fcbc 100644 --- a/util/system/sigset.cpp +++ b/util/system/sigset.cpp @@ -1 +1 @@ -#include "sigset.h" +#include "sigset.h" diff --git a/util/system/sigset.h b/util/system/sigset.h index 8dd02fd817..ed76bac439 100644 --- a/util/system/sigset.h +++ b/util/system/sigset.h @@ -5,20 +5,20 @@ #include "compat.h" #if defined _unix_ - #include <pthread.h> + #include <pthread.h> #elif defined _win_ - // Flags for sigprocmask: - #define SIG_BLOCK 1 - #define SIG_UNBLOCK 2 - #define SIG_SETMASK 3 + // Flags for sigprocmask: + #define SIG_BLOCK 1 + #define SIG_UNBLOCK 2 + #define SIG_SETMASK 3 using sigset_t = ui32; #else - #error not supported yet + #error not supported yet #endif -inline int SigEmptySet(sigset_t* set) { +inline int SigEmptySet(sigset_t* set) { #if defined _unix_ return sigemptyset(set); #else @@ -27,7 +27,7 @@ inline int SigEmptySet(sigset_t* set) { #endif } -inline int SigFillSet(sigset_t* set) { +inline int SigFillSet(sigset_t* set) { #if defined _unix_ return sigfillset(set); #else @@ -36,7 +36,7 @@ inline int SigFillSet(sigset_t* set) { #endif } -inline int SigAddSet(sigset_t* set, int signo) { +inline int SigAddSet(sigset_t* set, int signo) { #if defined _unix_ return sigaddset(set, signo); #else @@ -46,7 +46,7 @@ inline int SigAddSet(sigset_t* set, int signo) { #endif } -inline int SigDelSet(sigset_t* set, int signo) { +inline int SigDelSet(sigset_t* set, int signo) { #if defined _unix_ return sigdelset(set, signo); #else @@ -56,9 +56,9 @@ inline int SigDelSet(sigset_t* set, int signo) { #endif } -inline int SigIsMember(const sigset_t* set, int signo) { +inline int SigIsMember(const sigset_t* set, int signo) { #if defined _unix_ - return sigismember(const_cast<sigset_t*>(set), signo); + return sigismember(const_cast<sigset_t*>(set), signo); #else Y_UNUSED(set); Y_UNUSED(signo); @@ -66,7 +66,7 @@ inline int SigIsMember(const sigset_t* set, int signo) { #endif } -inline int SigProcMask(int how, const sigset_t* set, sigset_t* oset) { +inline int SigProcMask(int how, const sigset_t* set, sigset_t* oset) { #if defined _unix_ return pthread_sigmask(how, set, oset); #else diff --git a/util/system/spin_wait.cpp b/util/system/spin_wait.cpp index e27045e74f..b04552d915 100644 --- a/util/system/spin_wait.cpp +++ b/util/system/spin_wait.cpp @@ -1,40 +1,40 @@ -#include "spin_wait.h" -#include "yield.h" -#include "compat.h" -#include "thread.h" -#include "spinlock.h" - -#include <util/digest/numeric.h> -#include <util/generic/utility.h> - -template <class T> +#include "spin_wait.h" +#include "yield.h" +#include "compat.h" +#include "thread.h" +#include "spinlock.h" + +#include <util/digest/numeric.h> +#include <util/generic/utility.h> + +template <class T> static inline T RandomizeSleepTime(T t) noexcept { - static TAtomic counter = 0; - const T rndNum = IntHash((T)AtomicIncrement(counter)); - - return (t * (T)4 + (rndNum % t) * (T)2) / (T)5; -} - -//arbitrary values -#define MIN_SLEEP_TIME 500 + static TAtomic counter = 0; + const T rndNum = IntHash((T)AtomicIncrement(counter)); + + return (t * (T)4 + (rndNum % t) * (T)2) / (T)5; +} + +//arbitrary values +#define MIN_SLEEP_TIME 500 #define MAX_SPIN_COUNT 0x7FF - -TSpinWait::TSpinWait() noexcept - : T(MIN_SLEEP_TIME) - , C(0) -{ -} - -void TSpinWait::Sleep() noexcept { - ++C; - - if (C == MAX_SPIN_COUNT) { - ThreadYield(); - } else if ((C & MAX_SPIN_COUNT) == 0) { - usleep(RandomizeSleepTime(T)); - - T = Min<unsigned>((T * 3) / 2, 20000); - } else { - SpinLockPause(); - } -} + +TSpinWait::TSpinWait() noexcept + : T(MIN_SLEEP_TIME) + , C(0) +{ +} + +void TSpinWait::Sleep() noexcept { + ++C; + + if (C == MAX_SPIN_COUNT) { + ThreadYield(); + } else if ((C & MAX_SPIN_COUNT) == 0) { + usleep(RandomizeSleepTime(T)); + + T = Min<unsigned>((T * 3) / 2, 20000); + } else { + SpinLockPause(); + } +} diff --git a/util/system/spin_wait.h b/util/system/spin_wait.h index 91dd423e33..ded55b8d81 100644 --- a/util/system/spin_wait.h +++ b/util/system/spin_wait.h @@ -1,10 +1,10 @@ #pragma once -struct TSpinWait { - TSpinWait() noexcept; +struct TSpinWait { + TSpinWait() noexcept; + + void Sleep() noexcept; - void Sleep() noexcept; - - unsigned T; - unsigned C; + unsigned T; + unsigned C; }; diff --git a/util/system/spinlock.cpp b/util/system/spinlock.cpp index 63a803a30e..b117e1bcc4 100644 --- a/util/system/spinlock.cpp +++ b/util/system/spinlock.cpp @@ -1 +1 @@ -#include "spinlock.h" +#include "spinlock.h" diff --git a/util/system/spinlock.h b/util/system/spinlock.h index af2630890a..e596db3187 100644 --- a/util/system/spinlock.h +++ b/util/system/spinlock.h @@ -1,68 +1,68 @@ #pragma once -#include "atomic.h" -#include "spin_wait.h" - +#include "atomic.h" +#include "spin_wait.h" + class TSpinLockBase { -protected: +protected: inline TSpinLockBase() noexcept { AtomicSet(Val_, 0); - } + } -public: +public: inline bool IsLocked() const noexcept { - return AtomicGet(Val_); - } + return AtomicGet(Val_); + } inline bool TryAcquire() noexcept { - return AtomicTryLock(&Val_); - } + return AtomicTryLock(&Val_); + } inline bool try_lock() noexcept { return TryAcquire(); } -protected: - TAtomic Val_; +protected: + TAtomic Val_; }; -static inline void SpinLockPause() { +static inline void SpinLockPause() { #if defined(__GNUC__) #if defined(_i386_) || defined(_x86_64_) - __asm __volatile("pause"); + __asm __volatile("pause"); #elif defined(_arm64_) __asm __volatile("yield" :: : "memory"); #endif -#endif -} - -static inline void AcquireSpinLock(TAtomic* l) { - if (!AtomicTryLock(l)) { - do { - SpinLockPause(); - } while (!AtomicTryAndTryLock(l)); - } -} - -static inline void ReleaseSpinLock(TAtomic* l) { - AtomicUnlock(l); -} - -/* - * You should almost always use TAdaptiveLock instead of TSpinLock - */ -class TSpinLock: public TSpinLockBase { -public: +#endif +} + +static inline void AcquireSpinLock(TAtomic* l) { + if (!AtomicTryLock(l)) { + do { + SpinLockPause(); + } while (!AtomicTryAndTryLock(l)); + } +} + +static inline void ReleaseSpinLock(TAtomic* l) { + AtomicUnlock(l); +} + +/* + * You should almost always use TAdaptiveLock instead of TSpinLock + */ +class TSpinLock: public TSpinLockBase { +public: using TSpinLockBase::TSpinLockBase; inline void Release() noexcept { - ReleaseSpinLock(&Val_); - } - + ReleaseSpinLock(&Val_); + } + inline void Acquire() noexcept { - AcquireSpinLock(&Val_); - } + AcquireSpinLock(&Val_); + } inline void unlock() noexcept { Release(); @@ -71,33 +71,33 @@ public: inline void lock() noexcept { Acquire(); } -}; - -static inline void AcquireAdaptiveLock(TAtomic* l) { - if (!AtomicTryLock(l)) { - TSpinWait sw; - - while (!AtomicTryAndTryLock(l)) { - sw.Sleep(); - } - } -} - -static inline void ReleaseAdaptiveLock(TAtomic* l) { - AtomicUnlock(l); -} - -class TAdaptiveLock: public TSpinLockBase { -public: +}; + +static inline void AcquireAdaptiveLock(TAtomic* l) { + if (!AtomicTryLock(l)) { + TSpinWait sw; + + while (!AtomicTryAndTryLock(l)) { + sw.Sleep(); + } + } +} + +static inline void ReleaseAdaptiveLock(TAtomic* l) { + AtomicUnlock(l); +} + +class TAdaptiveLock: public TSpinLockBase { +public: using TSpinLockBase::TSpinLockBase; inline void Release() noexcept { - ReleaseAdaptiveLock(&Val_); - } - + ReleaseAdaptiveLock(&Val_); + } + inline void Acquire() noexcept { - AcquireAdaptiveLock(&Val_); - } + AcquireAdaptiveLock(&Val_); + } inline void unlock() noexcept { Release(); @@ -106,21 +106,21 @@ public: inline void lock() noexcept { Acquire(); } -}; - -#include "guard.h" - -template <> -struct TCommonLockOps<TAtomic> { +}; + +#include "guard.h" + +template <> +struct TCommonLockOps<TAtomic> { static inline void Acquire(TAtomic* v) noexcept { - AcquireAdaptiveLock(v); - } - + AcquireAdaptiveLock(v); + } + static inline bool TryAcquire(TAtomic* v) noexcept { return AtomicTryLock(v); } static inline void Release(TAtomic* v) noexcept { - ReleaseAdaptiveLock(v); - } -}; + ReleaseAdaptiveLock(v); + } +}; diff --git a/util/system/src_location.cpp b/util/system/src_location.cpp index 13ff1f24b3..43e596b325 100644 --- a/util/system/src_location.cpp +++ b/util/system/src_location.cpp @@ -1,10 +1,10 @@ -#include "src_location.h" - -#include <util/stream/output.h> - +#include "src_location.h" + +#include <util/stream/output.h> + #include <algorithm> -template <> +template <> void Out<TSourceLocation>(IOutputStream& o, const TSourceLocation& t) { #if defined(_win_) TString file(t.File); @@ -14,4 +14,4 @@ void Out<TSourceLocation>(IOutputStream& o, const TSourceLocation& t) { o << t.File; #endif o << ':' << t.Line; -} +} diff --git a/util/system/src_location.h b/util/system/src_location.h index 12ba6e063e..2e35395c54 100644 --- a/util/system/src_location.h +++ b/util/system/src_location.h @@ -1,25 +1,25 @@ -#pragma once - -#include "src_root.h" - -#include <util/generic/strbuf.h> - -struct TSourceLocation { +#pragma once + +#include "src_root.h" + +#include <util/generic/strbuf.h> + +struct TSourceLocation { constexpr TSourceLocation(const TStringBuf f, int l) noexcept - : File(f) - , Line(l) - { - } - - TStringBuf File; - int Line; -}; - + : File(f) + , Line(l) + { + } + + TStringBuf File; + int Line; +}; + // __SOURCE_FILE__ should be used instead of __FILE__ #if !defined(__NVCC__) - #define __SOURCE_FILE__ (__SOURCE_FILE_IMPL__.As<TStringBuf>()) + #define __SOURCE_FILE__ (__SOURCE_FILE_IMPL__.As<TStringBuf>()) #else - #define __SOURCE_FILE__ (__SOURCE_FILE_IMPL__.template As<TStringBuf>()) + #define __SOURCE_FILE__ (__SOURCE_FILE_IMPL__.template As<TStringBuf>()) #endif -#define __LOCATION__ ::TSourceLocation(__SOURCE_FILE__, __LINE__) +#define __LOCATION__ ::TSourceLocation(__SOURCE_FILE__, __LINE__) diff --git a/util/system/src_location_ut.cpp b/util/system/src_location_ut.cpp index 5b86cb86ef..cead18b64a 100644 --- a/util/system/src_location_ut.cpp +++ b/util/system/src_location_ut.cpp @@ -1,18 +1,18 @@ -#include "src_location.h" - -#include <util/string/builder.h> - +#include "src_location.h" + +#include <util/string/builder.h> + #include <library/cpp/testing/unittest/registar.h> - + static inline TString GenLoc() { - return TStringBuilder() << __LOCATION__; -} - + return TStringBuilder() << __LOCATION__; +} + Y_UNIT_TEST_SUITE(TestLocation) { Y_UNIT_TEST(Test1) { - UNIT_ASSERT_VALUES_EQUAL(GenLoc(), "util/system/src_location_ut.cpp:8"); + UNIT_ASSERT_VALUES_EQUAL(GenLoc(), "util/system/src_location_ut.cpp:8"); static constexpr TSourceLocation location = __LOCATION__; static_assert(location.Line >= 0, "__LOCATION__ can be used at compile time expressions"); - } -} + } +} diff --git a/util/system/src_root.h b/util/system/src_root.h index 4f2d9f5ee6..2e599acc34 100644 --- a/util/system/src_root.h +++ b/util/system/src_root.h @@ -1,37 +1,37 @@ -#pragma once - +#pragma once + #include "compiler.h" #include "defaults.h" #include <type_traits> -namespace NPrivate { - struct TStaticBuf { +namespace NPrivate { + struct TStaticBuf { constexpr TStaticBuf(const char* data, unsigned len) noexcept - : Data(data) - , Len(len) - { - } - - template <class T> + : Data(data) + , Len(len) + { + } + + template <class T> constexpr T As() const noexcept { - return T(Data, Len); - } - - template <class T> + return T(Data, Len); + } + + template <class T> constexpr operator T() const noexcept { - return this->As<T>(); - } - - const char* Data; - unsigned Len; - }; - -#define STATIC_BUF(x) ::NPrivate::TStaticBuf(x, sizeof(x) - 1) - + return this->As<T>(); + } + + const char* Data; + unsigned Len; + }; + +#define STATIC_BUF(x) ::NPrivate::TStaticBuf(x, sizeof(x) - 1) + constexpr TStaticBuf ArcRoot = STATIC_BUF(Y_STRINGIZE(ARCADIA_ROOT)); constexpr TStaticBuf BuildRoot = STATIC_BUF(Y_STRINGIZE(ARCADIA_BUILD_ROOT)); - + constexpr Y_FORCE_INLINE bool IsProperPrefix(const TStaticBuf prefix, const TStaticBuf string) noexcept { if (prefix.Len < string.Len) { for (unsigned i = prefix.Len; i-- > 0;) { @@ -53,7 +53,7 @@ namespace NPrivate { return BuildRoot.Len + 1; } return 0; - } + } constexpr Y_FORCE_INLINE TStaticBuf StripRoot(const TStaticBuf& f, unsigned prefixLength) noexcept { return TStaticBuf(f.Data + prefixLength, f.Len - prefixLength); @@ -63,6 +63,6 @@ namespace NPrivate { constexpr Y_FORCE_INLINE TStaticBuf StripRoot(const TStaticBuf& f) noexcept { return StripRoot(f, RootPrefixLength(f)); } -} - +} + #define __SOURCE_FILE_IMPL__ ::NPrivate::StripRoot(STATIC_BUF(__FILE__), std::integral_constant<unsigned, ::NPrivate::RootPrefixLength(STATIC_BUF(__FILE__))>::value) diff --git a/util/system/src_root_ut.cpp b/util/system/src_root_ut.cpp index e9a675eb9a..907872921d 100644 --- a/util/system/src_root_ut.cpp +++ b/util/system/src_root_ut.cpp @@ -1,14 +1,14 @@ -#include "src_root.h" - +#include "src_root.h" + #include <util/folder/pathsplit.h> #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TestSourceRoot) { Y_UNIT_TEST(TestStrip) { // Reconstruct() converts "\" -> "/" on Windows const TString path = TPathSplit(__SOURCE_FILE_IMPL__.As<TStringBuf>()).Reconstruct(); UNIT_ASSERT_EQUAL(path, "util" LOCSLASH_S "system" LOCSLASH_S "src_root_ut.cpp"); - } + } Y_UNIT_TEST(TestPrivateChopPrefixRoutine) { static constexpr const char str[] = ":\0:\0: It's unlikely that this string has an ARCADIA_ROOT as its prefix :\0:\0:"; @@ -24,4 +24,4 @@ Y_UNIT_TEST_SUITE(TestSourceRoot) { static_assert(!::NPrivate::IsProperPrefix(STATIC_BUF(""), STATIC_BUF("")), R"(IsProperPrefix("", "") failed)"); static_assert(::NPrivate::IsProperPrefix(STATIC_BUF("dir"), STATIC_BUF("dir/file")), R"(IsProperPrefix("dir", "dir/file") failed)"); } -} +} diff --git a/util/system/sys_alloc.cpp b/util/system/sys_alloc.cpp index 45ed522667..56b94ed611 100644 --- a/util/system/sys_alloc.cpp +++ b/util/system/sys_alloc.cpp @@ -1 +1 @@ -#include "sys_alloc.h" +#include "sys_alloc.h" diff --git a/util/system/sys_alloc.h b/util/system/sys_alloc.h index 4221a28f8c..8ff1757ee1 100644 --- a/util/system/sys_alloc.h +++ b/util/system/sys_alloc.h @@ -2,20 +2,20 @@ #include <util/system/compiler.h> -#include <cstdlib> +#include <cstdlib> #include <new> - -inline void* y_allocate(size_t n) { - void* r = malloc(n); - + +inline void* y_allocate(size_t n) { + void* r = malloc(n); + if (r == nullptr) { throw std::bad_alloc(); - } - + } + return r; } -inline void y_deallocate(void* p) { +inline void y_deallocate(void* p) { free(p); } @@ -24,20 +24,20 @@ inline void y_deallocate(void* p) { * * Our implementation work as C++99: if new_sz == 0 free will be called on 'p' and nullptr returned. */ -inline void* y_reallocate(void* p, size_t new_sz) { +inline void* y_reallocate(void* p, size_t new_sz) { if (!new_sz) { if (p) { free(p); } - + return nullptr; } - void* r = realloc(p, new_sz); - + void* r = realloc(p, new_sz); + if (r == nullptr) { throw std::bad_alloc(); - } - + } + return r; } diff --git a/util/system/sysstat.cpp b/util/system/sysstat.cpp index db3338b02e..3189905646 100644 --- a/util/system/sysstat.cpp +++ b/util/system/sysstat.cpp @@ -2,8 +2,8 @@ #ifdef _win_ - #include "winint.h" - #include <errno.h> + #include "winint.h" + #include <errno.h> int Chmod(const char* fname, int mode) { if (!fname) { @@ -11,7 +11,7 @@ int Chmod(const char* fname, int mode) { return -1; } ui32 fAttr = ::GetFileAttributesA(fname); - if (fAttr == 0xffffffff) + if (fAttr == 0xffffffff) return -1; if (mode & _S_IWRITE) { fAttr &= ~FILE_ATTRIBUTE_READONLY; @@ -30,7 +30,7 @@ int Mkdir(const char* path, int /*mode*/) { errno = EINVAL; return -1; } - if (!CreateDirectoryA(path, (LPSECURITY_ATTRIBUTES) nullptr)) { + if (!CreateDirectoryA(path, (LPSECURITY_ATTRIBUTES) nullptr)) { ui32 errCode = GetLastError(); if (errCode == ERROR_ALREADY_EXISTS) { errno = EEXIST; diff --git a/util/system/sysstat.h b/util/system/sysstat.h index b7c424c11b..bdea7a9512 100644 --- a/util/system/sysstat.h +++ b/util/system/sysstat.h @@ -4,20 +4,20 @@ #include <sys/stat.h> #ifdef _win_ - #define S_IRUSR _S_IREAD - #define S_IWUSR _S_IWRITE - #define S_IXUSR _S_IEXEC - #define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) - - #define S_IRGRP _S_IREAD - #define S_IWGRP _S_IWRITE - #define S_IXGRP _S_IEXEC - #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) - - #define S_IROTH _S_IREAD - #define S_IWOTH _S_IWRITE - #define S_IXOTH _S_IEXEC - #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) + #define S_IRUSR _S_IREAD + #define S_IWUSR _S_IWRITE + #define S_IXUSR _S_IEXEC + #define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) + + #define S_IRGRP _S_IREAD + #define S_IWGRP _S_IWRITE + #define S_IXGRP _S_IEXEC + #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) + + #define S_IROTH _S_IREAD + #define S_IWOTH _S_IWRITE + #define S_IXOTH _S_IEXEC + #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) #endif int Chmod(const char* fname, int mode); diff --git a/util/system/tempfile.h b/util/system/tempfile.h index de249c129d..47d69df737 100644 --- a/util/system/tempfile.h +++ b/util/system/tempfile.h @@ -1,32 +1,32 @@ #pragma once - -#include "fs.h" -#include "file.h" - + +#include "fs.h" +#include "file.h" + #include <util/folder/path.h> #include <util/generic/string.h> - -class TTempFile { -public: + +class TTempFile { +public: inline TTempFile(const TString& fname) - : Name_(fname) - { - } - + : Name_(fname) + { + } + inline ~TTempFile() { NFs::Remove(Name()); - } - + } + inline const TString& Name() const noexcept { - return Name_; - } - -private: + return Name_; + } + +private: const TString Name_; -}; - -class TTempFileHandle: public TTempFile, public TFile { -public: +}; + +class TTempFileHandle: public TTempFile, public TFile { +public: TTempFileHandle(); TTempFileHandle(const TString& fname); @@ -35,7 +35,7 @@ public: private: TFile CreateFile() const; -}; +}; /* * Creates a unique temporary filename in specified directory. diff --git a/util/system/thread.cpp b/util/system/thread.cpp index 6236746c2d..7d918f8686 100644 --- a/util/system/thread.cpp +++ b/util/system/thread.cpp @@ -1,12 +1,12 @@ -#include "tls.h" -#include "thread.h" -#include "thread.i" - +#include "tls.h" +#include "thread.h" +#include "thread.i" + #include <util/generic/ptr.h> #include <util/generic/ymath.h> -#include <util/generic/ylimits.h> +#include <util/generic/ylimits.h> #include <util/generic/yexception.h> -#include "yassert.h" +#include "yassert.h" #include <utility> #if defined(_glibc_) @@ -16,12 +16,12 @@ #endif #if defined(_unix_) - #include <pthread.h> + #include <pthread.h> #include <sys/types.h> #elif defined(_win_) - #include "dynlib.h" - #include <util/charset/wide.h> - #include <util/generic/scope.h> + #include "dynlib.h" + #include <util/charset/wide.h> + #include <util/generic/scope.h> #else #error "FIXME" #endif @@ -37,174 +37,174 @@ bool SetHighestThreadPriority() { #endif } -namespace { +namespace { using TParams = TThread::TParams; using TId = TThread::TId; - - inline void SetThrName(const TParams& p) { - try { + + inline void SetThrName(const TParams& p) { + try { if (p.Name) { TThread::SetCurrentThreadName(p.Name.data()); - } - } catch (...) { - // ¯\_(ツ)_/¯ - } - } - + } + } catch (...) { + // ¯\_(ツ)_/¯ + } + } + inline size_t StackSize(const TParams& p) noexcept { - if (p.StackSize) { - return FastClp2(p.StackSize); - } - - return 0; - } - -#if defined(_win_) - class TWinThread { - struct TMyParams: public TParams, public TThrRefBase { - inline TMyParams(const TParams& p) - : TParams(p) - , Result(0) - { - } - - void* Result; - }; - + if (p.StackSize) { + return FastClp2(p.StackSize); + } + + return 0; + } + +#if defined(_win_) + class TWinThread { + struct TMyParams: public TParams, public TThrRefBase { + inline TMyParams(const TParams& p) + : TParams(p) + , Result(0) + { + } + + void* Result; + }; + using TParamsRef = TIntrusivePtr<TMyParams>; - - public: - inline TWinThread(const TParams& params) - : P_(new TMyParams(params)) - , Handle(0) - #if _WIN32_WINNT < 0x0502 - , ThreadId(0) - #endif - { - } + + public: + inline TWinThread(const TParams& params) + : P_(new TMyParams(params)) + , Handle(0) + #if _WIN32_WINNT < 0x0502 + , ThreadId(0) + #endif + { + } inline bool Running() const noexcept { - return Handle != 0; - } - + return Handle != 0; + } + inline TId SystemThreadId() const noexcept { - #if _WIN32_WINNT < 0x0502 + #if _WIN32_WINNT < 0x0502 return (TId)ThreadId; - #else - return (TId)GetThreadId(Handle); - #endif - } - - inline void* Join() { - ::WaitForSingleObject(Handle, INFINITE); - ::CloseHandle(Handle); - - return P_->Result; - } - - inline void Detach() { - ::CloseHandle(Handle); - } + #else + return (TId)GetThreadId(Handle); + #endif + } + + inline void* Join() { + ::WaitForSingleObject(Handle, INFINITE); + ::CloseHandle(Handle); + + return P_->Result; + } + + inline void Detach() { + ::CloseHandle(Handle); + } static ui32 __stdcall Proxy(void* ptr) { NTls::TCleaner cleaner; - - (void)cleaner; - - { - TParamsRef p((TMyParams*)(ptr)); - - //drop counter, gotten in Start() - p->UnRef(); - - SetThrName(*p); - p->Result = p->Proc(p->Data); - } - + + (void)cleaner; + + { + TParamsRef p((TMyParams*)(ptr)); + + //drop counter, gotten in Start() + p->UnRef(); + + SetThrName(*p); + p->Result = p->Proc(p->Data); + } + return 0; - } - - inline void Start() { + } + + inline void Start() { //do not do this, kids, at home P_->Ref(); - #if _WIN32_WINNT < 0x0502 + #if _WIN32_WINNT < 0x0502 Handle = reinterpret_cast<HANDLE>(::_beginthreadex(nullptr, (unsigned)StackSize(*P_), Proxy, (void*)P_.Get(), 0, &ThreadId)); - #else + #else Handle = reinterpret_cast<HANDLE>(::_beginthreadex(nullptr, (unsigned)StackSize(*P_), Proxy, (void*)P_.Get(), 0, nullptr)); - #endif - + #endif + if (!Handle) { P_->UnRef(); ythrow yexception() << "failed to create a thread"; } - } - - private: - TParamsRef P_; - HANDLE Handle; - #if _WIN32_WINNT < 0x0502 - ui32 ThreadId; - #endif - }; - + } + + private: + TParamsRef P_; + HANDLE Handle; + #if _WIN32_WINNT < 0x0502 + ui32 ThreadId; + #endif + }; + using TThreadBase = TWinThread; #else - //unix - - #define PCHECK(x, y) \ - { \ - const int err_ = x; \ - if (err_) { \ - ythrow TSystemError(err_) << TStringBuf(y); \ - } \ - } - - class TPosixThread { - public: - inline TPosixThread(const TParams& params) - : P_(new TParams(params)) + //unix + + #define PCHECK(x, y) \ + { \ + const int err_ = x; \ + if (err_) { \ + ythrow TSystemError(err_) << TStringBuf(y); \ + } \ + } + + class TPosixThread { + public: + inline TPosixThread(const TParams& params) + : P_(new TParams(params)) , H_() - { - static_assert(sizeof(H_) == sizeof(TId), "expect sizeof(H_) == sizeof(TId)"); - } - + { + static_assert(sizeof(H_) == sizeof(TId), "expect sizeof(H_) == sizeof(TId)"); + } + inline TId SystemThreadId() const noexcept { - return (TId)H_; - } - - inline void* Join() { + return (TId)H_; + } + + inline void* Join() { void* tec = nullptr; - PCHECK(pthread_join(H_, &tec), "can not join thread"); - - return tec; - } - - inline void Detach() { - PCHECK(pthread_detach(H_), "can not detach thread"); - } - + PCHECK(pthread_join(H_, &tec), "can not join thread"); + + return tec; + } + + inline void Detach() { + PCHECK(pthread_detach(H_), "can not detach thread"); + } + inline bool Running() const noexcept { - return (bool)H_; - } - - inline void Start() { + return (bool)H_; + } + + inline void Start() { pthread_attr_t* pattrs = nullptr; - pthread_attr_t attrs; - - if (P_->StackSize > 0) { - Zero(attrs); - pthread_attr_init(&attrs); - pattrs = &attrs; - - if (P_->StackPointer) { - pthread_attr_setstack(pattrs, P_->StackPointer, P_->StackSize); - } else { - pthread_attr_setstacksize(pattrs, StackSize(*P_)); - } - } - + pthread_attr_t attrs; + + if (P_->StackSize > 0) { + Zero(attrs); + pthread_attr_init(&attrs); + pattrs = &attrs; + + if (P_->StackPointer) { + pthread_attr_setstack(pattrs, P_->StackPointer, P_->StackSize); + } else { + pthread_attr_setstacksize(pattrs, StackSize(*P_)); + } + } + { - TParams* holdP = P_.Release(); + TParams* holdP = P_.Release(); int err = pthread_create(&H_, pattrs, ThreadProxy, holdP); if (err) { H_ = {}; @@ -212,54 +212,54 @@ namespace { PCHECK(err, "failed to create thread"); } } - } - - private: - static void* ThreadProxy(void* arg) { - THolder<TParams> p((TParams*)arg); - - SetThrName(*p); - - return p->Proc(p->Data); - } - - private: - THolder<TParams> P_; - pthread_t H_; - }; - - #undef PCHECK - + } + + private: + static void* ThreadProxy(void* arg) { + THolder<TParams> p((TParams*)arg); + + SetThrName(*p); + + return p->Proc(p->Data); + } + + private: + THolder<TParams> P_; + pthread_t H_; + }; + + #undef PCHECK + using TThreadBase = TPosixThread; #endif - - template <class T> - static inline typename T::TValueType* Impl(T& t, const char* op, bool check = true) { - if (!t) { - ythrow yexception() << "can not " << op << " dead thread"; - } - - if (t->Running() != check) { - static const char* const msg[] = {"running", "not running"}; - - ythrow yexception() << "can not " << op << " " << msg[check] << " thread"; - } - - return t.Get(); - } -} - -class TThread::TImpl: public TThreadBase { -public: + + template <class T> + static inline typename T::TValueType* Impl(T& t, const char* op, bool check = true) { + if (!t) { + ythrow yexception() << "can not " << op << " dead thread"; + } + + if (t->Running() != check) { + static const char* const msg[] = {"running", "not running"}; + + ythrow yexception() << "can not " << op << " " << msg[check] << " thread"; + } + + return t.Get(); + } +} + +class TThread::TImpl: public TThreadBase { +public: inline TImpl(const TParams& params, THolder<TCallableBase> callable = {}) - : TThreadBase(params) + : TThreadBase(params) , Callable_(std::move(callable)) - { - } - + { + } + inline TId Id() const noexcept { - return ThreadIdHashFunction(SystemThreadId()); - } + return ThreadIdHashFunction(SystemThreadId()); + } static THolder<TImpl> Create(THolder<TCallableBase> callable) { TParams params(TCallableBase::ThreadWorker, callable.Get()); @@ -268,18 +268,18 @@ public: private: THolder<TCallableBase> Callable_; -}; - -TThread::TThread(const TParams& p) - : Impl_(new TImpl(p)) -{ -} - -TThread::TThread(TThreadProc threadProc, void* param) - : Impl_(new TImpl(TParams(threadProc, param))) -{ +}; + +TThread::TThread(const TParams& p) + : Impl_(new TImpl(p)) +{ } +TThread::TThread(TThreadProc threadProc, void* param) + : Impl_(new TImpl(TParams(threadProc, param))) +{ +} + TThread::TThread(TPrivateCtor, THolder<TCallableBase> callable) : Impl_(TImpl::Create(std::move(callable))) { @@ -287,13 +287,13 @@ TThread::TThread(TPrivateCtor, THolder<TCallableBase> callable) TThread::~TThread() { Join(); -} - +} + void TThread::Start() { - Impl(Impl_, "start", false)->Start(); -} - -void* TThread::Join() { + Impl(Impl_, "start", false)->Start(); +} + +void* TThread::Join() { if (Running()) { void* ret = Impl_->Join(); @@ -301,33 +301,33 @@ void* TThread::Join() { return ret; } - + return nullptr; } -void TThread::Detach() { - if (Running()) { - Impl_->Detach(); - Impl_.Destroy(); - } -} - +void TThread::Detach() { + if (Running()) { + Impl_->Detach(); + Impl_.Destroy(); + } +} + bool TThread::Running() const noexcept { return Impl_ && Impl_->Running(); -} - +} + TThread::TId TThread::Id() const noexcept { - if (Running()) { - return Impl_->Id(); - } - - return ImpossibleThreadId(); -} - + if (Running()) { + return Impl_->Id(); + } + + return ImpossibleThreadId(); +} + TThread::TId TThread::CurrentThreadId() noexcept { - return SystemCurrentThreadId(); -} - + return SystemCurrentThreadId(); +} + TThread::TId TThread::CurrentThreadNumericId() noexcept { #if defined(_win_) return GetCurrentThreadId(); @@ -353,61 +353,61 @@ TThread::TId TThread::CurrentThreadNumericId() noexcept { } TThread::TId TThread::ImpossibleThreadId() noexcept { - return Max<TThread::TId>(); -} + return Max<TThread::TId>(); +} namespace { - template <class T> + template <class T> static void* ThreadProcWrapper(void* param) { - return reinterpret_cast<T*>(param)->ThreadProc(); - } + return reinterpret_cast<T*>(param)->ThreadProc(); + } } ISimpleThread::ISimpleThread(size_t stackSize) : TThread(TParams(ThreadProcWrapper<ISimpleThread>, reinterpret_cast<void*>(this), stackSize)) { } - -#if defined(_MSC_VER) - // This beautiful piece of code is borrowed from - // http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - - // - // Usage: WindowsCurrentSetThreadName (-1, "MainThread"); - // - #include <windows.h> - #include <processthreadsapi.h> - -const DWORD MS_VC_EXCEPTION = 0x406D1388; - - #pragma pack(push, 8) -typedef struct tagTHREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. -} THREADNAME_INFO; - #pragma pack(pop) - -static void WindowsCurrentSetThreadName(DWORD dwThreadID, const char* threadName) { - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); - } __except (EXCEPTION_EXECUTE_HANDLER) { - } -} -#endif - + +#if defined(_MSC_VER) + // This beautiful piece of code is borrowed from + // http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx + + // + // Usage: WindowsCurrentSetThreadName (-1, "MainThread"); + // + #include <windows.h> + #include <processthreadsapi.h> + +const DWORD MS_VC_EXCEPTION = 0x406D1388; + + #pragma pack(push, 8) +typedef struct tagTHREADNAME_INFO { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; + #pragma pack(pop) + +static void WindowsCurrentSetThreadName(DWORD dwThreadID, const char* threadName) { + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } +} +#endif + #if defined(_win_) namespace { struct TWinThreadDescrAPI { TWinThreadDescrAPI() - : Kernel32Dll("kernel32.dll") + : Kernel32Dll("kernel32.dll") , SetThreadDescription((TSetThreadDescription)Kernel32Dll.SymOptional("SetThreadDescription")) , GetThreadDescription((TGetThreadDescription)Kernel32Dll.SymOptional("GetThreadDescription")) { @@ -435,8 +435,8 @@ namespace { return WideToUTF8((const wchar16*)wideName); } - typedef HRESULT(__cdecl* TSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription); - typedef HRESULT(__cdecl* TGetThreadDescription)(HANDLE hThread, PWSTR* ppszThreadDescription); + typedef HRESULT(__cdecl* TSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription); + typedef HRESULT(__cdecl* TGetThreadDescription)(HANDLE hThread, PWSTR* ppszThreadDescription); TDynamicLibrary Kernel32Dll; TSetThreadDescription SetThreadDescription; @@ -446,29 +446,29 @@ namespace { #endif // _win_ void TThread::SetCurrentThreadName(const char* name) { - (void)name; - -#if defined(_freebsd_) - pthread_t thread = pthread_self(); + (void)name; + +#if defined(_freebsd_) + pthread_t thread = pthread_self(); pthread_set_name_np(thread, name); -#elif defined(_linux_) +#elif defined(_linux_) prctl(PR_SET_NAME, name, 0, 0, 0); -#elif defined(_darwin_) +#elif defined(_darwin_) pthread_setname_np(name); #elif defined(_win_) auto api = Singleton<TWinThreadDescrAPI>(); if (api->HasAPI()) { api->SetDescr(name); } else { - #if defined(_MSC_VER) + #if defined(_MSC_VER) WindowsCurrentSetThreadName(DWORD(-1), name); - #endif + #endif } -#else -// no idea -#endif // OS -} - +#else +// no idea +#endif // OS +} + TString TThread::CurrentThreadName() { #if defined(_freebsd_) // TODO: check pthread_get_name_np API availability @@ -494,7 +494,7 @@ TString TThread::CurrentThreadName() { } return {}; #else -// no idea +// no idea #endif // OS return {}; @@ -510,37 +510,37 @@ bool TThread::CanGetCurrentThreadName() { #endif // OS } -TCurrentThreadLimits::TCurrentThreadLimits() noexcept - : StackBegin(nullptr) - , StackLength(0) -{ +TCurrentThreadLimits::TCurrentThreadLimits() noexcept + : StackBegin(nullptr) + , StackLength(0) +{ #if defined(_linux_) || defined(_cygwin_) || defined(_freebsd_) - pthread_attr_t attr; - pthread_attr_init(&attr); - - #if defined(_linux_) || defined(_cygwin_) - Y_VERIFY(pthread_getattr_np(pthread_self(), &attr) == 0, "pthread_getattr failed"); - #else + pthread_attr_t attr; + pthread_attr_init(&attr); + + #if defined(_linux_) || defined(_cygwin_) + Y_VERIFY(pthread_getattr_np(pthread_self(), &attr) == 0, "pthread_getattr failed"); + #else Y_VERIFY(pthread_attr_get_np(pthread_self(), &attr) == 0, "pthread_attr_get_np failed"); - #endif - pthread_attr_getstack(&attr, (void**)&StackBegin, &StackLength); - pthread_attr_destroy(&attr); - -#elif defined(_darwin_) - StackBegin = pthread_get_stackaddr_np(pthread_self()); - StackLength = pthread_get_stacksize_np(pthread_self()); -#elif defined(_MSC_VER) - - #if _WIN32_WINNT >= _WIN32_WINNT_WIN8 - ULONG_PTR b = 0; - ULONG_PTR e = 0; - + #endif + pthread_attr_getstack(&attr, (void**)&StackBegin, &StackLength); + pthread_attr_destroy(&attr); + +#elif defined(_darwin_) + StackBegin = pthread_get_stackaddr_np(pthread_self()); + StackLength = pthread_get_stacksize_np(pthread_self()); +#elif defined(_MSC_VER) + + #if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + ULONG_PTR b = 0; + ULONG_PTR e = 0; + GetCurrentThreadStackLimits(&b, &e); + + StackBegin = (const void*)b; + StackLength = e - b; - StackBegin = (const void*)b; - StackLength = e - b; - - #else + #else // Copied from https://github.com/llvm-mirror/compiler-rt/blob/release_40/lib/sanitizer_common/sanitizer_win.cc#L91 void* place_on_stack = alloca(16); MEMORY_BASIC_INFORMATION memory_info; @@ -549,9 +549,9 @@ TCurrentThreadLimits::TCurrentThreadLimits() noexcept StackBegin = memory_info.AllocationBase; StackLength = static_cast<const char*>(memory_info.BaseAddress) + memory_info.RegionSize - static_cast<const char*>(StackBegin); - #endif + #endif -#else - #error port me -#endif -} +#else + #error port me +#endif +} diff --git a/util/system/thread.h b/util/system/thread.h index a6e8abdb5b..15ced7295d 100644 --- a/util/system/thread.h +++ b/util/system/thread.h @@ -6,80 +6,80 @@ #include <util/generic/ptr.h> #include <util/generic/string.h> - + #include "defaults.h" #include "progname.h" bool SetHighestThreadPriority(); -class TThread { +class TThread { template <typename Callable> struct TCallableParams; struct TPrivateCtor {}; -public: +public: using TThreadProc = void* (*)(void*); using TId = size_t; - - struct TParams { - TThreadProc Proc; - void* Data; - size_t StackSize; - void* StackPointer; + + struct TParams { + TThreadProc Proc; + void* Data; + size_t StackSize; + void* StackPointer; // See comments for `SetCurrentThreadName` TString Name = GetProgramName(); - inline TParams() + inline TParams() : Proc(nullptr) , Data(nullptr) - , StackSize(0) - , StackPointer(nullptr) - { - } - - inline TParams(TThreadProc proc, void* data) - : Proc(proc) - , Data(data) - , StackSize(0) - , StackPointer(nullptr) - { - } - - inline TParams(TThreadProc proc, void* data, size_t stackSize) - : Proc(proc) - , Data(data) - , StackSize(stackSize) - , StackPointer(nullptr) - { - } - + , StackSize(0) + , StackPointer(nullptr) + { + } + + inline TParams(TThreadProc proc, void* data) + : Proc(proc) + , Data(data) + , StackSize(0) + , StackPointer(nullptr) + { + } + + inline TParams(TThreadProc proc, void* data, size_t stackSize) + : Proc(proc) + , Data(data) + , StackSize(stackSize) + , StackPointer(nullptr) + { + } + inline TParams& SetName(const TString& name) noexcept { - Name = name; - - return *this; - } - + Name = name; + + return *this; + } + inline TParams& SetStackSize(size_t size) noexcept { - StackSize = size; - - return *this; - } - + StackSize = size; + + return *this; + } + inline TParams& SetStackPointer(void* ptr) noexcept { - StackPointer = ptr; - - return *this; - } - }; - - TThread(const TParams& params); - TThread(TThreadProc threadProc, void* param); - + StackPointer = ptr; + + return *this; + } + }; + + TThread(const TParams& params); + TThread(TThreadProc threadProc, void* param); + template <typename Callable> TThread(Callable&& callable) : TThread(TPrivateCtor{}, - MakeHolder<TCallableParams<Callable>>(std::forward<Callable>(callable))) - { + MakeHolder<TCallableParams<Callable>>(std::forward<Callable>(callable))) + { } TThread(TParams&& params) @@ -93,14 +93,14 @@ public: } ~TThread(); - - void Start(); - - void* Join(); - void Detach(); + + void Start(); + + void* Join(); + void Detach(); bool Running() const noexcept; TId Id() const noexcept; - + static TId ImpossibleThreadId() noexcept; static TId CurrentThreadId() noexcept; @@ -117,7 +117,7 @@ public: // `CurrentThreadName` to return the same name as `name` make sure it's not longer than 15 // symbols. static void SetCurrentThreadName(const char* name); - + // NOTE: Will return empty string where CanGetCurrentThreadName() returns false. static TString CurrentThreadName(); @@ -125,7 +125,7 @@ public: // Will return true for Darwin, Linux or fresh Windows 10. static bool CanGetCurrentThreadName(); -private: +private: struct TCallableBase { virtual ~TCallableBase() = default; virtual void run() = 0; @@ -154,21 +154,21 @@ private: private: class TImpl; - THolder<TImpl> Impl_; + THolder<TImpl> Impl_; }; class ISimpleThread: public TThread { -public: +public: ISimpleThread(size_t stackSize = 0); virtual ~ISimpleThread() = default; virtual void* ThreadProc() = 0; }; - -struct TCurrentThreadLimits { - TCurrentThreadLimits() noexcept; - - const void* StackBegin; - size_t StackLength; -}; + +struct TCurrentThreadLimits { + TCurrentThreadLimits() noexcept; + + const void* StackBegin; + size_t StackLength; +}; diff --git a/util/system/thread.i b/util/system/thread.i index 8cba505473..9c24e600a2 100644 --- a/util/system/thread.i +++ b/util/system/thread.i @@ -1,52 +1,52 @@ -//do not use directly +//do not use directly #pragma once -#include "platform.h" +#include "platform.h" -#if defined(_win_) +#if defined(_win_) #include "winint.h" - #include <process.h> - - typedef HANDLE THREADHANDLE; -#else - #include <pthread.h> - #include <sched.h> - #include <errno.h> - #include <string.h> - - typedef pthread_t THREADHANDLE; -#endif - -#if defined(_freebsd_) - #include <pthread_np.h> -#elif defined(_linux_) - #include <sys/prctl.h> -#endif - -#include <util/digest/numeric.h> + #include <process.h> + + typedef HANDLE THREADHANDLE; +#else + #include <pthread.h> + #include <sched.h> + #include <errno.h> + #include <string.h> + + typedef pthread_t THREADHANDLE; +#endif + +#if defined(_freebsd_) + #include <pthread_np.h> +#elif defined(_linux_) + #include <sys/prctl.h> +#endif + +#include <util/digest/numeric.h> static inline size_t SystemCurrentThreadIdImpl() noexcept { - #if defined(_unix_) - return (size_t)pthread_self(); - #elif defined(_win_) - return (size_t)GetCurrentThreadId(); - #else - #error todo - #endif -} - -template <class T> + #if defined(_unix_) + return (size_t)pthread_self(); + #elif defined(_win_) + return (size_t)GetCurrentThreadId(); + #else + #error todo + #endif +} + +template <class T> static inline T ThreadIdHashFunction(T t) noexcept { - /* - * we must permute threadid bits, because some strange platforms(such Linux) - * have strange threadid numeric properties + /* + * we must permute threadid bits, because some strange platforms(such Linux) + * have strange threadid numeric properties * * Because they are alligned pointers to pthread_t rather that tid. * Currently there is no way to get tid without syscall (slightly slower) * (pthread_getthreadid_np is not implemeted in glibc/musl for some reason). - */ - return IntHash(t); -} - + */ + return IntHash(t); +} + static inline size_t SystemCurrentThreadId() noexcept { - return ThreadIdHashFunction(SystemCurrentThreadIdImpl()); -} + return ThreadIdHashFunction(SystemCurrentThreadIdImpl()); +} diff --git a/util/system/thread_ut.cpp b/util/system/thread_ut.cpp index d820898fd5..be610bc0ea 100644 --- a/util/system/thread_ut.cpp +++ b/util/system/thread_ut.cpp @@ -1,60 +1,60 @@ -#include "thread.h" - +#include "thread.h" + #include <library/cpp/testing/unittest/registar.h> - + #include <atomic> Y_UNIT_TEST_SUITE(TSysThreadTest) { - struct TIdTester { - inline TIdTester() + struct TIdTester { + inline TIdTester() : Thr(nullptr) - , Cur(0) - , Real(0) - { - } - - static inline void* DoRun(void* ptr) { - ((TIdTester*)ptr)->Run(); - + , Cur(0) + , Real(0) + { + } + + static inline void* DoRun(void* ptr) { + ((TIdTester*)ptr)->Run(); + return nullptr; - } - - inline void Run() { - Cur = TThread::CurrentThreadId(); - Real = Thr->Id(); + } + + inline void Run() { + Cur = TThread::CurrentThreadId(); + Real = Thr->Id(); Numeric = TThread::CurrentThreadNumericId(); - } - - TThread* Thr; - TThread::TId Cur; - TThread::TId Real; + } + + TThread* Thr; + TThread::TId Cur; + TThread::TId Real; TThread::TId Numeric; - }; - + }; + Y_UNIT_TEST(TestThreadId) { - TIdTester tst; - TThread thr(tst.DoRun, &tst); - - tst.Thr = &thr; - - thr.Start(); - thr.Join(); - - UNIT_ASSERT_EQUAL(tst.Cur, tst.Real); - UNIT_ASSERT(tst.Cur != 0); + TIdTester tst; + TThread thr(tst.DoRun, &tst); + + tst.Thr = &thr; + + thr.Start(); + thr.Join(); + + UNIT_ASSERT_EQUAL(tst.Cur, tst.Real); + UNIT_ASSERT(tst.Cur != 0); UNIT_ASSERT(tst.Numeric != 0); UNIT_ASSERT(tst.Numeric != tst.Real); - } - - void* ThreadProc(void*) { + } + + void* ThreadProc(void*) { TThread::SetCurrentThreadName("CurrentThreadSetNameTest"); return nullptr; - } - - void* ThreadProc2(void*) { + } + + void* ThreadProc2(void*) { return nullptr; - } - + } + void* ThreadProc3(void*) { const auto name = TThread::CurrentThreadName(); Y_FAKE_READ(name); @@ -107,18 +107,18 @@ Y_UNIT_TEST_SUITE(TSysThreadTest) { Y_UNIT_TEST(TestSetThreadName) { TThread thread(&ThreadProc, nullptr); - // just check it doesn't crash - thread.Start(); - thread.Join(); - } - + // just check it doesn't crash + thread.Start(); + thread.Join(); + } + Y_UNIT_TEST(TestSetThreadName2) { TThread thread(TThread::TParams(&ThreadProc, nullptr, 0).SetName("XXX")); - - thread.Start(); - thread.Join(); - } - + + thread.Start(); + thread.Join(); + } + Y_UNIT_TEST(TestGetThreadName) { TThread thread(&ThreadProc3, nullptr); thread.Start(); @@ -139,45 +139,45 @@ Y_UNIT_TEST_SUITE(TSysThreadTest) { Y_UNIT_TEST(TestDoubleJoin) { TThread thread(&ThreadProc, nullptr); - - thread.Start(); - thread.Join(); - + + thread.Start(); + thread.Join(); + UNIT_ASSERT_EQUAL(thread.Join(), nullptr); - } - + } + Y_UNIT_TEST(TestDoubleStart) { TThread thread(&ThreadProc, nullptr); - - thread.Start(); - UNIT_ASSERT_EXCEPTION(thread.Start(), yexception); - thread.Join(); - } - + + thread.Start(); + UNIT_ASSERT_EXCEPTION(thread.Start(), yexception); + thread.Join(); + } + Y_UNIT_TEST(TestNoStart) { TThread thread(&ThreadProc, nullptr); - } - + } + Y_UNIT_TEST(TestNoStartJoin) { TThread thread(&ThreadProc, nullptr); - + UNIT_ASSERT_EQUAL(thread.Join(), nullptr); - } - + } + Y_UNIT_TEST(TestStackPointer) { - TArrayHolder<char> buf(new char[64000]); + TArrayHolder<char> buf(new char[64000]); TThread thr(TThread::TParams(ThreadProc2, nullptr).SetStackPointer(buf.Get()).SetStackSize(64000)); - - thr.Start(); - UNIT_ASSERT_VALUES_EQUAL(thr.Join(), nullptr); - } - + + thr.Start(); + UNIT_ASSERT_VALUES_EQUAL(thr.Join(), nullptr); + } + Y_UNIT_TEST(TestStackLimits) { - TCurrentThreadLimits sl; - - UNIT_ASSERT(sl.StackBegin); - UNIT_ASSERT(sl.StackLength > 0); - } + TCurrentThreadLimits sl; + + UNIT_ASSERT(sl.StackBegin); + UNIT_ASSERT(sl.StackLength > 0); + } Y_UNIT_TEST(TestFunc) { std::atomic_bool flag = {false}; @@ -206,7 +206,7 @@ Y_UNIT_TEST_SUITE(TSysThreadTest) { Y_UNIT_TEST(TestCallable) { std::atomic_bool flag = {false}; - struct TCallable: TMoveOnly { + struct TCallable: TMoveOnly { std::atomic_bool* Flag_; TCallable(std::atomic_bool* flag) @@ -226,4 +226,4 @@ Y_UNIT_TEST_SUITE(TSysThreadTest) { UNIT_ASSERT_VALUES_EQUAL(thread.Join(), nullptr); UNIT_ASSERT(flag); } -}; +}; diff --git a/util/system/tls.cpp b/util/system/tls.cpp index c2f1a04a14..152e1434a1 100644 --- a/util/system/tls.cpp +++ b/util/system/tls.cpp @@ -1,260 +1,260 @@ -#include "tls.h" -#include "mutex.h" -#include "thread.h" - -#include <util/generic/set.h> -#include <util/generic/hash.h> -#include <util/generic/intrlist.h> -#include <util/generic/singleton.h> +#include "tls.h" +#include "mutex.h" +#include "thread.h" + +#include <util/generic/set.h> +#include <util/generic/hash.h> +#include <util/generic/intrlist.h> +#include <util/generic/singleton.h> #include <util/generic/vector.h> -#if defined(_unix_) - #include <pthread.h> -#endif - -using namespace NTls; - -namespace { - static inline TAtomicBase AcquireKey() { - static TAtomic cur; - - return AtomicIncrement(cur) - (TAtomicBase)1; - } - - class TGenericTlsBase { - public: +#if defined(_unix_) + #include <pthread.h> +#endif + +using namespace NTls; + +namespace { + static inline TAtomicBase AcquireKey() { + static TAtomic cur; + + return AtomicIncrement(cur) - (TAtomicBase)1; + } + + class TGenericTlsBase { + public: using TSmallKey = size_t; - - class TPerThreadStorage { - public: - struct TKey: public TNonCopyable { - inline TKey(TDtor dtor) - : Key(AcquireKey()) - , Dtor(dtor) - { - } - - TSmallKey Key; - TDtor Dtor; - }; - - class TStoredValue: public TIntrusiveListItem<TStoredValue> { - public: - inline TStoredValue(const TKey* key) + + class TPerThreadStorage { + public: + struct TKey: public TNonCopyable { + inline TKey(TDtor dtor) + : Key(AcquireKey()) + , Dtor(dtor) + { + } + + TSmallKey Key; + TDtor Dtor; + }; + + class TStoredValue: public TIntrusiveListItem<TStoredValue> { + public: + inline TStoredValue(const TKey* key) : Data_(nullptr) - , Dtor_(key->Dtor) - { - } - + , Dtor_(key->Dtor) + { + } + inline ~TStoredValue() { - if (Dtor_ && Data_) { - Dtor_(Data_); - } - } - + if (Dtor_ && Data_) { + Dtor_(Data_); + } + } + inline void Set(void* ptr) noexcept { - Data_ = ptr; - } - + Data_ = ptr; + } + inline void* Get() const noexcept { - return Data_; - } - - private: - void* Data_; - TDtor Dtor_; - }; - - inline TStoredValue* Value(const TKey* key) { - TStoredValue*& ret = *ValuePtr((size_t)key->Key); - - if (!ret) { - THolder<TStoredValue> sv(new TStoredValue(key)); - - Storage_.PushFront(sv.Get()); - ret = sv.Release(); - } - - return ret; - } - - inline TStoredValue** ValuePtr(size_t idx) { - // do not grow vector too much - if (idx < 10000) { - if (idx >= Values_.size()) { - Values_.resize(idx + 1); - } - - return &Values_[idx]; - } - - return &FarValues_[idx]; - } - - private: + return Data_; + } + + private: + void* Data_; + TDtor Dtor_; + }; + + inline TStoredValue* Value(const TKey* key) { + TStoredValue*& ret = *ValuePtr((size_t)key->Key); + + if (!ret) { + THolder<TStoredValue> sv(new TStoredValue(key)); + + Storage_.PushFront(sv.Get()); + ret = sv.Release(); + } + + return ret; + } + + inline TStoredValue** ValuePtr(size_t idx) { + // do not grow vector too much + if (idx < 10000) { + if (idx >= Values_.size()) { + Values_.resize(idx + 1); + } + + return &Values_[idx]; + } + + return &FarValues_[idx]; + } + + private: TVector<TStoredValue*> Values_; THashMap<size_t, TStoredValue*> FarValues_; - TIntrusiveListWithAutoDelete<TStoredValue, TDelete> Storage_; - }; - - inline TPerThreadStorage* MyStorage() { + TIntrusiveListWithAutoDelete<TStoredValue, TDelete> Storage_; + }; + + inline TPerThreadStorage* MyStorage() { #if defined(Y_HAVE_FAST_POD_TLS) - Y_POD_STATIC_THREAD(TPerThreadStorage*) - my(nullptr); - - if (!my) { - my = MyStorageSlow(); - } - - return my; -#else - return MyStorageSlow(); -#endif - } - - virtual TPerThreadStorage* MyStorageSlow() = 0; + Y_POD_STATIC_THREAD(TPerThreadStorage*) + my(nullptr); + + if (!my) { + my = MyStorageSlow(); + } + + return my; +#else + return MyStorageSlow(); +#endif + } + + virtual TPerThreadStorage* MyStorageSlow() = 0; virtual ~TGenericTlsBase() = default; - }; -} - -#if defined(_unix_) -namespace { - class TMasterTls: public TGenericTlsBase { - public: - inline TMasterTls() { + }; +} + +#if defined(_unix_) +namespace { + class TMasterTls: public TGenericTlsBase { + public: + inline TMasterTls() { Y_VERIFY(!pthread_key_create(&Key_, Dtor), "pthread_key_create failed"); - } - + } + inline ~TMasterTls() override { - //explicitly call dtor for main thread - Dtor(pthread_getspecific(Key_)); - + //explicitly call dtor for main thread + Dtor(pthread_getspecific(Key_)); + Y_VERIFY(!pthread_key_delete(Key_), "pthread_key_delete failed"); - } - - static inline TMasterTls* Instance() { - return SingletonWithPriority<TMasterTls, 1>(); - } - - private: + } + + static inline TMasterTls* Instance() { + return SingletonWithPriority<TMasterTls, 1>(); + } + + private: TPerThreadStorage* MyStorageSlow() override { - void* ret = pthread_getspecific(Key_); - - if (!ret) { - ret = new TPerThreadStorage(); - + void* ret = pthread_getspecific(Key_); + + if (!ret) { + ret = new TPerThreadStorage(); + Y_VERIFY(!pthread_setspecific(Key_, ret), "pthread_setspecific failed"); - } - - return (TPerThreadStorage*)ret; - } - - static void Dtor(void* ptr) { - delete (TPerThreadStorage*)ptr; - } - - private: - pthread_key_t Key_; - }; - + } + + return (TPerThreadStorage*)ret; + } + + static void Dtor(void* ptr) { + delete (TPerThreadStorage*)ptr; + } + + private: + pthread_key_t Key_; + }; + using TKeyDescriptor = TMasterTls::TPerThreadStorage::TKey; -} - -class TKey::TImpl: public TKeyDescriptor { -public: - inline TImpl(TDtor dtor) - : TKeyDescriptor(dtor) - { - } - - inline void* Get() const { - return TMasterTls::Instance()->MyStorage()->Value(this)->Get(); - } - - inline void Set(void* val) const { - TMasterTls::Instance()->MyStorage()->Value(this)->Set(val); - } - - static inline void Cleanup() { - } -}; -#else -namespace { - class TGenericTls: public TGenericTlsBase { - public: - virtual TPerThreadStorage* MyStorageSlow() { - auto lock = Guard(Lock_); - - { - TPTSRef& ret = Datas_[TThread::CurrentThreadId()]; - - if (!ret) { - ret.Reset(new TPerThreadStorage()); - } - - return ret.Get(); - } - } - +} + +class TKey::TImpl: public TKeyDescriptor { +public: + inline TImpl(TDtor dtor) + : TKeyDescriptor(dtor) + { + } + + inline void* Get() const { + return TMasterTls::Instance()->MyStorage()->Value(this)->Get(); + } + + inline void Set(void* val) const { + TMasterTls::Instance()->MyStorage()->Value(this)->Set(val); + } + + static inline void Cleanup() { + } +}; +#else +namespace { + class TGenericTls: public TGenericTlsBase { + public: + virtual TPerThreadStorage* MyStorageSlow() { + auto lock = Guard(Lock_); + + { + TPTSRef& ret = Datas_[TThread::CurrentThreadId()]; + + if (!ret) { + ret.Reset(new TPerThreadStorage()); + } + + return ret.Get(); + } + } + inline void Cleanup() noexcept { - with_lock (Lock_) { - Datas_.erase(TThread::CurrentThreadId()); - } - } - - static inline TGenericTls* Instance() { - return SingletonWithPriority<TGenericTls, 1>(); - } - - private: + with_lock (Lock_) { + Datas_.erase(TThread::CurrentThreadId()); + } + } + + static inline TGenericTls* Instance() { + return SingletonWithPriority<TGenericTls, 1>(); + } + + private: using TPTSRef = THolder<TPerThreadStorage>; - TMutex Lock_; + TMutex Lock_; THashMap<TThread::TId, TPTSRef> Datas_; - }; -} - -class TKey::TImpl { -public: - inline TImpl(TDtor dtor) - : Key_(dtor) - { - } - - inline void* Get() { - return TGenericTls::Instance()->MyStorage()->Value(&Key_)->Get(); - } - - inline void Set(void* ptr) { - TGenericTls::Instance()->MyStorage()->Value(&Key_)->Set(ptr); - } - - static inline void Cleanup() { - TGenericTls::Instance()->Cleanup(); - } - -private: - TGenericTls::TPerThreadStorage::TKey Key_; -}; -#endif - -TKey::TKey(TDtor dtor) - : Impl_(new TImpl(dtor)) -{ + }; +} + +class TKey::TImpl { +public: + inline TImpl(TDtor dtor) + : Key_(dtor) + { + } + + inline void* Get() { + return TGenericTls::Instance()->MyStorage()->Value(&Key_)->Get(); + } + + inline void Set(void* ptr) { + TGenericTls::Instance()->MyStorage()->Value(&Key_)->Set(ptr); + } + + static inline void Cleanup() { + TGenericTls::Instance()->Cleanup(); + } + +private: + TGenericTls::TPerThreadStorage::TKey Key_; +}; +#endif + +TKey::TKey(TDtor dtor) + : Impl_(new TImpl(dtor)) +{ } TKey::TKey(TKey&&) noexcept = default; TKey::~TKey() = default; - -void* TKey::Get() const { - return Impl_->Get(); -} - -void TKey::Set(void* ptr) const { - Impl_->Set(ptr); -} - + +void* TKey::Get() const { + return Impl_->Get(); +} + +void TKey::Set(void* ptr) const { + Impl_->Set(ptr); +} + void TKey::Cleanup() noexcept { - TImpl::Cleanup(); -} + TImpl::Cleanup(); +} diff --git a/util/system/tls.h b/util/system/tls.h index 3c4f56dbeb..34e0ba6db7 100644 --- a/util/system/tls.h +++ b/util/system/tls.h @@ -1,22 +1,22 @@ #pragma once -#include "defaults.h" - +#include "defaults.h" + #include <util/generic/ptr.h> #include <util/generic/noncopyable.h> -#include <new> - +#include <new> + #if defined(_darwin_) - #define Y_DISABLE_THRKEY_OPTIMIZATION + #define Y_DISABLE_THRKEY_OPTIMIZATION #endif - -#if defined(_arm_) && defined(_linux_) - #define Y_DISABLE_THRKEY_OPTIMIZATION -#endif - + +#if defined(_arm_) && defined(_linux_) + #define Y_DISABLE_THRKEY_OPTIMIZATION +#endif + #if defined(__GNUC__) && defined(__ANDROID__) && defined(__i686__) // https://st.yandex-team.ru/DEVTOOLS-3352 - #define Y_DISABLE_THRKEY_OPTIMIZATION + #define Y_DISABLE_THRKEY_OPTIMIZATION #endif /** @@ -127,53 +127,53 @@ // gcc and msvc support automatic tls for POD types #if defined(Y_DISABLE_THRKEY_OPTIMIZATION) -// nothing to do -#elif defined(__clang__) - #define Y_POD_THREAD(T) thread_local T - #define Y_POD_STATIC_THREAD(T) static thread_local T -#elif defined(__GNUC__) && !defined(_cygwin_) && !defined(_arm_) && !defined(__IOS_SIMULATOR__) - #define Y_POD_THREAD(T) __thread T - #define Y_POD_STATIC_THREAD(T) static __thread T -// msvc doesn't support __declspec(thread) in dlls, loaded manually (via LoadLibrary) -#elif (defined(_MSC_VER) && !defined(_WINDLL)) || defined(_arm_) - #define Y_POD_THREAD(T) __declspec(thread) T - #define Y_POD_STATIC_THREAD(T) __declspec(thread) static T -#endif +// nothing to do +#elif defined(__clang__) + #define Y_POD_THREAD(T) thread_local T + #define Y_POD_STATIC_THREAD(T) static thread_local T +#elif defined(__GNUC__) && !defined(_cygwin_) && !defined(_arm_) && !defined(__IOS_SIMULATOR__) + #define Y_POD_THREAD(T) __thread T + #define Y_POD_STATIC_THREAD(T) static __thread T +// msvc doesn't support __declspec(thread) in dlls, loaded manually (via LoadLibrary) +#elif (defined(_MSC_VER) && !defined(_WINDLL)) || defined(_arm_) + #define Y_POD_THREAD(T) __declspec(thread) T + #define Y_POD_STATIC_THREAD(T) __declspec(thread) static T +#endif #if !defined(Y_POD_THREAD) || !defined(Y_POD_STATIC_THREAD) - #define Y_POD_THREAD(T) Y_THREAD(T) - #define Y_POD_STATIC_THREAD(T) Y_STATIC_THREAD(T) -#else - #define Y_HAVE_FAST_POD_TLS + #define Y_POD_THREAD(T) Y_THREAD(T) + #define Y_POD_STATIC_THREAD(T) Y_STATIC_THREAD(T) +#else + #define Y_HAVE_FAST_POD_TLS #endif - -namespace NPrivate { - void FillWithTrash(void* ptr, size_t len); -} - -namespace NTls { + +namespace NPrivate { + void FillWithTrash(void* ptr, size_t len); +} + +namespace NTls { using TDtor = void (*)(void*); - - class TKey { + + class TKey { public: - TKey(TDtor dtor); + TKey(TDtor dtor); TKey(TKey&&) noexcept; ~TKey(); - - void* Get() const; - void Set(void* ptr) const; + + void* Get() const; + void Set(void* ptr) const; static void Cleanup() noexcept; private: - class TImpl; - THolder<TImpl> Impl_; + class TImpl; + THolder<TImpl> Impl_; }; struct TCleaner { inline ~TCleaner() { - TKey::Cleanup(); - } + TKey::Cleanup(); + } }; template <class T> @@ -181,22 +181,22 @@ namespace NTls { class TConstructor { public: TConstructor() noexcept = default; - + virtual ~TConstructor() = default; - + virtual T* Construct(void* ptr) const = 0; }; - + class TDefaultConstructor: public TConstructor { public: ~TDefaultConstructor() override = default; - + T* Construct(void* ptr) const override { - //memset(ptr, 0, sizeof(T)); + //memset(ptr, 0, sizeof(T)); return ::new (ptr) T(); } }; - + template <class T1> class TCopyConstructor: public TConstructor { public: @@ -204,48 +204,48 @@ namespace NTls { : Value(value) { } - + ~TCopyConstructor() override = default; - + T* Construct(void* ptr) const override { return ::new (ptr) T(Value); } - + private: T1 Value; }; - + public: - inline TValue() - : Constructor_(new TDefaultConstructor()) - , Key_(Dtor) - { + inline TValue() + : Constructor_(new TDefaultConstructor()) + , Key_(Dtor) + { } - - template <class T1> - inline TValue(const T1& value) - : Constructor_(new TCopyConstructor<T1>(value)) - , Key_(Dtor) - { + + template <class T1> + inline TValue(const T1& value) + : Constructor_(new TCopyConstructor<T1>(value)) + , Key_(Dtor) + { } - - template <class T1> - inline T& operator=(const T1& val) { + + template <class T1> + inline T& operator=(const T1& val) { return Get() = val; } - - inline operator const T&() const { + + inline operator const T&() const { return Get(); } - - inline operator T&() { + + inline operator T&() { return Get(); } - inline const T& operator->() const { + inline const T& operator->() const { return Get(); } - + inline T& operator->() { return Get(); } @@ -258,50 +258,50 @@ namespace NTls { return GetPtr(); } - inline T& Get() const { + inline T& Get() const { return *GetPtr(); } inline T* GetPtr() const { - T* val = static_cast<T*>(Key_.Get()); - + T* val = static_cast<T*>(Key_.Get()); + if (!val) { - THolder<void> mem(::operator new(sizeof(T))); - THolder<T> newval(Constructor_->Construct(mem.Get())); - + THolder<void> mem(::operator new(sizeof(T))); + THolder<T> newval(Constructor_->Construct(mem.Get())); + Y_UNUSED(mem.Release()); - Key_.Set((void*)newval.Get()); - val = newval.Release(); + Key_.Set((void*)newval.Get()); + val = newval.Release(); } - + return val; } - + private: static void Dtor(void* ptr) { - THolder<void> mem(ptr); - - ((T*)ptr)->~T(); - ::NPrivate::FillWithTrash(ptr, sizeof(T)); + THolder<void> mem(ptr); + + ((T*)ptr)->~T(); + ::NPrivate::FillWithTrash(ptr, sizeof(T)); } - + private: - THolder<TConstructor> Constructor_; - TKey Key_; + THolder<TConstructor> Constructor_; + TKey Key_; }; } - -template <class T> + +template <class T> static inline T& TlsRef(NTls::TValue<T>& v) noexcept { - return v; -} - -template <class T> + return v; +} + +template <class T> static inline const T& TlsRef(const NTls::TValue<T>& v) noexcept { - return v; -} - -template <class T> + return v; +} + +template <class T> static inline T& TlsRef(T& v) noexcept { - return v; -} + return v; +} diff --git a/util/system/tls_ut.cpp b/util/system/tls_ut.cpp index e84d34b42a..3003fa1635 100644 --- a/util/system/tls_ut.cpp +++ b/util/system/tls_ut.cpp @@ -1,58 +1,58 @@ -#include "tls.h" -#include "thread.h" - +#include "tls.h" +#include "thread.h" + #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TTestTLS) { - struct X { - inline X() - : V(0) - { - } - - inline void Do() { - ++TlsRef(V); - } - - inline int Get() { - return TlsRef(V); - } - - Y_THREAD(int) - V; - }; - + struct X { + inline X() + : V(0) + { + } + + inline void Do() { + ++TlsRef(V); + } + + inline int Get() { + return TlsRef(V); + } + + Y_THREAD(int) + V; + }; + Y_UNIT_TEST(TestHugeSetup) { - TArrayHolder<X> x(new X[100000]); - + TArrayHolder<X> x(new X[100000]); + struct TThr: public ISimpleThread { - inline TThr(X* ptr) - : P(ptr) - { - } - + inline TThr(X* ptr) + : P(ptr) + { + } + void* ThreadProc() noexcept override { - for (size_t i = 0; i < 100000; ++i) { - P[i].Do(); - } - - return nullptr; - } - - X* P; - }; - - TThr thr1(x.Get()); - TThr thr2(x.Get()); - - thr1.Start(); - thr2.Start(); - - thr1.Join(); - thr2.Join(); - - for (size_t i = 0; i < 100000; ++i) { - UNIT_ASSERT_VALUES_EQUAL(x.Get()[i].Get(), 0); - } - } -} + for (size_t i = 0; i < 100000; ++i) { + P[i].Do(); + } + + return nullptr; + } + + X* P; + }; + + TThr thr1(x.Get()); + TThr thr2(x.Get()); + + thr1.Start(); + thr2.Start(); + + thr1.Join(); + thr2.Join(); + + for (size_t i = 0; i < 100000; ++i) { + UNIT_ASSERT_VALUES_EQUAL(x.Get()[i].Get(), 0); + } + } +} diff --git a/util/system/type_name.cpp b/util/system/type_name.cpp index 0377da4212..61bae26843 100644 --- a/util/system/type_name.cpp +++ b/util/system/type_name.cpp @@ -1,9 +1,9 @@ -#include "platform.h" +#include "platform.h" #include "demangle_impl.h" #ifdef __GNUC__ - #include <stdexcept> - #include <cxxabi.h> + #include <stdexcept> + #include <cxxabi.h> #endif #include "type_name.h" @@ -30,12 +30,12 @@ const char* NPrivate::TCppDemangler::Demangle(const char* name) { #else int status; TmpBuf_.Reset(__cxxabiv1::__cxa_demangle(name, nullptr, nullptr, &status)); - - if (!TmpBuf_) { + + if (!TmpBuf_) { return name; - } - - return TmpBuf_.Get(); + } + + return TmpBuf_.Get(); #endif } diff --git a/util/system/type_name_ut.cpp b/util/system/type_name_ut.cpp index 86597f4232..0eed1c9788 100644 --- a/util/system/type_name_ut.cpp +++ b/util/system/type_name_ut.cpp @@ -1,5 +1,5 @@ #include "type_name.h" - + #include <library/cpp/testing/unittest/registar.h> #include <util/generic/yexception.h> @@ -28,19 +28,19 @@ namespace NUtil::NTypeNameTest { virtual ~TRombicHead() = default; }; - class TRombicLeftArc: public virtual TRombicHead { + class TRombicLeftArc: public virtual TRombicHead { public: int x; virtual ~TRombicLeftArc() = default; }; - class TRombicRightArc: public virtual TRombicHead { + class TRombicRightArc: public virtual TRombicHead { public: int y; virtual ~TRombicRightArc() = default; }; - class TRombicTail: public virtual TRombicRightArc, TRombicLeftArc { + class TRombicTail: public virtual TRombicRightArc, TRombicLeftArc { public: virtual ~TRombicTail() = default; }; @@ -164,10 +164,10 @@ Y_UNIT_TEST_SUITE(TypeName) { } Y_UNIT_TEST(DistinguishPointerQualifiers) { - char* simplePtr = nullptr; - const char* constPtr = nullptr; - volatile char* volatilePtr = nullptr; - const volatile char* cvPtr = nullptr; + char* simplePtr = nullptr; + const char* constPtr = nullptr; + volatile char* volatilePtr = nullptr; + const volatile char* cvPtr = nullptr; #ifdef _MSC_VER UNIT_ASSERT_VALUES_EQUAL(TypeName(simplePtr), "char * __ptr64"); diff --git a/util/system/types.cpp b/util/system/types.cpp index 11cc72aee3..75dba24f61 100644 --- a/util/system/types.cpp +++ b/util/system/types.cpp @@ -1,18 +1,18 @@ -#include "types.h" - -#include <util/generic/typetraits.h> +#include "types.h" + +#include <util/generic/typetraits.h> #include <util/generic/typelist.h> - -static_assert(sizeof(ui8) == 1, "incorrect ui8 type"); -static_assert(sizeof(ui16) == 2, "incorrect ui16 type"); -static_assert(sizeof(ui32) == 4, "incorrect ui32 type"); -static_assert(sizeof(ui64) == 8, "incorrect ui64 type"); - -static_assert(sizeof(i8) == 1, "incorrect i8 type"); -static_assert(sizeof(i16) == 2, "incorrect i16 type"); -static_assert(sizeof(i32) == 4, "incorrect i32 type"); -static_assert(sizeof(i64) == 8, "incorrect i64 type"); - -static_assert(sizeof(size_t) == sizeof(ssize_t), "incorrect ssize_t"); - + +static_assert(sizeof(ui8) == 1, "incorrect ui8 type"); +static_assert(sizeof(ui16) == 2, "incorrect ui16 type"); +static_assert(sizeof(ui32) == 4, "incorrect ui32 type"); +static_assert(sizeof(ui64) == 8, "incorrect ui64 type"); + +static_assert(sizeof(i8) == 1, "incorrect i8 type"); +static_assert(sizeof(i16) == 2, "incorrect i16 type"); +static_assert(sizeof(i32) == 4, "incorrect i32 type"); +static_assert(sizeof(i64) == 8, "incorrect i64 type"); + +static_assert(sizeof(size_t) == sizeof(ssize_t), "incorrect ssize_t"); + static_assert(TTypeList<ui32, ui64>::THave<size_t>::value, "incorrect size_t"); diff --git a/util/system/types.h b/util/system/types.h index 12e68a6060..bf6ba1c6d0 100644 --- a/util/system/types.h +++ b/util/system/types.h @@ -1,119 +1,119 @@ -#pragma once - -// DO_NOT_STYLE - -#include "platform.h" - -#include <inttypes.h> - -typedef int8_t i8; -typedef int16_t i16; -typedef uint8_t ui8; -typedef uint16_t ui16; - +#pragma once + +// DO_NOT_STYLE + +#include "platform.h" + +#include <inttypes.h> + +typedef int8_t i8; +typedef int16_t i16; +typedef uint8_t ui8; +typedef uint16_t ui16; + typedef int yssize_t; #define PRIYSZT "d" #if defined(_darwin_) && defined(_32_) typedef unsigned long ui32; -typedef long i32; +typedef long i32; #else -typedef uint32_t ui32; -typedef int32_t i32; +typedef uint32_t ui32; +typedef int32_t i32; #endif - + #if defined(_darwin_) && defined(_64_) typedef unsigned long ui64; -typedef long i64; +typedef long i64; #else -typedef uint64_t ui64; -typedef int64_t i64; +typedef uint64_t ui64; +typedef int64_t i64; #endif - -#define LL(number) INT64_C(number) -#define ULL(number) UINT64_C(number) - + +#define LL(number) INT64_C(number) +#define ULL(number) UINT64_C(number) + // Macro for size_t and ptrdiff_t types -#if defined(_32_) - #if defined(_darwin_) - #define PRISZT "lu" - #undef PRIi32 - #define PRIi32 "li" - #undef SCNi32 - #define SCNi32 "li" - #undef PRId32 - #define PRId32 "li" - #undef SCNd32 - #define SCNd32 "li" - #undef PRIu32 - #define PRIu32 "lu" - #undef SCNu32 - #define SCNu32 "lu" - #undef PRIx32 - #define PRIx32 "lx" - #undef SCNx32 - #define SCNx32 "lx" - #elif !defined(_cygwin_) - #define PRISZT PRIu32 - #else - #define PRISZT "u" - #endif - #define SCNSZT SCNu32 - #define PRIPDT PRIi32 - #define SCNPDT SCNi32 - #define PRITMT PRIi32 - #define SCNTMT SCNi32 -#elif defined(_64_) - #if defined(_darwin_) - #define PRISZT "lu" - #undef PRIu64 - #define PRIu64 PRISZT - #undef PRIx64 - #define PRIx64 "lx" - #undef PRIX64 - #define PRIX64 "lX" - #undef PRId64 - #define PRId64 "ld" - #undef PRIi64 - #define PRIi64 "li" - #undef SCNi64 - #define SCNi64 "li" - #undef SCNu64 - #define SCNu64 "lu" - #undef SCNx64 - #define SCNx64 "lx" - #else - #define PRISZT PRIu64 - #endif - #define SCNSZT SCNu64 - #define PRIPDT PRIi64 - #define SCNPDT SCNi64 - #define PRITMT PRIi64 - #define SCNTMT SCNi64 -#else - #error "Unsupported platform" -#endif - +#if defined(_32_) + #if defined(_darwin_) + #define PRISZT "lu" + #undef PRIi32 + #define PRIi32 "li" + #undef SCNi32 + #define SCNi32 "li" + #undef PRId32 + #define PRId32 "li" + #undef SCNd32 + #define SCNd32 "li" + #undef PRIu32 + #define PRIu32 "lu" + #undef SCNu32 + #define SCNu32 "lu" + #undef PRIx32 + #define PRIx32 "lx" + #undef SCNx32 + #define SCNx32 "lx" + #elif !defined(_cygwin_) + #define PRISZT PRIu32 + #else + #define PRISZT "u" + #endif + #define SCNSZT SCNu32 + #define PRIPDT PRIi32 + #define SCNPDT SCNi32 + #define PRITMT PRIi32 + #define SCNTMT SCNi32 +#elif defined(_64_) + #if defined(_darwin_) + #define PRISZT "lu" + #undef PRIu64 + #define PRIu64 PRISZT + #undef PRIx64 + #define PRIx64 "lx" + #undef PRIX64 + #define PRIX64 "lX" + #undef PRId64 + #define PRId64 "ld" + #undef PRIi64 + #define PRIi64 "li" + #undef SCNi64 + #define SCNi64 "li" + #undef SCNu64 + #define SCNu64 "lu" + #undef SCNx64 + #define SCNx64 "lx" + #else + #define PRISZT PRIu64 + #endif + #define SCNSZT SCNu64 + #define PRIPDT PRIi64 + #define SCNPDT SCNi64 + #define PRITMT PRIi64 + #define SCNTMT SCNi64 +#else + #error "Unsupported platform" +#endif + // SUPERLONG #if !defined(DONT_USE_SUPERLONG) && !defined(SUPERLONG_MAX) - #define SUPERLONG_MAX ~LL(0) + #define SUPERLONG_MAX ~LL(0) typedef i64 SUPERLONG; #endif - -// UNICODE + +// UNICODE #ifdef __cplusplus -// UCS-2, native byteorder +// UCS-2, native byteorder typedef char16_t wchar16; -// internal symbol type: UTF-16LE -typedef wchar16 TChar; +// internal symbol type: UTF-16LE +typedef wchar16 TChar; typedef char32_t wchar32; #endif - -#if defined(_MSC_VER) - #include <basetsd.h> -typedef SSIZE_T ssize_t; - #define HAVE_SSIZE_T 1 - #include <wchar.h> -#endif - -#include <sys/types.h> + +#if defined(_MSC_VER) + #include <basetsd.h> +typedef SSIZE_T ssize_t; + #define HAVE_SSIZE_T 1 + #include <wchar.h> +#endif + +#include <sys/types.h> diff --git a/util/system/unaligned_mem.cpp b/util/system/unaligned_mem.cpp index b683ea9aae..a1d635196f 100644 --- a/util/system/unaligned_mem.cpp +++ b/util/system/unaligned_mem.cpp @@ -1 +1 @@ -#include "unaligned_mem.h" +#include "unaligned_mem.h" diff --git a/util/system/unaligned_mem.h b/util/system/unaligned_mem.h index 4b84686f2f..b3c674e33e 100644 --- a/util/system/unaligned_mem.h +++ b/util/system/unaligned_mem.h @@ -1,28 +1,28 @@ -#pragma once - -#include "defaults.h" +#pragma once + +#include "defaults.h" #include "yassert.h" - -#include <string.h> + +#include <string.h> #include <type_traits> - + // The following code used to have smart tricks assuming that unaligned reads and writes are OK on x86. This assumption // is wrong because compiler may emit alignment-sensitive x86 instructions e.g. movaps. See IGNIETFERRO-735. -template <class T> +template <class T> inline T ReadUnaligned(const void* from) noexcept { - T ret; - memcpy(&ret, from, sizeof(T)); - return ret; -} - + T ret; + memcpy(&ret, from, sizeof(T)); + return ret; +} + // std::remove_reference_t for non-deduced context to prevent such code to blow below: // ui8 first = f(); ui8 second = g(); // WriteUnaligned(to, first - second) (int will be deduced) -template <class T> +template <class T> inline void WriteUnaligned(void* to, const std::remove_reference_t<T>& t) noexcept { - memcpy(to, &t, sizeof(T)); -} + memcpy(to, &t, sizeof(T)); +} template <class T, unsigned Align = sizeof(T)> class TUnalignedMemoryIterator { diff --git a/util/system/unaligned_mem_ut.cpp b/util/system/unaligned_mem_ut.cpp index 9de3f3e931..d8c799d727 100644 --- a/util/system/unaligned_mem_ut.cpp +++ b/util/system/unaligned_mem_ut.cpp @@ -1,8 +1,8 @@ -#include "unaligned_mem.h" - +#include "unaligned_mem.h" + #include <library/cpp/testing/benchmark/bench.h> #include <library/cpp/testing/unittest/registar.h> - + #include <util/system/compiler.h> #ifdef Y_HAVE_INT128 @@ -21,7 +21,7 @@ namespace { } static TUInt128 Max() { - return {~(__uint128_t)0}; + return {~(__uint128_t)0}; } __uint128_t x; @@ -32,15 +32,15 @@ namespace { Y_UNIT_TEST_SUITE(UnalignedMem) { Y_UNIT_TEST(TestReadWrite) { alignas(ui64) char buf[100]; - + WriteUnaligned<ui16>(buf + 1, (ui16)1); WriteUnaligned<ui32>(buf + 1 + 2, (ui32)2); WriteUnaligned<ui64>(buf + 1 + 2 + 4, (ui64)3); - + UNIT_ASSERT_VALUES_EQUAL(ReadUnaligned<ui16>(buf + 1), 1); UNIT_ASSERT_VALUES_EQUAL(ReadUnaligned<ui32>(buf + 1 + 2), 2); UNIT_ASSERT_VALUES_EQUAL(ReadUnaligned<ui64>(buf + 1 + 2 + 4), 3); - } + } Y_UNIT_TEST(TestReadWriteRuntime) { // Unlike the test above, this test avoids compile-time execution by a smart compiler. @@ -93,4 +93,4 @@ Y_UNIT_TEST_SUITE(UnalignedMem) { UNIT_ASSERT(val == TUInt128::Max()); } #endif -} +} diff --git a/util/system/user.cpp b/util/system/user.cpp index 83e89ea0a8..bdbc9e54dc 100644 --- a/util/system/user.cpp +++ b/util/system/user.cpp @@ -6,19 +6,19 @@ #include <util/generic/yexception.h> #ifdef _win_ - #include "winint.h" + #include "winint.h" #else - #include <errno.h> - #include <pwd.h> - #include <unistd.h> + #include <errno.h> + #include <pwd.h> + #include <unistd.h> #endif TString GetUsername() { for (const auto& var : {"LOGNAME", "USER", "LNAME", "USERNAME"}) { TString val = GetEnv(var); - if (val) { + if (val) { return val; - } + } } TTempBuf nameBuf; @@ -34,15 +34,15 @@ TString GetUsername() { } else { return TString(nameBuf.Data(), (size_t)(len - 1)); } -#elif defined(_bionic_) - const passwd* pwd = getpwuid(geteuid()); - - if (pwd) { +#elif defined(_bionic_) + const passwd* pwd = getpwuid(geteuid()); + + if (pwd) { return TString(pwd->pw_name); - } - + } + ythrow TSystemError() << TStringBuf(" getpwuid failed"); -#else +#else passwd pwd; passwd* tmpPwd; int err = getpwuid_r(geteuid(), &pwd, nameBuf.Data(), nameBuf.Size(), &tmpPwd); diff --git a/util/system/user_ut.cpp b/util/system/user_ut.cpp index 4f8a5ce2ef..070ad98ed5 100644 --- a/util/system/user_ut.cpp +++ b/util/system/user_ut.cpp @@ -1,9 +1,9 @@ -#include "user.h" - +#include "user.h" + #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TestUser) { Y_UNIT_TEST(TestNotEmpty) { - UNIT_ASSERT(GetUsername()); - } -} + UNIT_ASSERT(GetUsername()); + } +} diff --git a/util/system/ut/ya.make b/util/system/ut/ya.make index 127e7c261e..453b5f8c15 100644 --- a/util/system/ut/ya.make +++ b/util/system/ut/ya.make @@ -1,16 +1,16 @@ -UNITTEST_FOR(util) +UNITTEST_FOR(util) OWNER(g:util) SUBSCRIBER(g:util-subscribers) -FORK_TESTS() +FORK_TESTS() -FORK_SUBTESTS() +FORK_SUBTESTS() -SPLIT_FACTOR(40) - -TIMEOUT(300) +SPLIT_FACTOR(40) +TIMEOUT(300) + SIZE(MEDIUM) IF (OS_DARWIN) @@ -24,57 +24,57 @@ PEERDIR( ) SRCS( - system/align_ut.cpp - system/atexit_ut.cpp - system/atomic_ut.cpp - system/backtrace_ut.cpp - system/byteorder_ut.cpp - system/compat_ut.cpp + system/align_ut.cpp + system/atexit_ut.cpp + system/atomic_ut.cpp + system/backtrace_ut.cpp + system/byteorder_ut.cpp + system/compat_ut.cpp system/compiler_ut.cpp - system/context_ut.cpp - system/condvar_ut.cpp - system/cpu_id_ut.cpp - system/datetime_ut.cpp + system/context_ut.cpp + system/condvar_ut.cpp + system/cpu_id_ut.cpp + system/datetime_ut.cpp system/daemon_ut.cpp - system/direct_io_ut.cpp - system/env_ut.cpp - system/error_ut.cpp - system/event_ut.cpp - system/execpath_ut.cpp - system/file_ut.cpp - system/filemap_ut.cpp - system/flock_ut.cpp - system/fs_ut.cpp - system/fstat_ut.cpp - system/getpid_ut.cpp - system/guard_ut.cpp + system/direct_io_ut.cpp + system/env_ut.cpp + system/error_ut.cpp + system/event_ut.cpp + system/execpath_ut.cpp + system/file_ut.cpp + system/filemap_ut.cpp + system/flock_ut.cpp + system/fs_ut.cpp + system/fstat_ut.cpp + system/getpid_ut.cpp + system/guard_ut.cpp system/hi_lo_ut.cpp - system/hostname_ut.cpp - system/info_ut.cpp + system/hostname_ut.cpp + system/info_ut.cpp system/interrupt_signals_ut.cpp - system/mem_info_ut.cpp + system/mem_info_ut.cpp system/mincore_ut.cpp - system/mutex_ut.cpp - system/nice_ut.cpp - system/pipe_ut.cpp - system/platform_ut.cpp - system/progname_ut.cpp - system/rusage_ut.cpp - system/rwlock_ut.cpp + system/mutex_ut.cpp + system/nice_ut.cpp + system/pipe_ut.cpp + system/platform_ut.cpp + system/progname_ut.cpp + system/rusage_ut.cpp + system/rwlock_ut.cpp system/sanitizers_ut.cpp - system/shellcommand_ut.cpp - system/spinlock_ut.cpp - system/src_root_ut.cpp - system/src_location_ut.cpp + system/shellcommand_ut.cpp + system/spinlock_ut.cpp + system/src_root_ut.cpp + system/src_location_ut.cpp system/shmat_ut.cpp - system/tempfile_ut.cpp - system/thread_ut.cpp - system/tls_ut.cpp + system/tempfile_ut.cpp + system/thread_ut.cpp + system/tls_ut.cpp system/types_ut.cpp system/type_name_ut.cpp - system/user_ut.cpp - system/unaligned_mem_ut.cpp - system/yassert_ut.cpp + system/user_ut.cpp + system/unaligned_mem_ut.cpp + system/yassert_ut.cpp ) IF (OS_WINDOWS) diff --git a/util/system/utime.cpp b/util/system/utime.cpp index c7bfc4bf3d..44135e9b42 100644 --- a/util/system/utime.cpp +++ b/util/system/utime.cpp @@ -1,20 +1,20 @@ -#include "../system/utime.h" - -#ifdef _MSC_VER - #include <sys/utime.h> -#else - #define HDR <../include/utime.h> - #include <sys/types.h> - #include HDR -#endif - -int TouchFile(const char* filePath) { +#include "../system/utime.h" + +#ifdef _MSC_VER + #include <sys/utime.h> +#else + #define HDR <../include/utime.h> + #include <sys/types.h> + #include HDR +#endif + +int TouchFile(const char* filePath) { return utime(filePath, nullptr); -} - -int SetModTime(const char* filePath, time_t modtime, time_t actime) { - struct utimbuf buf; - buf.modtime = modtime; - buf.actime = actime; - return utime(filePath, &buf); -} +} + +int SetModTime(const char* filePath, time_t modtime, time_t actime) { + struct utimbuf buf; + buf.modtime = modtime; + buf.actime = actime; + return utime(filePath, &buf); +} diff --git a/util/system/utime.h b/util/system/utime.h index 1c52e6614d..1558378ec7 100644 --- a/util/system/utime.h +++ b/util/system/utime.h @@ -2,5 +2,5 @@ #include "defaults.h" -int TouchFile(const char* filePath); -int SetModTime(const char* filePath, time_t modtime, time_t actime); +int TouchFile(const char* filePath); +int SetModTime(const char* filePath, time_t modtime, time_t actime); diff --git a/util/system/valgrind.cpp b/util/system/valgrind.cpp index 8b2f172a6c..f7599f9f1f 100644 --- a/util/system/valgrind.cpp +++ b/util/system/valgrind.cpp @@ -1 +1 @@ -#include "valgrind.h" +#include "valgrind.h" diff --git a/util/system/valgrind.h b/util/system/valgrind.h index 2ec4ed927c..6cc9e6e575 100644 --- a/util/system/valgrind.h +++ b/util/system/valgrind.h @@ -1,36 +1,36 @@ #pragma once - -#if defined(WITH_VALGRIND) && defined(HAVE_VALGRIND) - #include <valgrind/valgrind.h> - #include <valgrind/memcheck.h> - - #if !defined(VALGRIND_CHECK_READABLE) - #define VALGRIND_CHECK_READABLE(s, l) VALGRIND_CHECK_MEM_IS_DEFINED(s, l) - #endif - - #if !defined(VALGRIND_MAKE_READABLE) - #define VALGRIND_MAKE_READABLE(a, b) VALGRIND_MAKE_MEM_DEFINED(a, b) - #endif -#else - #define RUNNING_ON_VALGRIND 0 - #define VALGRIND_CHECK_READABLE(s, l) - #define VALGRIND_MAKE_READABLE(a, b) 0 - #define VALGRIND_STACK_REGISTER(start, end) 0 - #define VALGRIND_STACK_DEREGISTER(id) - #define VALGRIND_DISCARD(v) ((void)v) -static inline int VALGRIND_PRINTF(...) { - return 0; -} - #define VALGRIND_DO_LEAK_CHECK -#endif + +#if defined(WITH_VALGRIND) && defined(HAVE_VALGRIND) + #include <valgrind/valgrind.h> + #include <valgrind/memcheck.h> + + #if !defined(VALGRIND_CHECK_READABLE) + #define VALGRIND_CHECK_READABLE(s, l) VALGRIND_CHECK_MEM_IS_DEFINED(s, l) + #endif + + #if !defined(VALGRIND_MAKE_READABLE) + #define VALGRIND_MAKE_READABLE(a, b) VALGRIND_MAKE_MEM_DEFINED(a, b) + #endif +#else + #define RUNNING_ON_VALGRIND 0 + #define VALGRIND_CHECK_READABLE(s, l) + #define VALGRIND_MAKE_READABLE(a, b) 0 + #define VALGRIND_STACK_REGISTER(start, end) 0 + #define VALGRIND_STACK_DEREGISTER(id) + #define VALGRIND_DISCARD(v) ((void)v) +static inline int VALGRIND_PRINTF(...) { + return 0; +} + #define VALGRIND_DO_LEAK_CHECK +#endif namespace NValgrind { inline constexpr static bool ValgrindIsOn() noexcept { -#if defined(WITH_VALGRIND) - return true; -#else - return false; -#endif +#if defined(WITH_VALGRIND) + return true; +#else + return false; +#endif } // Returns valgrinded if running under Valgrind and plain otherwise diff --git a/util/system/winint.cpp b/util/system/winint.cpp index b13033bdee..8abdc8c93a 100644 --- a/util/system/winint.cpp +++ b/util/system/winint.cpp @@ -1 +1 @@ -#include "winint.h" +#include "winint.h" diff --git a/util/system/winint.h b/util/system/winint.h index ebeaefb3d2..8eab0e05ca 100644 --- a/util/system/winint.h +++ b/util/system/winint.h @@ -1,43 +1,43 @@ #pragma once -#include "platform.h" +#include "platform.h" #if defined(_win_) - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - - #ifndef NOMINMAX - #define NOMINMAX - #endif - - #include <windows.h> - - #undef GetFreeSpace - #undef LoadImage - #undef GetMessage - #undef SendMessage - #undef DeleteFile - #undef OPTIONAL - #undef GetUserName - #undef CreateMutex - #undef GetObject - #undef GetGeoInfo - #undef GetClassName - #undef LANG_LAO - #undef GetKValue - #undef StartDoc - #undef UpdateResource - #undef GetNameInfo - #undef GetProp - #undef SetProp - #undef RemoveProp - - #undef IGNORE - #undef ERROR - #undef TRANSPARENT - - #undef CM_NONE + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + + #ifndef NOMINMAX + #define NOMINMAX + #endif + + #include <windows.h> + + #undef GetFreeSpace + #undef LoadImage + #undef GetMessage + #undef SendMessage + #undef DeleteFile + #undef OPTIONAL + #undef GetUserName + #undef CreateMutex + #undef GetObject + #undef GetGeoInfo + #undef GetClassName + #undef LANG_LAO + #undef GetKValue + #undef StartDoc + #undef UpdateResource + #undef GetNameInfo + #undef GetProp + #undef SetProp + #undef RemoveProp + + #undef IGNORE + #undef ERROR + #undef TRANSPARENT + + #undef CM_NONE #endif diff --git a/util/system/yassert.cpp b/util/system/yassert.cpp index 0f586648b7..c3557146d0 100644 --- a/util/system/yassert.cpp +++ b/util/system/yassert.cpp @@ -1,8 +1,8 @@ -#include "yassert.h" - +#include "yassert.h" + #include "backtrace.h" -#include "guard.h" -#include "spinlock.h" +#include "guard.h" +#include "spinlock.h" #include "src_root.h" #include <util/datetime/base.h> @@ -16,40 +16,40 @@ #include <cstdlib> #include <stdarg.h> #include <stdio.h> - + #ifdef CLANG_COVERAGE extern "C" { - // __llvm_profile_write_file may not be provided if the executable target uses NO_CLANG_COVERAGE() macro and - // arrives as test's dependency via DEPENDS() macro. - // That's why we provide a weak no-op implementation for __llvm_profile_write_file, - // which is used below in the code, to correctly save codecoverage profile before program exits using abort(). - Y_WEAK int __llvm_profile_write_file(void) { - return 0; - } + // __llvm_profile_write_file may not be provided if the executable target uses NO_CLANG_COVERAGE() macro and + // arrives as test's dependency via DEPENDS() macro. + // That's why we provide a weak no-op implementation for __llvm_profile_write_file, + // which is used below in the code, to correctly save codecoverage profile before program exits using abort(). + Y_WEAK int __llvm_profile_write_file(void) { + return 0; + } } #endif -namespace { - struct TPanicLockHolder: public TAdaptiveLock { - }; -} +namespace { + struct TPanicLockHolder: public TAdaptiveLock { + }; +} namespace NPrivate { [[noreturn]] Y_NO_INLINE void InternalPanicImpl(int line, const char* function, const char* expr, int, int, int, const TStringBuf file, const char* errorMessage, size_t errorMessageSize) noexcept; } void ::NPrivate::Panic(const TStaticBuf& file, int line, const char* function, const char* expr, const char* format, ...) noexcept { - try { - // We care of panic of first failed thread only - // Otherwise stderr could contain multiple messages and stack traces shuffled - auto guard = Guard(*Singleton<TPanicLockHolder>()); + try { + // We care of panic of first failed thread only + // Otherwise stderr could contain multiple messages and stack traces shuffled + auto guard = Guard(*Singleton<TPanicLockHolder>()); TString errorMsg; - va_list args; - va_start(args, format); + va_list args; + va_start(args, format); // format has " " prefix to mute GCC warning on empty format vsprintf(errorMsg, format[0] == ' ' ? format + 1 : format, args); - va_end(args); + va_end(args); constexpr int abiPlaceholder = 0; ::NPrivate::InternalPanicImpl(line, function, expr, abiPlaceholder, abiPlaceholder, abiPlaceholder, file.As<TStringBuf>(), errorMsg.c_str(), errorMsg.size()); @@ -66,7 +66,7 @@ namespace NPrivate { const TString now = TInstant::Now().ToStringLocal(); TString r; - TStringOutput o(r); + TStringOutput o(r); if (expr) { o << "VERIFY failed (" << now << "): " << errorMsg << Endl; } else { @@ -80,7 +80,7 @@ namespace NPrivate { } Cerr << r << Flush; #ifndef WITH_VALGRIND - PrintBackTrace(); + PrintBackTrace(); #endif #ifdef CLANG_COVERAGE if (__llvm_profile_write_file()) { @@ -88,7 +88,7 @@ namespace NPrivate { } #endif abort(); - } catch (...) { + } catch (...) { abort(); - } + } } diff --git a/util/system/yassert.h b/util/system/yassert.h index 529823440c..ee5f166ee9 100644 --- a/util/system/yassert.h +++ b/util/system/yassert.h @@ -1,53 +1,53 @@ #pragma once -#include "defaults.h" -#include "src_root.h" +#include "defaults.h" +#include "src_root.h" #include "backtrace.h" -#if defined(_MSC_VER) - #include <new> - #if defined(_DEBUG) - #if defined(_CRTDBG_MAP_ALLOC) - #include <cstdlib> /* definitions for malloc/calloc */ - #include <malloc.h> /* must be before their redefinitions as _*_dbg() */ - #endif - #include <crtdbg.h> - #else - #endif - #include <cassert> -#elif defined(__GNUC__) - #ifdef _sun_ - #include <alloca.h> - #endif - #include <cassert> -#endif +#if defined(_MSC_VER) + #include <new> + #if defined(_DEBUG) + #if defined(_CRTDBG_MAP_ALLOC) + #include <cstdlib> /* definitions for malloc/calloc */ + #include <malloc.h> /* must be before their redefinitions as _*_dbg() */ + #endif + #include <crtdbg.h> + #else + #endif + #include <cassert> +#elif defined(__GNUC__) + #ifdef _sun_ + #include <alloca.h> + #endif + #include <cassert> +#endif #if !defined(_MSC_VER) #if defined(__has_builtin) && __has_builtin(__debugbreak) - // Do nothing, use __debugbreak builtin + // Do nothing, use __debugbreak builtin #else -inline void __debugbreak() { - #if defined(__x86_64__) || defined(__i386__) - __asm__ volatile("int $3\n"); - #else - assert(0); - #endif -} +inline void __debugbreak() { + #if defined(__x86_64__) || defined(__i386__) + __asm__ volatile("int $3\n"); + #else + assert(0); + #endif +} #endif -inline bool YaIsDebuggerPresent() { - return false; -} -#else -// __debugbreak is intrinsic in MSVC +inline bool YaIsDebuggerPresent() { + return false; +} +#else +// __debugbreak is intrinsic in MSVC -extern "C" { - __declspec(dllimport) int __stdcall IsDebuggerPresent(); -} +extern "C" { + __declspec(dllimport) int __stdcall IsDebuggerPresent(); +} -inline bool YaIsDebuggerPresent() { - return IsDebuggerPresent() != 0; -} +inline bool YaIsDebuggerPresent() { + return IsDebuggerPresent() != 0; +} #endif inline void YaDebugBreak() { @@ -57,36 +57,36 @@ inline void YaDebugBreak() { #undef Y_ASSERT #if !defined(NDEBUG) && !defined(__GCCXML__) - #define Y_ASSERT(a) \ - do { \ - try { \ - if (Y_UNLIKELY(!(a))) { \ - if (YaIsDebuggerPresent()) \ - __debugbreak(); \ - else { \ - PrintBackTrace(); \ + #define Y_ASSERT(a) \ + do { \ + try { \ + if (Y_UNLIKELY(!(a))) { \ + if (YaIsDebuggerPresent()) \ + __debugbreak(); \ + else { \ + PrintBackTrace(); \ /* NOLINTNEXTLINE */ \ - assert(false && (a)); \ - } \ - } \ - } catch (...) { \ - if (YaIsDebuggerPresent()) \ - __debugbreak(); \ - else { \ - PrintBackTrace(); \ + assert(false && (a)); \ + } \ + } \ + } catch (...) { \ + if (YaIsDebuggerPresent()) \ + __debugbreak(); \ + else { \ + PrintBackTrace(); \ /* NOLINTNEXTLINE */ \ - assert(false && "Exception during assert"); \ - } \ - } \ - } while (false) + assert(false && "Exception during assert"); \ + } \ + } \ + } while (false) #else - #define Y_ASSERT(a) \ - do { \ - if (false) { \ - auto __xxx = static_cast<bool>(a); \ - Y_UNUSED(__xxx); \ - } \ - } while (false) + #define Y_ASSERT(a) \ + do { \ + if (false) { \ + auto __xxx = static_cast<bool>(a); \ + Y_UNUSED(__xxx); \ + } \ + } while (false) #endif namespace NPrivate { @@ -96,10 +96,10 @@ namespace NPrivate { /// Assert that does not depend on NDEBUG macro and outputs message like printf #define Y_VERIFY(expr, ...) \ - do { \ - if (Y_UNLIKELY(!(expr))) { \ - ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \ - } \ + do { \ + if (Y_UNLIKELY(!(expr))) { \ + ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \ + } \ } while (false) #define Y_FAIL(...) \ @@ -108,19 +108,19 @@ namespace NPrivate { } while (false) #ifndef NDEBUG - /// Assert that depend on NDEBUG macro and outputs message like printf - #define Y_VERIFY_DEBUG(expr, ...) \ - do { \ - if (Y_UNLIKELY(!(expr))) { \ - ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \ - } \ - } while (false) + /// Assert that depend on NDEBUG macro and outputs message like printf + #define Y_VERIFY_DEBUG(expr, ...) \ + do { \ + if (Y_UNLIKELY(!(expr))) { \ + ::NPrivate::Panic(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__, #expr, " " __VA_ARGS__); \ + } \ + } while (false) #else - #define Y_VERIFY_DEBUG(expr, ...) \ - do { \ - if (false) { \ - bool __xxx = static_cast<bool>(expr); \ - Y_UNUSED(__xxx); \ - } \ - } while (false) + #define Y_VERIFY_DEBUG(expr, ...) \ + do { \ + if (false) { \ + bool __xxx = static_cast<bool>(expr); \ + Y_UNUSED(__xxx); \ + } \ + } while (false) #endif diff --git a/util/system/yassert_ut.cpp b/util/system/yassert_ut.cpp index ddd392666c..3a4a112873 100644 --- a/util/system/yassert_ut.cpp +++ b/util/system/yassert_ut.cpp @@ -6,18 +6,18 @@ Y_UNIT_TEST_SUITE(YassertTest) { Y_UNIT_TEST(TestAcsLikeFunctionCall) { - if (true) { + if (true) { Y_ASSERT(true); // this cannot be compiled if Y_ASSERT is "if (!cond) { ... }" - } else { + } else { Y_ASSERT(false); - } + } bool var = false; - if (false) { + if (false) { Y_ASSERT(false); - } else { + } else { var = true; // this is unreachable if Y_ASSERT is "if (!cond) { ... }" - } + } UNIT_ASSERT(var); } diff --git a/util/system/yield.cpp b/util/system/yield.cpp index b327b37b1a..c8bbf684e2 100644 --- a/util/system/yield.cpp +++ b/util/system/yield.cpp @@ -1,25 +1,25 @@ -#include "platform.h" - -#ifdef _win_ - #include "winint.h" - #include <process.h> -#else - #include <pthread.h> - #include <sched.h> -#endif - +#include "platform.h" + +#ifdef _win_ + #include "winint.h" + #include <process.h> +#else + #include <pthread.h> + #include <sched.h> +#endif + void SchedYield() noexcept { -#if defined(_unix_) - sched_yield(); -#else - Sleep(0); -#endif -} - +#if defined(_unix_) + sched_yield(); +#else + Sleep(0); +#endif +} + void ThreadYield() noexcept { -#if defined(_freebsd_) - pthread_yield(); -#else - SchedYield(); -#endif -} +#if defined(_freebsd_) + pthread_yield(); +#else + SchedYield(); +#endif +} diff --git a/util/system/yield.h b/util/system/yield.h index 9965fb52b5..70ef498123 100644 --- a/util/system/yield.h +++ b/util/system/yield.h @@ -1,4 +1,4 @@ #pragma once - + void SchedYield() noexcept; void ThreadYield() noexcept; |