Skip to content

Commit 7c64b55

Browse files
Make sc_event thread safe
Signed-off-by: Mark Burton <mburton@quicinc.com>
1 parent b4dada7 commit 7c64b55

File tree

4 files changed

+110
-11
lines changed

4 files changed

+110
-11
lines changed

src/sysc/communication/sc_prim_channel.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ sc_prim_channel::sc_prim_channel( const char* name_ )
6363
m_registry->insert( *this );
6464
}
6565

66+
sc_prim_channel::sc_prim_channel( bool is_kernel )
67+
: sc_object( ),
68+
m_registry( simcontext()->get_prim_channel_registry() ),
69+
m_update_next_p( 0 )
70+
{
71+
if (is_kernel) {
72+
m_registry->insert_internal( *this );
73+
} else {
74+
m_registry->insert( *this );
75+
}
76+
}
6677

6778
// destructor
6879

@@ -237,18 +248,8 @@ class sc_prim_channel_registry::async_update_list
237248
// ----------------------------------------------------------------------------
238249

239250
void
240-
sc_prim_channel_registry::insert( sc_prim_channel& prim_channel_ )
251+
sc_prim_channel_registry::insert_internal( sc_prim_channel& prim_channel_ )
241252
{
242-
if( sc_is_running() ) {
243-
SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "simulation running" );
244-
return;
245-
}
246-
247-
if( m_simc->elaboration_done() ) {
248-
SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "elaboration done" );
249-
return;
250-
}
251-
252253
#ifdef DEBUG_SYSTEMC
253254
// check if prim_channel_ is already inserted
254255
for( int i = 0; i < size(); ++ i ) {
@@ -264,6 +265,21 @@ sc_prim_channel_registry::insert( sc_prim_channel& prim_channel_ )
264265

265266
}
266267

