From 02d00265e71b9739b48c2f2f9a9089f4b5f2b363 Mon Sep 17 00:00:00 2001 From: Doug Gale Date: Fri, 26 Dec 2014 02:27:09 -0500 Subject: [PATCH] Initial implementation --- CMakeLists.txt | 2 + main.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..38e7a7c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,2 @@ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread") +add_executable(starve-check main.cpp) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..3e3cc04 --- /dev/null +++ b/main.cpp @@ -0,0 +1,153 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static constexpr std::size_t max_threads = 256; + +typedef std::chrono::system_clock Clock; +typedef std::chrono::time_point TimePoint; +typedef std::chrono::duration Duration; + +static void error(char const* message, int exitcode = 2) +{ + std::cerr << message << std::endl; + exit(exitcode); +} + +class stress_instance +{ +public: + stress_instance(); + ~stress_instance(); + void run(); + std::int64_t getCount(); + void stop(); + +private: + typedef std::atomic_int_least64_t CounterType; + void worker(); + + std::atomic_bool stopRequested; + std::thread thread; + char padding1[64]; + CounterType counter; + char padding2[64]; +}; + +static int run_stress(int cpucount, int timeLimit) +{ + static stress_instance instances[max_threads]; + stress_instance* end = instances + cpucount; + std::for_each(instances, end, + [](stress_instance& instance) + { + instance.run(); + }); + + // Use a condition variable wait for delays + // It looks more like we are doing work than + // it would if we were calling sleep_for + std::mutex dummyMutex; + std::condition_variable dummyConditionVariable; + std::unique_lock lock(dummyMutex); + do + { + dummyConditionVariable.wait_until(lock, Clock::now() + Duration(1)); + + std::for_each(instances, end, + [](stress_instance& instance) + { + std::cout << (instance.getCount() / 1000000) << "M "; + }); + std::cout << std::endl; + + // Only decrement it if it is positive + timeLimit -= (timeLimit > 0); + } + while (timeLimit != 0); +} + +int main(int argc, char** argv) +{ + int threads = 1; + bool force = false; + int timeLimit = -1; + + for (int i = 1; i < argc; ) + { + if (!strcmp(argv[i], "-t")) + { + if (argc + 1 >= argc) + error("Missing argument to thread count option (-t)"); + threads = atoi(argv[++i]); + } + else if (!strcmp(argv[i], "-i")) + { + if (argc + 1 >= argc) + error("Missing argument to iteration count option (-i)"); + timeLimit = atoi(argv[++i]); + } + else if (!strcmp(argv[i], "-f")) + { + force = true; + } + else + { + error((std::string("Invalid switch: ") + argv[i]).c_str()); + } + } + + std::size_t cpuCount = std::thread::hardware_concurrency(); + + if (threads <= 0) + threads = cpuCount; + + if (!force && threads > cpuCount) + threads = cpuCount; + + if (threads > max_threads) + threads = max_threads; + + return run_stress(threads, timeLimit); +} + +stress_instance::stress_instance() + : stopRequested(false) + , counter(0) +{ +} + +stress_instance::~stress_instance() +{ + stop(); +} + +void stress_instance::run() +{ + thread = std::thread(&stress_instance::worker, this); +} + +std::int64_t stress_instance::getCount() +{ + return counter.exchange(0); +} + +void stress_instance::stop() +{ + stopRequested = true; + if (thread.joinable()) + thread.join(); +} + +void stress_instance::worker() +{ + while (!stopRequested) + ++counter; +}