Skip to content

Commit

Permalink
Partial support of MacOs
Browse files Browse the repository at this point in the history
Signed-off-by: drslebedev <dr.s.lebedev@gmail.com>
  • Loading branch information
drslebedev authored and RalphSteinhagen committed Sep 6, 2024
1 parent 63f82c7 commit 02b5587
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 174 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ endif ()
option(ENABLE_EXAMPLES "Enable Example Builds" ${GR_TOPLEVEL_PROJECT})

option(ENABLE_TESTING "Enable Test Builds" ${GR_TOPLEVEL_PROJECT})
if (ENABLE_TESTING AND UNIX AND NOT APPLE)
if (ENABLE_TESTING AND (UNIX OR APPLE))
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
enable_testing()
if (ENABLE_COVERAGE)
Expand Down
4 changes: 2 additions & 2 deletions bench/benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ template<Numeric T>
std::string to_si_prefix(T value_base, std::string_view unit = "s", std::size_t significant_digits = 0) {
static constexpr std::array si_prefixes{'q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'};
static constexpr long double base = 1000.0L;
long double value = value_base;
auto value = static_cast<long double>(value_base);

std::size_t exponent = 10U;
if (value == 0.0L) {
Expand Down Expand Up @@ -791,7 +791,7 @@ class benchmark : public ut::detail::test {
add_statistics(result_map, time_differences_ns);

result_map.try_emplace("total time", duration_s, "s", _precision);
result_map.try_emplace("ops/s", _n_scale_results * N_ITERATIONS / duration_s, "", std::max(1, _precision));
result_map.try_emplace("ops/s", static_cast<long double>(_n_scale_results * N_ITERATIONS) / duration_s, "", std::max(1, _precision));

if constexpr (MARKER_SIZE > 0) {
auto transposed_map = utils::convert<N_ITERATIONS>(marker_iter);
Expand Down
2 changes: 2 additions & 0 deletions blocks/http/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
if (NOT APPLE)
add_ut_test(qa_HttpBlock)
target_link_libraries(qa_HttpBlock PRIVATE gr-http)

if (EMSCRIPTEN)
target_link_options(qa_HttpBlock PRIVATE --pre-js=${CMAKE_CURRENT_SOURCE_DIR}/pre.js --emrun)
endif ()
endif ()
2 changes: 1 addition & 1 deletion core/benchmarks/bm_Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

using namespace gr;

#if defined __has_include && not __EMSCRIPTEN__
#if defined(__has_include) && not defined(__EMSCRIPTEN__) && not defined(__APPLE__)
#if __has_include(<pthread.h>) && __has_include(<sched.h>)
#include <errno.h>
#include <pthread.h>
Expand Down
2 changes: 1 addition & 1 deletion core/include/gnuradio-4.0/WaitStrategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class SpinWait {
yieldProcessor();
}
}
#ifndef __EMSCRIPTEN__
#if not defined(__EMSCRIPTEN__) && not defined(__APPLE__)
static void yieldProcessor() noexcept { asm volatile("rep\nnop"); }
#else
static void yieldProcessor() noexcept { std::this_thread::sleep_for(std::chrono::milliseconds(1)); }
Expand Down
191 changes: 66 additions & 125 deletions core/include/gnuradio-4.0/thread/thread_affinity.hpp

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion core/test/qa_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ const boost::ut::suite SequenceTests = [] {
"Sequence"_test = [] {
using namespace gr;
using signed_index_type = std::make_signed_t<std::size_t>;
#if not defined(__APPLE__)
expect(eq(alignof(Sequence), 64UZ));
#endif
expect(eq(0L, kInitialCursorValue));
expect(nothrow([] { Sequence(); }));
expect(nothrow([] { Sequence(2); }));
Expand Down Expand Up @@ -621,8 +623,9 @@ const boost::ut::suite StreamTagConcept = [] {
int64_t index;
std::string data;
};

#if not defined(__APPLE__)
expect(eq(sizeof(buffer_tag), 64UZ)) << "tag size";
#endif
BufferLike auto buffer = CircularBuffer<int32_t>(1024);
BufferLike auto tagBuffer = CircularBuffer<buffer_tag>(32);
expect(ge(buffer.size(), 1024u));
Expand Down
2 changes: 1 addition & 1 deletion core/test/qa_grc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ const boost::ut::suite GrcTests = [] {
}
};

#ifndef __EMSCRIPTEN__
#if not defined(__EMSCRIPTEN__) && not defined(__APPLE__)
"Basic graph loading and storing using plugins"_test = [] {
try {
using namespace gr;
Expand Down
92 changes: 51 additions & 41 deletions core/test/qa_thread_affinity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const boost::ut::suite ThreadAffinityTests = [] {
using namespace boost::ut;

"thread_exception"_test = [] {
expect(nothrow([]{gr::thread_pool::thread::thread_exception();}));
expect(nothrow([] { gr::thread_pool::thread::thread_exception(); }));
expect(gr::thread_pool::thread::thread_exception().name() == "thread_exception"_b);
expect(gr::thread_pool::thread::thread_exception().message(-1) == "unknown threading error code -1"_b);
expect(gr::thread_pool::thread::thread_exception().message(-2) == "unknown threading error code -2"_b);
Expand All @@ -19,7 +19,7 @@ const boost::ut::suite ThreadAffinityTests = [] {
};

"thread_helper"_test = [] {
#if not defined(__EMSCRIPTEN__)
#if not defined(__EMSCRIPTEN__) && not defined(__APPLE__)
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_FIFO) == gr::thread_pool::thread::Policy::FIFO);
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_RR) == gr::thread_pool::thread::Policy::ROUND_ROBIN);
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_OTHER) == gr::thread_pool::thread::Policy::OTHER);
Expand All @@ -28,14 +28,18 @@ const boost::ut::suite ThreadAffinityTests = [] {
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(-2) == gr::thread_pool::thread::Policy::UNKNOWN);
};

#if not defined(__EMSCRIPTEN__)
#if not defined(__EMSCRIPTEN__) && not defined(__APPLE__)
"basic thread affinity"_test = [] {
using namespace gr::thread_pool;
std::atomic<bool> run = true;
const auto dummyAction = [&run]() { while (run) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } };
std::thread testThread(dummyAction);
std::atomic<bool> run = true;
const auto dummyAction = [&run]() {
while (run) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
};
std::thread testThread(dummyAction);

constexpr std::array threadMap = { true, false, false, false };
constexpr std::array threadMap = {true, false, false, false};
thread::setThreadAffinity(threadMap, testThread);
auto affinity = thread::getThreadAffinity(testThread);
bool equal = true;
Expand All @@ -47,7 +51,7 @@ const boost::ut::suite ThreadAffinityTests = [] {
expect(equal) << fmt::format("set {{{}}} affinity map does not match get {{{}}} map", fmt::join(threadMap, ", "), fmt::join(affinity, ", "));

// tests w/o thread argument
constexpr std::array threadMapOn = { true, true };
constexpr std::array threadMapOn = {true, true};
thread::setThreadAffinity(threadMapOn);
affinity = thread::getThreadAffinity();
for (size_t i = 0; i < std::min(threadMapOn.size(), affinity.size()); i++) {
Expand All @@ -58,16 +62,16 @@ const boost::ut::suite ThreadAffinityTests = [] {
expect(equal) << fmt::format("set {{{}}} affinity map does not match get {{{}}} map", fmt::join(threadMap, ", "), fmt::join(affinity, ", "));

std::thread bogusThread;
expect(throws<std::system_error>([&]{ thread::getThreadAffinity(bogusThread); }));
expect(throws<std::system_error>([&]{ thread::setThreadAffinity(threadMapOn, bogusThread); }));
expect(throws<std::system_error>([&] { thread::getThreadAffinity(bogusThread); }));
expect(throws<std::system_error>([&] { thread::setThreadAffinity(threadMapOn, bogusThread); }));

run = false;
testThread.join();
};

"basic process affinity"_test = [] {
using namespace gr::thread_pool;
constexpr std::array threadMap = { true, false, false, false };
constexpr std::array threadMap = {true, false, false, false};
thread::setProcessAffinity(threadMap);
auto affinity = thread::getProcessAffinity();
bool equal = true;
Expand All @@ -77,29 +81,33 @@ const boost::ut::suite ThreadAffinityTests = [] {
}
}
expect(equal) << fmt::format("set {{{}}} affinity map does not match get {{{}}} map", fmt::join(threadMap, ", "), fmt::join(affinity, ", "));
constexpr std::array threadMapOn = { true, true, true, true };
constexpr std::array threadMapOn = {true, true, true, true};
thread::setProcessAffinity(threadMapOn);
expect(throws<std::system_error>([&]{ thread::getProcessAffinity(-1); }));
expect(throws<std::system_error>([&]{ thread::setProcessAffinity(threadMapOn, -1); }));
expect(throws<std::system_error>([&] { thread::getProcessAffinity(-1); }));
expect(throws<std::system_error>([&] { thread::setProcessAffinity(threadMapOn, -1); }));
};

"ThreadName"_test = [] {
using namespace gr::thread_pool;
expect(!thread::getThreadName().empty()) << "Thread name shouldn't be empty";
expect(nothrow([]{ thread::setThreadName("testCoreName"); }));
expect(nothrow([] { thread::setThreadName("testCoreName"); }));
expect(thread::getThreadName() == "testCoreName"_b);

std::atomic<bool> run = true;
const auto dummyAction = [&run]() { while (run) { std::this_thread::sleep_for(std::chrono::milliseconds(20)); } };
std::thread testThread(dummyAction);
const auto dummyAction = [&run]() {
while (run) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
};
std::thread testThread(dummyAction);
expect(!thread::getThreadName(testThread).empty()) << "Thread Name shouldn't be empty";
expect(nothrow([&]{ thread::setThreadName("testThreadName", testThread); }));
expect(nothrow([&] { thread::setThreadName("testThreadName", testThread); }));
thread::setThreadName("testThreadName", testThread);
expect(thread::getThreadName(testThread) == "testThreadName"_b);

std::thread uninitialisedTestThread;
expect(throws<std::system_error>([&]{ thread::getThreadName(uninitialisedTestThread); }));
expect(throws<std::system_error>([&]{ thread::setThreadName("name", uninitialisedTestThread); }));
expect(throws<std::system_error>([&] { thread::getThreadName(uninitialisedTestThread); }));
expect(throws<std::system_error>([&] { thread::setThreadName("name", uninitialisedTestThread); }));
run = false;
testThread.join();
};
Expand All @@ -109,7 +117,7 @@ const boost::ut::suite ThreadAffinityTests = [] {
expect(!thread::getProcessName().empty()) << "Process name shouldn't be empty";
expect(that % thread::getProcessName() == thread::getProcessName(thread::detail::getPid()));

expect(nothrow([]{ thread::setProcessName("TestProcessName"); }));
expect(nothrow([] { thread::setProcessName("TestProcessName"); }));
expect(thread::getProcessName() == "TestProcessName"_b);
};

Expand All @@ -119,27 +127,31 @@ const boost::ut::suite ThreadAffinityTests = [] {
expect(that % param.policy == OTHER);
expect(that % param.priority == 0);

expect(nothrow([]{ setProcessSchedulingParameter(OTHER, 0); }));
expect(throws<std::system_error>([]{ setProcessSchedulingParameter(OTHER, 0, -1); }));
expect(throws<std::system_error>([]{ setProcessSchedulingParameter(OTHER, 4); }));
expect(throws<std::system_error>([]{ setProcessSchedulingParameter(ROUND_ROBIN, 5); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
expect(nothrow([] { setProcessSchedulingParameter(OTHER, 0); }));
expect(throws<std::system_error>([] { setProcessSchedulingParameter(OTHER, 0, -1); }));
expect(throws<std::system_error>([] { setProcessSchedulingParameter(OTHER, 4); }));
expect(throws<std::system_error>([] { setProcessSchedulingParameter(ROUND_ROBIN, 5); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
param = getProcessSchedulingParameter();
expect(that % param.policy == OTHER);
expect(that % param.priority == 0);

expect(throws<std::system_error>([]{ getProcessSchedulingParameter(-1); }));
expect(throws<std::system_error>([]{ setProcessSchedulingParameter(ROUND_ROBIN, 5, -1); }));
expect(throws<std::system_error>([] { getProcessSchedulingParameter(-1); }));
expect(throws<std::system_error>([] { setProcessSchedulingParameter(ROUND_ROBIN, 5, -1); }));

expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_FIFO) == gr::thread_pool::thread::FIFO);
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_RR) == gr::thread_pool::thread::ROUND_ROBIN);
expect(that % gr::thread_pool::thread::detail::getEnumPolicy(SCHED_OTHER) == gr::thread_pool::thread::OTHER);
};

"ThreadSchedulingParameter"_test = [] {
std::atomic<bool> run = true;
const auto dummyAction = [&run]() { while (run) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } };
std::thread testThread(dummyAction);
std::thread bogusThread;
std::atomic<bool> run = true;
const auto dummyAction = [&run]() {
while (run) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
};
std::thread testThread(dummyAction);
std::thread bogusThread;

using namespace gr::thread_pool::thread;
struct SchedulingParameter param = getThreadSchedulingParameter(testThread);
Expand All @@ -148,23 +160,21 @@ const boost::ut::suite ThreadAffinityTests = [] {

setThreadSchedulingParameter(OTHER, 0, testThread);
setThreadSchedulingParameter(OTHER, 0);
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(OTHER, 0, bogusThread); }));
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(OTHER, 4, testThread); }));
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(OTHER, 4); }));
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(ROUND_ROBIN, 5, testThread); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(ROUND_ROBIN, 5); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(OTHER, 0, bogusThread); }));
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(OTHER, 4, testThread); }));
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(OTHER, 4); }));
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(ROUND_ROBIN, 5, testThread); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(ROUND_ROBIN, 5); })); // missing rights -- because most users do not have CAP_SYS_NICE rights by default -- hard to unit-test
param = getThreadSchedulingParameter(testThread);
expect(that % param.policy == OTHER);

expect(throws<std::system_error>([&]{ getThreadSchedulingParameter(bogusThread); }));
expect(throws<std::system_error>([&]{ setThreadSchedulingParameter(ROUND_ROBIN, 5, bogusThread); }));
expect(throws<std::system_error>([&] { getThreadSchedulingParameter(bogusThread); }));
expect(throws<std::system_error>([&] { setThreadSchedulingParameter(ROUND_ROBIN, 5, bogusThread); }));

run = false;
testThread.join();
};
#endif
};

int
main() { /* tests are statically executed */
}
int main() { /* tests are statically executed */ }
2 changes: 1 addition & 1 deletion core/test/qa_thread_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const boost::ut::suite ThreadPoolTests = [] {
expect(ret.get() == 42_i);

auto taskName = pool.execute<"taskName", 0, -1>([] { return gr::thread_pool::thread::getThreadName(); });
#ifdef __EMSCRIPTEN__
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
expect(taskName.get() == "unknown thread name"_b);
#else
expect(taskName.get() == "taskName"_b);
Expand Down

0 comments on commit 02b5587

Please sign in to comment.