268+
void
269+
sc_prim_channel_registry::insert( sc_prim_channel& prim_channel_ )
270+
{
271+
if( sc_is_running() ) {
272+
SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "simulation running" );
273+
return;
274+
}
275+
276+
if( m_simc->elaboration_done() ) {
277+
SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "elaboration done" );
278+
return;
279+
}
280+
insert_internal( prim_channel_ );
281+
}
282+
267283
void
268284
sc_prim_channel_registry::remove( sc_prim_channel& prim_channel_ )
269285
{

src/sysc/communication/sc_prim_channel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class SC_API sc_prim_channel
6666
// constructors
6767
sc_prim_channel();
6868
explicit sc_prim_channel( const char* );
69+
explicit sc_prim_channel( bool );
6970

7071
// destructor
7172
virtual ~sc_prim_channel();
@@ -229,7 +230,9 @@ class SC_API sc_prim_channel
229230
class sc_prim_channel_registry
230231
{
231232
friend class sc_simcontext;
233+
friend class sc_prim_channel;
232234

235+
void insert_internal( sc_prim_channel& );
233236
public:
234237

235238
void insert( sc_prim_channel& );

src/sysc/kernel/sc_event.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <cstring>
3131

3232
#include "sysc/kernel/sc_event.h"
33+
#include "sc_simcontext.h"
3334
#include "sysc/kernel/sc_kernel_ids.h"
3435
#include "sysc/kernel/sc_stage_callback_registry.h"
3536
#include "sysc/kernel/sc_process.h"
@@ -61,6 +62,10 @@ sc_event::basename() const
6162
void
6263
sc_event::cancel()
6364
{
65+
if (m_simc != sc_get_curr_simcontext()) {
66+
m_async_helper.pending_cancel();
67+
return;
68+
}
6469
// cancel a delta or timed notification
6570
switch( m_notify_type ) {
6671
case DELTA: {
@@ -86,6 +91,10 @@ sc_event::cancel()
8691
void
8792
sc_event::notify()
8893
{
94+
if (m_simc != sc_get_curr_simcontext()) {
95+
m_async_helper.pending_notify(SC_ZERO_TIME);
96+
return;
97+
}
8998
// immediate notification
9099
if( !m_simc->evaluation_phase() )
91100
// coming from
@@ -103,6 +112,11 @@ sc_event::notify()
103112
void
104113
sc_event::notify( const sc_time& t )
105114
{
115+
if (m_simc != sc_get_curr_simcontext()) {
116+
std::cout << name()<<"HERE: ("<<t<<")\n";
117+
m_async_helper.pending_notify(t);
118+
return;
119+
}
106120
if( m_notify_type == DELTA ) {
107121
return;
108122
}
@@ -287,6 +301,7 @@ sc_event::sc_event( const char* name )
287301
, m_threads_dynamic()
288302
, m_name()
289303
, m_parent_with_hierarchy_flag(NULL)
304+
, m_async_helper(this)
290305
{
291306
register_event( name );
292307
}
@@ -310,6 +325,7 @@ sc_event::sc_event()
310325
, m_threads_dynamic()
311326
, m_name()
312327
, m_parent_with_hierarchy_flag(NULL)
328+
, m_async_helper(this)
313329
{
314330
register_event( NULL );
315331
}
@@ -333,6 +349,7 @@ sc_event::sc_event( kernel_tag, const char* name )
333349
, m_threads_dynamic()
334350
, m_name()
335351
, m_parent_with_hierarchy_flag(NULL)
352+
, m_async_helper(this)
336353
{
337354
register_event( name, /* is_kernel_event = */ true );
338355
}

src/sysc/kernel/sc_event.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
#include "sysc/kernel/sc_kernel_ids.h"
3535
#include "sysc/kernel/sc_simcontext.h"
3636
#include "sysc/communication/sc_writer_policy.h"
37+
#include "sysc/communication/sc_prim_channel.h"
3738
#include "sysc/utils/sc_ptr_flag.h"
39+
#include <mutex>
3840

3941
#if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN)
4042
#pragma warning(push)
@@ -273,6 +275,56 @@ class SC_API sc_event
273275
friend class sc_join;
274276
friend class sc_trace_file;
275277

278+
class pending_helper : public sc_prim_channel
279+
{
280+
std::mutex mutex;
281+
class sc_event *event;
282+
283+
bool valid=false;
284+
bool cancel=false;
285+
sc_time time;
286+
287+
void update(void) {
288+
mutex.lock();
289+
if (valid) {
290+
if (cancel) {
291+
valid=false;
292+
mutex.unlock();
293+
event->cancel();
294+
} else {
295+
valid=false;
296+
auto t=time;
297+
mutex.unlock();
298+
event->cancel();
299+
event->notify(t);
300+
}
301+
} else {
302+
mutex.unlock();
303+
}
304+
}
305+
306+
public:
307+
void pending_notify(sc_time t) {
308+
mutex.lock();
309+
time=t;
310+
valid=true;
311+
mutex.unlock();
312+
async_request_update();
313+
}
314+
void pending_cancel() {
315+
mutex.lock();
316+
valid=true;
317+
cancel=true;
318+
mutex.unlock();
319+
async_request_update();
320+
}
321+
322+
pending_helper(sc_event *e) : sc_prim_channel(true) {
323+
event=e;
324+
}
325+
326+
};
327+
friend class pending_helper;
276328
public:
277329

278330
sc_event();
@@ -354,6 +406,9 @@ class SC_API sc_event
354406
// disabled
355407
sc_event( const sc_event& );
356408
sc_event& operator = ( const sc_event& );
409+
410+
pending_helper m_async_helper;
411+
357412
};
358413

359414
// ----------------------------------------------------------------------------
@@ -424,6 +479,10 @@ inline
424479
void
425480
sc_event::notify_internal( const sc_time& t )
426481
{
482+
if (m_simc != sc_get_curr_simcontext()) {
483+
m_async_helper.pending_notify(t);
484+
return;
485+
}
427486
if( t == SC_ZERO_TIME ) {
428487
// add this event to the delta events set
429488
m_delta_event_index = m_simc->add_delta_event( this );
@@ -441,6 +500,10 @@ inline
441500
void
442501
sc_event::notify_next_delta()
443502
{
503+
if (m_simc != sc_get_curr_simcontext()) {
504+
m_async_helper.pending_notify(SC_ZERO_TIME);
505+
return;
506+
}
444507
if( m_notify_type != NONE ) {
445508
SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
446509
}

0 commit comments

Comments
 (0)