X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Ftest%2FDeterministicSchedule.cpp;h=d4e8d2da7f63d149cdea059f2d3d579a8fed4293;hb=0a6bc82e3b9ef8eb49dec6fa7208719ee32990af;hp=a08be86baf393945eebb32e605131060031446c6;hpb=a1614feea3f3c0beb75fb2dc43ec45b3e5d57223;p=folly.git diff --git a/folly/test/DeterministicSchedule.cpp b/folly/test/DeterministicSchedule.cpp index a08be86b..d4e8d2da 100644 --- a/folly/test/DeterministicSchedule.cpp +++ b/folly/test/DeterministicSchedule.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2013-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +15,17 @@ */ #include + +#include + #include #include #include #include -#include #include -#include +#include + +#include namespace folly { namespace test { @@ -29,6 +33,8 @@ namespace test { FOLLY_TLS sem_t* DeterministicSchedule::tls_sem; FOLLY_TLS DeterministicSchedule* DeterministicSchedule::tls_sched; FOLLY_TLS unsigned DeterministicSchedule::tls_threadId; +thread_local AuxAct DeterministicSchedule::tls_aux_act; +AuxChk DeterministicSchedule::aux_chk; // access is protected by futexLock static std::unordered_map*, @@ -37,10 +43,11 @@ static std::unordered_map*, static std::mutex futexLock; DeterministicSchedule::DeterministicSchedule( - const std::function& scheduler) - : scheduler_(scheduler), nextThreadId_(1) { + const std::function& scheduler) + : scheduler_(scheduler), nextThreadId_(1), step_(0) { assert(tls_sem == nullptr); assert(tls_sched == nullptr); + assert(tls_aux_act == nullptr); tls_sem = new sem_t; sem_init(tls_sem, 0, 1); @@ -56,16 +63,16 @@ DeterministicSchedule::~DeterministicSchedule() { beforeThreadExit(); } -std::function DeterministicSchedule::uniform(long seed) { +std::function DeterministicSchedule::uniform(uint64_t seed) { auto rand = std::make_shared(seed); return [rand](size_t numActive) { - auto dist = std::uniform_int_distribution(0, numActive - 1); + auto dist = std::uniform_int_distribution(0, numActive - 1); return dist(*rand); }; } struct UniformSubset { - UniformSubset(long seed, int subsetSize, int stepsBetweenSelect) + UniformSubset(uint64_t seed, size_t subsetSize, size_t stepsBetweenSelect) : uniform_(DeterministicSchedule::uniform(seed)), subsetSize_(subsetSize), stepsBetweenSelect_(stepsBetweenSelect), @@ -81,19 +88,20 @@ struct UniformSubset { } private: - std::function uniform_; + std::function uniform_; const size_t subsetSize_; - const int stepsBetweenSelect_; + const size_t stepsBetweenSelect_; - int stepsLeft_; + size_t stepsLeft_; // only the first subsetSize_ is properly randomized - std::vector perm_; + std::vector perm_; void adjustPermSize(size_t numActive) { if (perm_.size() > numActive) { - perm_.erase(std::remove_if(perm_.begin(), perm_.end(), [=](size_t x) { - return x >= numActive; - }), perm_.end()); + perm_.erase(std::remove_if(perm_.begin(), + perm_.end(), + [=](size_t x) { return x >= numActive; }), + perm_.end()); } else { while (perm_.size() < numActive) { perm_.push_back(perm_.size()); @@ -104,15 +112,14 @@ struct UniformSubset { void shufflePrefix() { for (size_t i = 0; i < std::min(perm_.size() - 1, subsetSize_); ++i) { - int j = uniform_(perm_.size() - i) + i; + size_t j = uniform_(perm_.size() - i) + i; std::swap(perm_[i], perm_[j]); } } }; -std::function DeterministicSchedule::uniformSubset(long seed, - int n, - int m) { +std::function +DeterministicSchedule::uniformSubset(uint64_t seed, size_t n, size_t m) { auto gen = std::make_shared(seed, n, m); return [=](size_t numActive) { return (*gen)(numActive); }; } @@ -128,15 +135,23 @@ void DeterministicSchedule::afterSharedAccess() { if (!sched) { return; } + sem_post(sched->sems_[sched->scheduler_(sched->sems_.size())]); +} +void DeterministicSchedule::afterSharedAccess(bool success) { + auto sched = tls_sched; + if (!sched) { + return; + } + sched->callAux(success); sem_post(sched->sems_[sched->scheduler_(sched->sems_.size())]); } -int DeterministicSchedule::getRandNumber(int n) { +size_t DeterministicSchedule::getRandNumber(size_t n) { if (tls_sched) { return tls_sched->scheduler_(n); } - return std::rand() % n; + return Random::rand32() % n; } int DeterministicSchedule::getcpu(unsigned* cpu, @@ -156,6 +171,18 @@ int DeterministicSchedule::getcpu(unsigned* cpu, return 0; } +void DeterministicSchedule::setAuxAct(AuxAct& aux) { + tls_aux_act = aux; +} + +void DeterministicSchedule::setAuxChk(AuxChk& aux) { + aux_chk = aux; +} + +void DeterministicSchedule::clearAuxChk() { + aux_chk = nullptr; +} + sem_t* DeterministicSchedule::beforeThreadCreate() { sem_t* s = new sem_t; sem_init(s, 0, 0); @@ -193,6 +220,7 @@ void DeterministicSchedule::beforeThreadExit() { delete tls_sem; tls_sem = nullptr; tls_sched = nullptr; + tls_aux_act = nullptr; } void DeterministicSchedule::join(std::thread& child) { @@ -211,6 +239,17 @@ void DeterministicSchedule::join(std::thread& child) { child.join(); } +void DeterministicSchedule::callAux(bool success) { + ++step_; + if (tls_aux_act) { + tls_aux_act(success); + tls_aux_act = nullptr; + } + if (aux_chk) { + aux_chk(step_); + } +} + void DeterministicSchedule::post(sem_t* sem) { beforeSharedAccess(); sem_post(sem); @@ -238,8 +277,8 @@ void DeterministicSchedule::wait(sem_t* sem) { // we're not busy waiting because this is a deterministic schedule } } -} -} +} // namespace test +} // namespace folly namespace folly { namespace detail { @@ -250,8 +289,8 @@ using namespace std::chrono; template <> FutexResult Futex::futexWaitImpl( uint32_t expected, - time_point* absSystemTimeout, - time_point* absSteadyTimeout, + system_clock::time_point const* absSystemTimeout, + steady_clock::time_point const* absSteadyTimeout, uint32_t waitMask) { bool hasTimeout = absSystemTimeout != nullptr || absSteadyTimeout != nullptr; bool awoken = false; @@ -262,7 +301,7 @@ FutexResult Futex::futexWaitImpl( << ", .., " << std::hex << waitMask << ") beginning.."); futexLock.lock(); - if (data == expected) { + if (this->data == expected) { auto& queue = futexQueues[this]; queue.emplace_back(waitMask, &awoken); auto ours = queue.end(); @@ -297,18 +336,18 @@ FutexResult Futex::futexWaitImpl( char const* resultStr = "?"; switch (result) { - case FutexResult::AWOKEN: - resultStr = "AWOKEN"; - break; - case FutexResult::TIMEDOUT: - resultStr = "TIMEDOUT"; - break; - case FutexResult::INTERRUPTED: - resultStr = "INTERRUPTED"; - break; - case FutexResult::VALUE_CHANGED: - resultStr = "VALUE_CHANGED"; - break; + case FutexResult::AWOKEN: + resultStr = "AWOKEN"; + break; + case FutexResult::TIMEDOUT: + resultStr = "TIMEDOUT"; + break; + case FutexResult::INTERRUPTED: + resultStr = "INTERRUPTED"; + break; + case FutexResult::VALUE_CHANGED: + resultStr = "VALUE_CHANGED"; + break; } FOLLY_TEST_DSCHED_VLOG(this << ".futexWait(" << std::hex << expected << ", .., " << std::hex << waitMask << ") -> " @@ -343,6 +382,7 @@ int Futex::futexWake(int count, uint32_t wakeMask) { DeterministicSchedule::afterSharedAccess(); return rv; } +} // namespace detail template <> CacheLocality const& CacheLocality::system() { @@ -351,23 +391,7 @@ CacheLocality const& CacheLocality::system() { } template <> -const AccessSpreader - AccessSpreader::stripeByCore( - CacheLocality::system<>().numCachesByLevel.front()); - -template <> -const AccessSpreader - AccessSpreader::stripeByChip( - CacheLocality::system<>().numCachesByLevel.back()); - -template <> -AccessSpreaderArray - AccessSpreaderArray::sharedInstance = {}; - -template <> -Getcpu::Func AccessSpreader::pickGetcpuFunc( - size_t /* numStripes */) { - return &DeterministicSchedule::getcpu; -} -} +Getcpu::Func AccessSpreader::pickGetcpuFunc() { + return &detail::DeterministicSchedule::getcpu; } +} // namespace folly