Skip to content

Commit

Permalink
fix race condition in sc_suspend test
Browse files Browse the repository at this point in the history
Align async_event example code with the scp_async_event as it's cleaner
Prevent race condition on startup in sc_suspend test

Signed-off-by: Mark Burton <mburton@quicinc.com>
  • Loading branch information
markfoodyburton committed Nov 20, 2024
1 parent 257e1b9 commit eaaf4d6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 25 deletions.
5 changes: 0 additions & 5 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,3 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
)
endif()

# Skip some test execution under some conditions
if(APPLE OR HAS__aarch64__DEFINED)
# TODO: Test hangs frequently on macOS and/or ARM 64-bit setups
skip_test(systemc/kernel/sc_suspend)
endif()
66 changes: 46 additions & 20 deletions tests/systemc/kernel/sc_suspend/sc_suspend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,62 +41,86 @@
#include <systemc>
#include <thread>

class async_event : public sc_core::sc_prim_channel, public sc_core::sc_event, public sc_core::sc_stage_callback_if
class async_event : public sc_core::sc_prim_channel,
public sc_core::sc_event,
public sc_core::sc_stage_callback_if
{
private:
int outstanding;
sc_core::sc_time m_delay;
std::thread::id tid;
std::mutex mutex; // Belt and braces
bool outstanding;

public:
async_event(bool start_attached = true): outstanding(0)
{
async_event(bool start_attached = true): outstanding(0) {
sc_core::sc_register_stage_callback(*this, sc_core::SC_PRE_PAUSE | sc_core::SC_PRE_SUSPEND | sc_core::SC_POST_SUSPEND);
tid = std::this_thread::get_id();
outstanding = 0;
outstanding = false;
enable_attach_suspending(start_attached);
}

void async_notify() { notify(); }

void notify(sc_core::sc_time delay = sc_core::sc_time(sc_core::SC_ZERO_TIME))
{
void notify() {
if (tid == std::this_thread::get_id()) {
sc_core::sc_event::notify();
} else {
notify(sc_core::SC_ZERO_TIME);
}
}
void notify(double d, sc_core::sc_time_unit u) {
notify(sc_core::sc_time(d, u));
}
void notify(sc_core::sc_time delay) {
if (tid == std::this_thread::get_id()) {
sc_core::sc_event::notify(delay);
} else {
mutex.lock();
m_delay = delay;
outstanding++;
outstanding = true;
mutex.unlock();
async_request_update();
}
}

void async_attach_suspending() { this->sc_core::sc_prim_channel::async_attach_suspending(); }
bool triggered() const {
if (tid == std::this_thread::get_id()) {
return sc_core::sc_event::triggered();
} else {
SC_REPORT_ERROR("async_event",
"It is an error to call triggered() from outside "
"the SystemC thread");
}
return false;
}
void async_attach_suspending() {
this->sc_core::sc_prim_channel::async_attach_suspending();
}

void async_detach_suspending() { this->sc_core::sc_prim_channel::async_detach_suspending(); }
void async_detach_suspending() {
this->sc_core::sc_prim_channel::async_detach_suspending();
}

void enable_attach_suspending(bool e)
{
mutex.lock();
void enable_attach_suspending(bool e) {
e ? this->async_attach_suspending() : this->async_detach_suspending();
mutex.unlock();
}

private:
void update(void)
{
void update(void) {
mutex.lock();
// we should be in SystemC thread
if (outstanding) {
sc_event::notify(m_delay);
outstanding--;
if (outstanding) request_update();
outstanding = false;
}
mutex.unlock();
}

void start_of_simulation() {
// we should be in SystemC thread
if (outstanding) {
request_update();
}
}
void stage_callback(const sc_core::sc_stage& stage)
{
std::ostringstream stage_str;
Expand All @@ -116,6 +140,7 @@ class async_event : public sc_core::sc_prim_channel, public sc_core::sc_event, p
};

SC_MODULE (tester) {
bool released = false;
std::mutex mutex;
std::condition_variable condition;
std::thread t;
Expand All @@ -125,7 +150,7 @@ SC_MODULE (tester) {
SC_CTOR (tester) :
t([&] {
std::unique_lock<decltype(mutex)> lock(mutex);
condition.wait(lock);
condition.wait(lock, [&](){return released;});
start.notify();
}),
start(false)
Expand Down Expand Up @@ -156,6 +181,7 @@ SC_MODULE (tester) {

// triggure the other thread to release us !
std::lock_guard<decltype(mutex)> lock(mutex);
released = true;
condition.notify_one();
} else {
SC_REPORT_INFO("tester", ("Unsuspend at SystemC time: " + sc_core::sc_time_stamp().to_string()).c_str());
Expand Down

0 comments on commit eaaf4d6

Please sign in to comment.