Skip to content

Commit 727e66f

Browse files
Additional thead safety and cleanups
Signed-off-by: Mark Burton <mburton@quicinc.com>
1 parent c2d4c18 commit 727e66f

File tree

13 files changed

+308
-207
lines changed

13 files changed

+308
-207
lines changed

src/sysc/kernel/sc_event.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void
9292
sc_event::notify()
9393
{
9494
if (m_simc != sc_get_curr_simcontext()) {
95-
m_async_helper.pending_notify(SC_ZERO_TIME);
95+
m_async_helper.pending_notify();
9696
return;
9797
}
9898
// immediate notification
@@ -113,7 +113,6 @@ void
113113
sc_event::notify( const sc_time& t )
114114
{
115115
if (m_simc != sc_get_curr_simcontext()) {
116-
std::cout << name()<<"HERE: ("<<t<<")\n";
117116
m_async_helper.pending_notify(t);
118117
return;
119118
}
@@ -182,6 +181,10 @@ static void sc_warn_notify_delayed()
182181
void
183182
sc_event::notify_delayed()
184183
{
184+
if (m_simc != sc_get_curr_simcontext()) {
185+
m_async_helper.pending_notify();
186+
return;
187+
}
185188
sc_warn_notify_delayed();
186189
if( m_notify_type != NONE ) {
187190
SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
@@ -194,6 +197,11 @@ sc_event::notify_delayed()
194197
void
195198
sc_event::notify_delayed( const sc_time& t )
196199
{
200+
if (m_simc != sc_get_curr_simcontext()) {
201+
m_async_helper.pending_notify(t);
202+
return;
203+
}
204+
197205
sc_warn_notify_delayed();
198206
if( m_notify_type != NONE ) {
199207
SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
@@ -557,7 +565,7 @@ union sc_event_timed_u
557565
char dummy[sizeof( sc_event_timed )];
558566
};
559567

560-
static
568+
thread_local static
561569
sc_event_timed_u* free_list = 0;
562570

563571
void*

src/sysc/kernel/sc_event.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class SC_API sc_event
282282

283283
bool valid=false;
284284
bool cancel=false;
285+
bool timed=false;
285286
sc_time time;
286287

287288
void update(void) {
@@ -294,9 +295,13 @@ class SC_API sc_event
294295
} else {
295296
valid=false;
296297
auto t=time;
298+
auto t_valid=timed;
297299
mutex.unlock();
298-
event->cancel();
299-
event->notify(t);
300+
if (t_valid) {
301+
event->notify(t);
302+
} else {
303+
event->notify();
304+
}
300305
}
301306
} else {
302307
mutex.unlock();
@@ -305,17 +310,22 @@ class SC_API sc_event
305310

306311
public:
307312
void pending_notify(sc_time t) {
308-
mutex.lock();
313+
std::lock_guard<std::mutex> lg(mutex);
309314
time=t;
315+
timed=true;
316+
valid=true;
317+
async_request_update();
318+
}
319+
void pending_notify() {
320+
std::lock_guard<std::mutex> lg(mutex);
321+
timed=false;
310322
valid=true;
311-
mutex.unlock();
312323
async_request_update();
313324
}
314325
void pending_cancel() {
315-
mutex.lock();
326+
std::lock_guard<std::mutex> lg(mutex);
316327
valid=true;
317328
cancel=true;
318-
mutex.unlock();
319329
async_request_update();
320330
}
321331

src/sysc/kernel/sc_name_gen.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ sc_name_gen::sc_name_gen() : m_unique_name_map(), m_unique_name()
4545

4646
sc_name_gen::~sc_name_gen()
4747
{
48+
std::unique_lock<std::mutex> lock(m_mutex);
4849
sc_strhash<int*>::iterator it( m_unique_name_map );
4950
for( ; ! it.empty(); it ++ ) {
5051
delete it.contents();
@@ -58,6 +59,7 @@ sc_name_gen::~sc_name_gen()
5859
const char*
5960
sc_name_gen::gen_unique_name( const char* basename_, bool preserve_first )
6061
{
62+
std::unique_lock<std::mutex> lock(m_mutex);
6163
if( basename_ == 0 || *basename_ == 0 ) {
6264
SC_REPORT_ERROR( SC_ID_GEN_UNIQUE_NAME_, 0 );
6365
basename_ = "unnamed"; // usually not reached

src/sysc/kernel/sc_name_gen.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#ifndef SC_NAME_GEN
3131
#define SC_NAME_GEN
3232

33+
#include <mutex>
3334
#include <string>
3435
#include "sysc/utils/sc_hash.h"
3536

@@ -52,7 +53,7 @@ class sc_name_gen
5253
bool preserve_first = false );
5354

5455
private:
55-
56+
std::mutex m_mutex;
5657
sc_strhash<int*> m_unique_name_map;
5758
std::string m_unique_name;
5859

src/sysc/kernel/sc_object_manager.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ sc_object_manager::~sc_object_manager()
9898
// | Result is an std::string containing the name.
9999
// +----------------------------------------------------------------------------
100100
std::string sc_object_manager::create_name(const char* leaf_name)
101-
{
101+
{
102+
std::unique_lock<std::mutex> lock(m_mutex);
103+
102104
bool clash; // true if path name exists in obj table
103105
std::string leafname_string; // string containing the leaf name.
104106
std::string parentname_string; // parent path name
@@ -337,6 +339,8 @@ sc_object_manager::hierarchy_size()
337339
bool
338340
sc_object_manager::insert_external_name(const std::string& name)
339341
{
342+
std::unique_lock<std::mutex> lock(m_mutex);
343+
340344
if(!name_exists(name)) {
341345
m_instance_table[name].m_element_p = NULL;
342346
m_instance_table[name].m_name_origin = SC_NAME_EXTERNAL;
@@ -368,6 +372,8 @@ sc_object_manager::insert_external_name(const std::string& name)
368372
void
369373
sc_object_manager::insert_event(const std::string& name, sc_event* event_p)
370374
{
375+
std::unique_lock<std::mutex> lock(m_mutex);
376+
371377
m_instance_table[name].m_element_p = static_cast<void*>(event_p);
372378
m_instance_table[name].m_name_origin = SC_NAME_EVENT;
373379
}
@@ -385,6 +391,8 @@ sc_object_manager::insert_event(const std::string& name, sc_event* event_p)
385391
void
386392
sc_object_manager::insert_object(const std::string& name, sc_object* object_p)
387393
{
394+
std::unique_lock<std::mutex> lock(m_mutex);
395+
388396
m_instance_table[name].m_element_p = static_cast<void*>(object_p);
389397
m_instance_table[name].m_name_origin = SC_NAME_OBJECT;
390398
}
@@ -479,6 +487,8 @@ sc_object_manager::top_of_module_name_stack_name() const
479487
void
480488
sc_object_manager::remove_event(const std::string& name)
481489
{
490+
std::unique_lock<std::mutex> lock(m_mutex);
491+
482492
instance_table_t::iterator it; // instance table iterator.
483493
it = m_instance_table.find(name);
484494
if(it != m_instance_table.end()
@@ -501,6 +511,8 @@ sc_object_manager::remove_event(const std::string& name)
501511
void
502512
sc_object_manager::remove_object(const std::string& name)
503513
{
514+
std::unique_lock<std::mutex> lock(m_mutex);
515+
504516
instance_table_t::iterator it; // instance table iterator.
505517
it = m_instance_table.find(name);
506518
if(it != m_instance_table.end()
@@ -523,6 +535,8 @@ sc_object_manager::remove_object(const std::string& name)
523535
bool
524536
sc_object_manager::remove_external_name(const std::string& name)
525537
{
538+
std::unique_lock<std::mutex> lock(m_mutex);
539+
526540
instance_table_t::iterator it; // instance table iterator.
527541
it = m_instance_table.find(name);
528542
if(it != m_instance_table.end()

src/sysc/kernel/sc_object_manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define SC_OBJECT_MANAGER_H
3232

3333
#include <map>
34+
#include <mutex>
3435
#include <vector>
3536

3637
namespace sc_core {
@@ -110,6 +111,7 @@ class sc_object_manager
110111
bool m_event_walk_ok; // true if can walk events.
111112
instance_table_t m_instance_table; // table of instances.
112113
sc_module_name* m_module_name_stack; // sc_module_name stack.
114+
std::mutex m_mutex; // Mutex to ensure thread safety.
113115
instance_table_t::iterator m_object_it; // object instance iterator.
114116
object_vector_t m_object_stack; // sc_object stack.
115117
bool m_object_walk_ok; // true if can walk objects.

src/sysc/kernel/sc_simcontext.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ sc_simcontext::init()
372372
void
373373
sc_simcontext::clean()
374374
{
375+
if (m_parent_context) return; // assume the parent will delete us
375376
// remove remaining zombie processes
376377
do_collect_processes();
377378

@@ -385,13 +386,15 @@ sc_simcontext::clean()
385386
delete m_null_event_p;
386387
delete m_timed_events;
387388
delete m_process_table;
388-
delete m_name_gen;
389389
delete m_stage_cb_registry;
390390
delete m_prim_channel_registry;
391391
delete m_export_registry;
392392
delete m_port_registry;
393393
delete m_module_registry;
394-
delete m_object_manager;
394+
if (!m_parent_context) {
395+
delete m_name_gen;
396+
delete m_object_manager;
397+
}
395398

396399
m_delta_events.clear();
397400
m_child_objects.clear();
@@ -1703,7 +1706,7 @@ sc_start( const sc_time& duration, sc_starvation_policy p )
17031706
exit_time = context_p->m_curr_time + duration;
17041707

17051708
// called with duration = SC_ZERO_TIME for the first time
1706-
static bool init_delta_or_pending_updates =
1709+
thread_local static bool init_delta_or_pending_updates =
17071710
( starting_delta == 0 && exit_time == SC_ZERO_TIME );
17081711

17091712
// If the simulation status is bad issue the appropriate message:

src/sysc/utils/sc_mempool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ sc_mempool_int::~sc_mempool_int()
244244
delete[] allocators;
245245
}
246246

247-
static sc_mempool_int* the_mempool = 0;
247+
thread_local static sc_mempool_int* the_mempool = 0;
248248

249249
void*
250250
sc_mempool_int::do_allocate(std::size_t sz)

src/sysc/utils/sc_ob_event.h

Lines changed: 52 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -35,83 +35,63 @@
3535
#include <string>
3636

3737
namespace sc_core {
38-
class sc_ob_event : public sc_core::sc_module, public sc_core::sc_event, public sc_core::sc_stage_callback_if
39-
{
38+
class sc_ob_event : public sc_core::sc_module,
39+
public sc_core::sc_event,
40+
public sc_core::sc_stage_callback_if {
4041

4142
private:
42-
sc_core::sc_event m_update;
43-
sc_core::sc_time m_scheduled;
44-
sc_core::sc_process_handle m_th;
45-
46-
void update_m()
47-
{
48-
auto now = sc_core::sc_time_stamp();
49-
if (now >= m_scheduled) {
50-
sc_core::sc_event::notify();
51-
} else {
52-
sc_core::sc_time pending = now;
53-
if (sc_core::sc_pending_activity_at_future_time()) {
54-
pending = now + sc_core::sc_time_to_pending_activity();
55-
}
56-
if (pending >= m_scheduled) {
57-
sc_core::sc_event::notify(m_scheduled - now);
58-
} else {
59-
if (pending > now) {
60-
m_update.notify(pending - now);
61-
} else {
62-
sc_core::sc_register_stage_callback(*this, sc_core::SC_POST_UPDATE);
63-
}
64-
}
65-
}
66-
}
67-
68-
void future_events_notify_th()
69-
{
70-
while (true) {
71-
m_th.suspend();
72-
update_m();
73-
}
43+
sc_core::sc_time m_scheduled;
44+
sc_core::sc_process_handle m_th;
45+
46+
void future_events_notify_th() {
47+
while (true) {
48+
m_th.suspend();
49+
50+
auto now = sc_core::sc_time_stamp();
51+
if (now >= m_scheduled) {
52+
sc_core::sc_event::notify();
53+
} else {
54+
sc_core::sc_event::notify(m_scheduled - now);
55+
}
7456
}
57+
}
7558

7659
public:
77-
sc_ob_event(const sc_core::sc_module_name& n = sc_core::sc_gen_unique_name("sc_ob_event"))
78-
: sc_module(n)
79-
, sc_core::sc_event((std::string(n) + "_notifier_event").c_str())
80-
, m_update((std::string(n) + "_update_event").c_str())
81-
, m_scheduled(sc_core::SC_ZERO_TIME)
82-
{
83-
SC_METHOD(update_m);
84-
sensitive << m_update;
85-
dont_initialize();
86-
SC_THREAD(future_events_notify_th);
87-
m_th = sc_core::sc_get_current_process_handle();
88-
}
89-
void notify()
90-
{
91-
m_scheduled = sc_core::sc_time_stamp();
92-
m_update.notify(sc_core::SC_ZERO_TIME);
93-
}
94-
void notify(double delay, sc_core::sc_time_unit unit)
95-
{
96-
m_scheduled = sc_core::sc_time_stamp() + sc_core::sc_time(delay, unit);
97-
m_update.notify(sc_core::SC_ZERO_TIME);
98-
}
99-
void notify(sc_core::sc_time delay)
100-
{
101-
m_scheduled = sc_core::sc_time_stamp() + delay;
102-
m_update.notify(sc_core::SC_ZERO_TIME);
103-
}
104-
105-
void stage_callback(const sc_core::sc_stage& stage)
106-
{
107-
if (sc_core::sc_pending_activity_at_future_time()) {
108-
m_th.resume();
109-
sc_core::sc_unregister_stage_callback(*this, sc_core::SC_POST_UPDATE);
110-
}
111-
}
112-
113-
~sc_ob_event() {}
60+
sc_ob_event(const sc_core::sc_module_name &n =
61+
sc_core::sc_gen_unique_name("sc_ob_event"))
62+
: sc_module(n), m_scheduled(sc_core::SC_ZERO_TIME) {
63+
SC_THREAD(future_events_notify_th);
64+
m_th = sc_core::sc_get_current_process_handle();
65+
}
66+
void notify() {
67+
sc_core::sc_event::notify();
68+
sc_core::sc_unregister_stage_callback(*this, sc_core::SC_POST_UPDATE);
69+
}
70+
void notify(double delay, sc_core::sc_time_unit unit) {
71+
notify(sc_core::sc_time(delay, unit));
72+
}
73+
void notify(sc_core::sc_time delay) {
74+
sc_core::sc_event::cancel();
75+
m_scheduled = sc_core::sc_time_stamp() + delay;
76+
sc_core::sc_register_stage_callback(*this, sc_core::SC_POST_UPDATE);
77+
}
78+
79+
void stage_callback(const sc_core::sc_stage &stage) {
80+
// if (sc_core::sc_pending_activity()) { // should the event fire is there is pending activity, or if we arrive at the time?
81+
sc_core::sc_time pending = sc_core::sc_time_stamp();
82+
if (sc_core::sc_pending_activity_at_future_time()) {
83+
pending += sc_core::sc_time_to_pending_activity();
84+
}
85+
86+
if (pending >= m_scheduled) {
87+
m_th.resume();
88+
sc_core::sc_unregister_stage_callback(*this, sc_core::SC_POST_UPDATE);
89+
}
90+
// }
91+
}
92+
93+
~sc_ob_event() {}
11494
};
115-
} // namespace
95+
} // namespace sc_core
11696

11797
#endif // _SC_OB_EVENT_

0 commit comments

Comments
 (0)