sc_thread_process.cpp revision 12027:1eb7dc7aa10b
1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_thread_process.cpp -- Thread process implementation
23
24  Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005
25
26 CHANGE LOG AT THE END OF THE FILE
27 *****************************************************************************/
28
29#include "sysc/kernel/sc_cmnhdr.h"
30#include "sysc/kernel/sc_constants.h"
31#include "sysc/kernel/sc_thread_process.h"
32#include "sysc/kernel/sc_process_handle.h"
33#include "sysc/kernel/sc_simcontext_int.h"
34#include "sysc/kernel/sc_module.h"
35#include "sysc/utils/sc_machine.h"
36
37// DEBUGGING MACROS:
38//
39// DEBUG_MSG(NAME,P,MSG)
40//     MSG  = message to print
41//     NAME = name that must match the process for the message to print, or
42//            null if the message should be printed unconditionally.
43//     P    = pointer to process message is for, or NULL in which case the
44//            message will not print.
45#if 0
46#   define DEBUG_NAME ""
47#   define DEBUG_MSG(NAME,P,MSG) \
48    { \
49        if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
50          std::cout << "**** " << sc_time_stamp() << " ("  \
51	            << sc_get_current_process_name() << "): " << MSG \
52		    << " - " << P->name() << std::endl; \
53    }
54#else
55#   define DEBUG_MSG(NAME,P,MSG)
56#endif
57
58
59//------------------------------------------------------------------------------
60// user-defined default stack-size
61//------------------------------------------------------------------------------
62#if defined(SC_OVERRIDE_DEFAULT_STACK_SIZE)
63#   define SC_DEFAULT_STACK_SIZE_ SC_OVERRIDE_DEFAULT_STACK_SIZE
64
65//------------------------------------------------------------------------------
66// architecture-specific default stack sizes
67//------------------------------------------------------------------------------
68#elif !defined(SC_USE_PTHREADS) && (defined(__CYGWIN32__) || defined(__CYGWIN32))
69#   define SC_DEFAULT_STACK_SIZE_ 0x50000
70
71#elif defined(SC_LONG_64) || defined(__x86_64__) || defined(__LP64__) || \
72      defined(_M_X64) || defined(_M_AMD64)
73#   define SC_DEFAULT_STACK_SIZE_ 0x40000
74
75#else
76#   define SC_DEFAULT_STACK_SIZE_ 0x20000
77
78#endif // SC_DEFAULT_STACK_SIZE_
79
80
81//------------------------------------------------------------------------------
82// force 16-byte alignment on coroutine entry functions, needed for
83// QuickThreads (32-bit, see also fixes in qt/md/{i386,iX86_64}.[hs]),
84// and MinGW32 / Cygwin32 compilers on Windows platforms
85#if defined(__GNUC__) && !defined(__ICC) && !defined(__x86_64__) && \
86    (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 1 )
87# define SC_ALIGNED_STACK_ \
88    __attribute__((force_align_arg_pointer))
89#else
90# define SC_ALIGNED_STACK_ /* empty */
91#endif
92
93
94namespace sc_core {
95
96const int SC_DEFAULT_STACK_SIZE   = SC_DEFAULT_STACK_SIZE_;
97#undef SC_DEFAULT_STACK_SIZE_
98#undef SC_OVERRIDE_DEFAULT_STACK_SIZE
99
100//------------------------------------------------------------------------------
101//"sc_thread_cor_fn"
102//
103// This function invokes the coroutine for the supplied object instance.
104//------------------------------------------------------------------------------
105SC_ALIGNED_STACK_
106void sc_thread_cor_fn( void* arg )
107{
108    sc_simcontext*   simc_p = sc_get_curr_simcontext();
109    sc_thread_handle thread_h = RCAST<sc_thread_handle>( arg );
110
111    // PROCESS THE THREAD AND PROCESS ANY EXCEPTIONS THAT ARE THROWN:
112
113    while( true ) {
114
115        try {
116            thread_h->semantics();
117        }
118        catch( sc_user ) {
119            continue;
120        }
121        catch( sc_halt ) {
122            ::std::cout << "Terminating process "
123                      << thread_h->name() << ::std::endl;
124        }
125        catch( const sc_unwind_exception& ex ) {
126	    ex.clear();
127            if ( ex.is_reset() ) continue;
128        }
129        catch( ... ) {
130            sc_report* err_p = sc_handle_exception();
131            thread_h->simcontext()->set_error( err_p );
132        }
133        break;
134    }
135
136    sc_process_b*    active_p = sc_get_current_process_b();
137
138    // REMOVE ALL TRACES OF OUR THREAD FROM THE SIMULATORS DATA STRUCTURES:
139
140    thread_h->disconnect_process();
141
142    // IF WE AREN'T ACTIVE MAKE SURE WE WON'T EXECUTE:
143
144    if ( thread_h->next_runnable() != 0 )
145    {
146	simc_p->remove_runnable_thread(thread_h);
147    }
148
149    // IF WE ARE THE ACTIVE PROCESS ABORT OUR EXECUTION:
150
151
152    if ( active_p == (sc_process_b*)thread_h )
153    {
154
155        sc_core::sc_cor* x = simc_p->next_cor();
156	simc_p->cor_pkg()->abort( x );
157    }
158
159}
160
161
162//------------------------------------------------------------------------------
163//"sc_thread_process::disable_process"
164//
165// This virtual method suspends this process and its children if requested to.
166//     descendants = indicator of whether this process' children should also
167//                   be suspended
168//------------------------------------------------------------------------------
169void sc_thread_process::disable_process(
170    sc_descendant_inclusion_info descendants )
171{
172
173    // IF NEEDED PROPOGATE THE DISABLE REQUEST THROUGH OUR DESCENDANTS:
174
175    if ( descendants == SC_INCLUDE_DESCENDANTS )
176    {
177        const std::vector<sc_object*>& children = get_child_objects();
178        int                            child_n  = children.size();
179
180        for ( int child_i = 0; child_i < child_n; child_i++ )
181        {
182            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
183            if ( child_p ) child_p->disable_process(descendants);
184        }
185    }
186
187    // DON'T ALLOW CORNER CASE BY DEFAULT:
188
189    if ( !sc_allow_process_control_corners )
190    {
191	switch( m_trigger_type )
192	{
193	  case AND_LIST_TIMEOUT:
194	  case EVENT_TIMEOUT:
195	  case OR_LIST_TIMEOUT:
196	  case TIMEOUT:
197	    report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
198		         "attempt to disable a thread with timeout wait");
199	    break;
200	  default:
201	    break;
202	}
203    }
204
205    // DISABLE OUR OBJECT INSTANCE:
206
207    m_state = m_state | ps_bit_disabled;
208
209    // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE THREAD:
210
211    if ( !sc_is_running() )
212    {
213	m_state = m_state | ps_bit_ready_to_run;
214        simcontext()->remove_runnable_thread(this);
215    }
216}
217
218//------------------------------------------------------------------------------
219//"sc_thread_process::enable_process"
220//
221// This method resumes the execution of this process, and if requested, its
222// descendants. If the process was suspended and has a resumption pending it
223// will be dispatched in the next delta cycle. Otherwise the state will be
224// adjusted to indicate it is no longer suspended, but no immediate execution
225// will occur.
226//------------------------------------------------------------------------------
227void sc_thread_process::enable_process(
228    sc_descendant_inclusion_info descendants )
229{
230
231    // IF NEEDED PROPOGATE THE ENABLE REQUEST THROUGH OUR DESCENDANTS:
232
233    if ( descendants == SC_INCLUDE_DESCENDANTS )
234    {
235        const std::vector<sc_object*>& children = get_child_objects();
236        int                            child_n  = children.size();
237
238        for ( int child_i = 0; child_i < child_n; child_i++ )
239        {
240            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
241            if ( child_p ) child_p->enable_process(descendants);
242        }
243    }
244
245    // ENABLE THIS OBJECT INSTANCE:
246    //
247    // If it was disabled and ready to run then put it on the run queue.
248
249    m_state = m_state & ~ps_bit_disabled;
250    if ( m_state == ps_bit_ready_to_run && sc_allow_process_control_corners )
251    {
252        m_state = ps_normal;
253	if ( next_runnable() == 0 )
254	    simcontext()->push_runnable_thread(this);
255    }
256}
257
258
259//------------------------------------------------------------------------------
260//"sc_thread_process::kill_process"
261//
262// This method removes this object instance from use. It calls the
263// sc_process_b::kill_process() method to perform low level clean up. Then
264// it aborts this process if it is the active process.
265//------------------------------------------------------------------------------
266void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants )
267{
268
269    // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR:
270
271    if ( !sc_is_running() )
272    {
273        report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ );
274    }
275
276    // IF NEEDED PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS:
277
278    if ( descendants == SC_INCLUDE_DESCENDANTS )
279    {
280        const std::vector<sc_object*> children = get_child_objects();
281        int                           child_n  = children.size();
282
283        for ( int child_i = 0; child_i < child_n; child_i++ )
284        {
285            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
286            if ( child_p ) child_p->kill_process(descendants);
287        }
288    }
289
290    // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE
291    // IGNORE THE KILL:
292
293    if ( m_unwinding )
294    {
295        SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
296        return;
297    }
298
299    if ( m_state & ps_bit_zombie )
300        return;
301
302    // SET UP TO KILL THE PROCESS IF SIMULATION HAS STARTED:
303    //
304    // If the thread does not have a stack don't try the throw!
305
306    if ( sc_is_running() && m_has_stack )
307    {
308        m_throw_status = THROW_KILL;
309        m_wait_cycle_n = 0;
310        simcontext()->preempt_with(this);
311    }
312
313    // IF THE SIMULATION HAS NOT STARTED REMOVE TRACES OF OUR PROCESS FROM
314    // EVENT QUEUES, ETC.:
315
316    else
317    {
318        disconnect_process();
319    }
320}
321
322//------------------------------------------------------------------------------
323//"sc_thread_process::prepare_for_simulation"
324//
325// This method prepares this object instance for simulation. It calls the
326// coroutine package to create the actual thread.
327//------------------------------------------------------------------------------
328void sc_thread_process::prepare_for_simulation()
329{
330    m_cor_p = simcontext()->cor_pkg()->create( m_stack_size,
331                         sc_thread_cor_fn, this );
332    m_cor_p->stack_protect( true );
333}
334
335
336//------------------------------------------------------------------------------
337//"sc_thread_process::resume_process"
338//
339// This method resumes the execution of this process, and if requested, its
340// descendants. If the process was suspended and has a resumption pending it
341// will be dispatched in the next delta cycle. Otherwise the state will be
342// adjusted to indicate it is no longer suspended, but no immediate execution
343// will occur.
344//------------------------------------------------------------------------------
345void sc_thread_process::resume_process(
346    sc_descendant_inclusion_info descendants )
347{
348
349    // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS:
350
351    if ( descendants == SC_INCLUDE_DESCENDANTS )
352    {
353        const std::vector<sc_object*>& children = get_child_objects();
354        int                            child_n  = children.size();
355
356        for ( int child_i = 0; child_i < child_n; child_i++ )
357        {
358            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
359            if ( child_p ) child_p->resume_process(descendants);
360        }
361    }
362
363    // BY DEFAULT THE CORNER CASE IS AN ERROR:
364
365    if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) &&
366         (m_state & ps_bit_suspended) )
367    {
368	m_state = m_state & ~ps_bit_suspended;
369        report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
370	             "call to resume() on a disabled suspended thread");
371    }
372
373    // CLEAR THE SUSPENDED BIT:
374
375    m_state = m_state & ~ps_bit_suspended;
376
377    // RESUME OBJECT INSTANCE IF IT IS READY TO RUN:
378
379    if ( m_state & ps_bit_ready_to_run )
380    {
381	m_state = m_state & ~ps_bit_ready_to_run;
382	if ( next_runnable() == 0 )
383	    simcontext()->push_runnable_thread(this);
384	remove_dynamic_events();  // order important.
385    }
386}
387
388//------------------------------------------------------------------------------
389//"sc_thread_process::sc_thread_process"
390//
391// This is the object instance constructor for this class.
392//------------------------------------------------------------------------------
393sc_thread_process::sc_thread_process( const char* name_p, bool free_host,
394    SC_ENTRY_FUNC method_p, sc_process_host* host_p,
395    const sc_spawn_options* opt_p
396):
397    sc_process_b(
398        name_p ? name_p : sc_gen_unique_name("thread_p"),
399        true, free_host, method_p, host_p, opt_p),
400    m_cor_p(0), m_monitor_q(), m_stack_size(SC_DEFAULT_STACK_SIZE),
401    m_wait_cycle_n(0)
402{
403
404    // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMULATION HAS STARTED:
405
406    if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() )
407    {
408        report_error( SC_ID_MODULE_THREAD_AFTER_START_ );
409    }
410
411    // INITIALIZE VALUES:
412    //
413    // If there are spawn options use them.
414
415    m_process_kind = SC_THREAD_PROC_;
416
417    if (opt_p) {
418        m_dont_init = opt_p->m_dont_initialize;
419        if ( opt_p->m_stack_size ) m_stack_size = opt_p->m_stack_size;
420
421        // traverse event sensitivity list
422        for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) {
423            sc_sensitive::make_static_sensitivity(
424                this, *opt_p->m_sensitive_events[i]);
425        }
426
427        // traverse port base sensitivity list
428        for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++)
429        {
430            sc_sensitive::make_static_sensitivity(
431                this, *opt_p->m_sensitive_port_bases[i]);
432        }
433
434        // traverse interface sensitivity list
435        for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++)
436        {
437            sc_sensitive::make_static_sensitivity(
438                this, *opt_p->m_sensitive_interfaces[i]);
439        }
440
441        // traverse event finder sensitivity list
442        for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size();
443            i++)
444        {
445            sc_sensitive::make_static_sensitivity(
446                this, *opt_p->m_sensitive_event_finders[i]);
447        }
448
449        // process any reset signal specification:
450
451	opt_p->specify_resets();
452
453    }
454
455    else
456    {
457        m_dont_init = false;
458    }
459
460}
461
462//------------------------------------------------------------------------------
463//"sc_thread_process::~sc_thread_process"
464//
465// This is the object instance constructor for this class.
466//------------------------------------------------------------------------------
467sc_thread_process::~sc_thread_process()
468{
469
470    // DESTROY THE COROUTINE FOR THIS THREAD:
471
472    if( m_cor_p != 0 ) {
473        m_cor_p->stack_protect( false );
474        delete m_cor_p;
475        m_cor_p = 0;
476    }
477}
478
479
480//------------------------------------------------------------------------------
481//"sc_thread_process::signal_monitors"
482//
483// This methods signals the list of monitors for this object instance.
484//------------------------------------------------------------------------------
485void sc_thread_process::signal_monitors(int type)
486{
487    int mon_n;  // # of monitors present.
488
489    mon_n = m_monitor_q.size();
490    for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
491        m_monitor_q[mon_i]->signal(this, type);
492}
493
494
495//------------------------------------------------------------------------------
496//"sc_thread_process::suspend_process"
497//
498// This virtual method suspends this process and its children if requested to.
499//     descendants = indicator of whether this process' children should also
500//                   be suspended
501//------------------------------------------------------------------------------
502void sc_thread_process::suspend_process(
503    sc_descendant_inclusion_info descendants )
504{
505
506    // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS:
507
508    if ( descendants == SC_INCLUDE_DESCENDANTS )
509    {
510        const std::vector<sc_object*>& children = get_child_objects();
511        int                            child_n  = children.size();
512
513        for ( int child_i = 0; child_i < child_n; child_i++ )
514        {
515            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
516            if ( child_p ) child_p->suspend_process(descendants);
517        }
518    }
519
520    // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS:
521    //   (a) if this thread has a reset_signal_is specification
522    //   (b) if this thread is in synchronous reset
523
524    if ( !sc_allow_process_control_corners && m_has_reset_signal )
525    {
526	report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
527		     "attempt to suspend a thread that has a reset signal");
528    }
529    else if ( !sc_allow_process_control_corners && m_sticky_reset )
530    {
531	report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_,
532		     "attempt to suspend a thread in synchronous reset");
533    }
534
535    // SUSPEND OUR OBJECT INSTANCE:
536    //
537    // (1) If we are on the runnable queue then set suspended and ready_to_run,
538    //     and remove ourselves from the run queue.
539    // (2) If this is a self-suspension then a resume should cause immediate
540    //     scheduling of the process, and we need to call suspend_me() here.
541
542    m_state = m_state | ps_bit_suspended;
543    if ( next_runnable() != 0 )
544    {
545	m_state = m_state | ps_bit_ready_to_run;
546	simcontext()->remove_runnable_thread( this );
547    }
548    if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this)  )
549    {
550	m_state = m_state | ps_bit_ready_to_run;
551	suspend_me();
552    }
553}
554
555//------------------------------------------------------------------------------
556//"sc_thread_process::throw_reset"
557//
558// This virtual method is invoked when an reset is to be thrown. The
559// method will cancel any dynamic waits. If the reset is asynchronous it will
560// queue this object instance to be executed.
561//------------------------------------------------------------------------------
562void sc_thread_process::throw_reset( bool async )
563{
564    // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE
565    // IGNORE THE RESET:
566
567    if ( m_unwinding )
568    {
569        SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
570        return;
571    }
572
573    if ( m_state & ps_bit_zombie )
574        return;
575
576
577    // Set the throw type and clear any pending dynamic events:
578
579    m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET;
580    m_wait_cycle_n = 0;
581
582    // If this is an asynchronous reset:
583    //
584    //   (a) Cancel any dynamic events
585    //   (b) Set the thread up for execution:
586    //         (i) If we are in the execution phase do it now.
587    //         (ii) If we are not queue it to execute next when we hit
588    //              the execution phase.
589
590    if ( async )
591    {
592        m_state = m_state & ~ps_bit_ready_to_run;
593        remove_dynamic_events();
594	if ( simcontext()->evaluation_phase() )
595	{
596            simcontext()->preempt_with( this );
597	}
598	else
599	{
600	    if ( is_runnable() )
601	        simcontext()->remove_runnable_thread(this);
602	    simcontext()->execute_thread_next(this);
603	}
604    }
605}
606
607
608//------------------------------------------------------------------------------
609//"sc_thread_process::throw_user"
610//
611// This virtual method is invoked when a user exception is to be thrown.
612// If requested it will also throw the exception to the children of this
613// object instance. The order of dispatch for the processes that are
614// thrown the exception is from youngest child to oldest child and then
615// this process instance. This means that this instance will be pushed onto
616// the front of the simulator's runnable queue and then the children will
617// be processed recursively.
618//     helper_p    =  helper object to use to throw the exception.
619//     descendants =  indicator of whether this process' children should also
620//                    be suspended
621//------------------------------------------------------------------------------
622void sc_thread_process::throw_user( const sc_throw_it_helper& helper,
623    sc_descendant_inclusion_info descendants )
624{
625
626    // IF THE SIMULATION IS NOT ACTAULLY RUNNING THIS IS AN ERROR:
627
628    if ( sc_get_status() != SC_RUNNING )
629    {
630        report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ );
631    }
632
633    // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS:
634
635    if ( descendants == SC_INCLUDE_DESCENDANTS )
636    {
637        const std::vector<sc_object*> children = get_child_objects();
638        int                           child_n  = children.size();
639
640        for ( int child_i = 0; child_i < child_n; child_i++ )
641        {
642            sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]);
643            if ( child_p )
644	    {
645	        DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on");
646	        child_p->throw_user(helper, descendants);
647	    }
648        }
649    }
650
651    // IF THE PROCESS IS CURRENTLY UNWINDING IGNORE THE THROW:
652
653    if ( m_unwinding )
654    {
655        SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() );
656	return;
657    }
658
659    // SET UP THE THROW REQUEST FOR THIS OBJECT INSTANCE AND QUEUE IT FOR
660    // EXECUTION:
661
662    if( m_has_stack )
663    {
664        remove_dynamic_events();
665        DEBUG_MSG(DEBUG_NAME,this,"throwing user exception to");
666        m_throw_status = THROW_USER;
667        if ( m_throw_helper_p != 0 ) delete m_throw_helper_p;
668        m_throw_helper_p = helper.clone();
669        simcontext()->preempt_with( this );
670    }
671    else
672    {
673        SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() );
674    }
675}
676
677
678//------------------------------------------------------------------------------
679//"sc_thread_process::trigger_dynamic"
680//
681// This method sets up a dynamic trigger on an event.
682//
683// Notes:
684//   (1) This method is identical to sc_method_process::trigger_dynamic(),
685//       but they cannot be combined as sc_process_b::trigger_dynamic()
686//       because the signatures things like sc_event::remove_dynamic()
687//       have different overloads for sc_thread_process* and sc_method_process*.
688//       So if you change code here you'll also need to change it in
689//       sc_method_process.cpp.
690//
691// Result is true if this process should be removed from the event's list,
692// false if not.
693//------------------------------------------------------------------------------
694bool sc_thread_process::trigger_dynamic( sc_event* e )
695{
696    // No time outs yet, and keep gcc happy.
697
698    m_timed_out = false;
699
700    // Escape cases:
701    //   (a) If this thread issued the notify() don't schedule it for
702    //       execution, but leave the sensitivity in place.
703    //   (b) If this thread is already runnable can't trigger an event.
704
705    // not possible for thread processes!
706#if 0 // ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS )
707    if ( sc_get_current_process_b() == (sc_process_b*)this )
708    {
709        report_immediate_self_notification();
710        return false;
711    }
712#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
713
714    if( is_runnable() )
715        return true;
716
717    // If a process is disabled then we ignore any events, leaving them enabled:
718    //
719    // But if this is a time out event we need to remove both it and the
720    // event that was being waited for.
721
722    if ( m_state & ps_bit_disabled )
723    {
724        if ( e == m_timeout_event_p )
725	{
726	    remove_dynamic_events( true );
727	    return true;
728	}
729	else
730	{
731	    return false;
732	}
733    }
734
735
736    // Process based on the event type and current process state:
737    //
738    // Every case needs to set 'rc' and continue on to the end of
739    // this method to allow suspend processing to work correctly.
740
741    switch( m_trigger_type )
742    {
743      case EVENT:
744	m_event_p = 0;
745	m_trigger_type = STATIC;
746	break;
747
748      case AND_LIST:
749        -- m_event_count;
750	if ( m_event_count == 0 )
751	{
752	    m_event_list_p->auto_delete();
753	    m_event_list_p = 0;
754	    m_trigger_type = STATIC;
755	}
756	else
757	{
758	    return true;
759	}
760	break;
761
762      case OR_LIST:
763	m_event_list_p->remove_dynamic( this, e );
764	m_event_list_p->auto_delete();
765	m_event_list_p = 0;
766	m_trigger_type = STATIC;
767	break;
768
769      case TIMEOUT:
770	m_trigger_type = STATIC;
771	break;
772
773      case EVENT_TIMEOUT:
774        if ( e == m_timeout_event_p )
775	{
776	    m_timed_out = true;
777	    m_event_p->remove_dynamic( this );
778	    m_event_p = 0;
779	    m_trigger_type = STATIC;
780	}
781	else
782	{
783	    m_timeout_event_p->cancel();
784	    m_timeout_event_p->reset();
785	    m_event_p = 0;
786	    m_trigger_type = STATIC;
787	}
788	break;
789
790      case OR_LIST_TIMEOUT:
791        if ( e == m_timeout_event_p )
792	{
793            m_timed_out = true;
794            m_event_list_p->remove_dynamic( this, e );
795            m_event_list_p->auto_delete();
796            m_event_list_p = 0;
797            m_trigger_type = STATIC;
798	}
799
800	else
801	{
802            m_timeout_event_p->cancel();
803            m_timeout_event_p->reset();
804	    m_event_list_p->remove_dynamic( this, e );
805	    m_event_list_p->auto_delete();
806	    m_event_list_p = 0;
807	    m_trigger_type = STATIC;
808	}
809	break;
810
811      case AND_LIST_TIMEOUT:
812        if ( e == m_timeout_event_p )
813	{
814            m_timed_out = true;
815            m_event_list_p->remove_dynamic( this, e );
816            m_event_list_p->auto_delete();
817            m_event_list_p = 0;
818            m_trigger_type = STATIC;
819	}
820
821	else
822	{
823	    -- m_event_count;
824	    if ( m_event_count == 0 )
825	    {
826		m_timeout_event_p->cancel();
827		m_timeout_event_p->reset();
828		// no need to remove_dynamic
829		m_event_list_p->auto_delete();
830		m_event_list_p = 0;
831		m_trigger_type = STATIC;
832	    }
833	    else
834	    {
835	        return true;
836	    }
837	}
838	break;
839
840      case STATIC: {
841        // we should never get here, but throw_it() can make it happen.
842	SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name());
843        return true;
844      }
845    }
846
847    // If we get here then the thread is has satisfied its wait criteria, if
848    // its suspended mark its state as ready to run. If its not suspended then
849    // push it onto the runnable queue.
850
851    if ( (m_state & ps_bit_suspended) )
852    {
853	m_state = m_state | ps_bit_ready_to_run;
854    }
855    else
856    {
857        simcontext()->push_runnable_thread(this);
858    }
859
860    return true;
861}
862
863
864//------------------------------------------------------------------------------
865//"sc_set_stack_size"
866//
867//------------------------------------------------------------------------------
868void
869sc_set_stack_size( sc_thread_handle thread_h, std::size_t size )
870{
871    thread_h->set_stack_size( size );
872}
873
874#undef DEBUG_MSG
875#undef DEBUG_NAME
876
877} // namespace sc_core
878
879
880/*****************************************************************************
881
882  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
883  changes you are making here.
884
885      Name, Affiliation, Date:
886  Description of Modification:
887
888 *****************************************************************************/
889
890// $Log: sc_thread_process.cpp,v $
891// Revision 1.57  2011/08/24 22:05:51  acg
892//  Torsten Maehne: initialization changes to remove warnings.
893//
894// Revision 1.56  2011/08/07 19:08:04  acg
895//  Andy Goodrich: moved logs to end of file so line number synching works
896//  better between versions.
897//
898// Revision 1.55  2011/08/04 17:16:22  acg
899//  Philipp A. Hartmann: fix handling of child objects in kill routine, need
900//  to use a copy rather than a reference.
901//
902// Revision 1.53  2011/07/29 22:45:38  acg
903//  Philipp A. Hartmann: changes to handle case where a process control
904//  invocation on a child process causes the list of child processes to change.
905//
906// Revision 1.52  2011/07/24 11:27:04  acg
907//  Andy Goodrich: moved the check for unwinding processes until after the
908//  descendants have been processed in throw_user and kill.
909//
910// Revision 1.51  2011/07/24 11:20:03  acg
911//  Philipp A. Hartmann: process control error message improvements:
912//  (1) Downgrade error to warning for re-kills of processes.
913//  (2) Add process name to process messages.
914//  (3) drop some superfluous colons in messages.
915//
916// Revision 1.50  2011/05/09 04:07:49  acg
917//  Philipp A. Hartmann:
918//    (1) Restore hierarchy in all phase callbacks.
919//    (2) Ensure calls to before_end_of_elaboration.
920//
921// Revision 1.49  2011/05/05 17:45:27  acg
922//  Philip A. Hartmann: changes in WIN64 support.
923//  Andy Goodrich: additional DEBUG_MSG instances to trace process handling.
924//
925// Revision 1.48  2011/04/19 15:04:27  acg
926//  Philipp A. Hartmann: clean up SC_ID messages.
927//
928// Revision 1.47  2011/04/19 02:39:09  acg
929//  Philipp A. Hartmann: added checks for additional throws during stack unwinds.
930//
931// Revision 1.46  2011/04/14 22:33:43  acg
932//  Andy Goodrich: added missing checks for a process being a zombie.
933//
934// Revision 1.45  2011/04/13 02:45:11  acg
935//  Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG
936//  macro was used.
937//
938// Revision 1.44  2011/04/11 22:04:33  acg
939//  Andy Goodrich: use the DEBUG_NAME macro for DEBUG_MSG messages.
940//
941// Revision 1.43  2011/04/10 22:12:32  acg
942//  Andy Goodrich: adding debugging macros.
943//
944// Revision 1.42  2011/04/08 22:40:26  acg
945//  Andy Goodrich: moved the reset event notification code out of throw_reset()
946//  and into suspend_me.
947//
948// Revision 1.41  2011/04/08 18:24:07  acg
949//  Andy Goodrich: fix asynchronous reset dispatch and when the reset_event()
950//  is fired.
951//
952// Revision 1.40  2011/04/05 20:50:57  acg
953//  Andy Goodrich:
954//    (1) changes to make sure that event(), posedge() and negedge() only
955//        return true if the clock has not moved.
956//    (2) fixes for method self-resumes.
957//    (3) added SC_PRERELEASE_VERSION
958//    (4) removed kernel events from the object hierarchy, added
959//        sc_hierarchy_name_exists().
960//
961// Revision 1.39  2011/04/01 22:30:39  acg
962//  Andy Goodrich: change hard assertion to warning for trigger_dynamic()
963//  getting called when there is only STATIC sensitivity. This can result
964//  because of sc_process_handle::throw_it().
965//
966// Revision 1.38  2011/03/23 16:17:52  acg
967//  Andy Goodrich: don't emit an error message for a resume on a disabled
968//  process that is not suspended.
969//
970// Revision 1.37  2011/03/20 13:43:23  acg
971//  Andy Goodrich: added async_signal_is() plus suspend() as a corner case.
972//
973// Revision 1.36  2011/03/08 20:49:31  acg
974//  Andy Goodrich: implement coarse checking for synchronous reset - suspend
975//  interaction.
976//
977// Revision 1.35  2011/03/08 20:32:28  acg
978//  Andy Goodrich: implemented "coarse" checking for undefined process
979//  control interactions.
980//
981// Revision 1.34  2011/03/07 18:25:19  acg
982//  Andy Goodrich: tightening of check for resume on a disabled process to
983//  only produce an error if it is ready to run.
984//
985// Revision 1.33  2011/03/07 17:38:44  acg
986//  Andy Goodrich: tightening up of checks for undefined interaction between
987//  synchronous reset and suspend.
988//
989// Revision 1.32  2011/03/06 23:30:13  acg
990//  Andy Goodrich: refining suspend - sync reset corner case checking so that
991//  the following are error situations:
992//    (1) Calling suspend on a process with a reset_signal_is() specification
993//        or sync_reset_on() is active.
994//    (2) Calling sync_reset_on() on a suspended process.
995//
996// Revision 1.31  2011/03/06 19:57:11  acg
997//  Andy Goodrich: refinements for the illegal suspend - synchronous reset
998//  interaction.
999//
1000// Revision 1.30  2011/03/06 16:47:09  acg
1001//  Andy Goodrich: changes for testing sync_reset - suspend corner cases.
1002//
1003// Revision 1.29  2011/03/06 15:59:23  acg
1004//  Andy Goodrich: added process control corner case checks.
1005//
1006// Revision 1.28  2011/03/05 19:44:20  acg
1007//  Andy Goodrich: changes for object and event naming and structures.
1008//
1009// Revision 1.27  2011/02/19 08:30:53  acg
1010//  Andy Goodrich: Moved process queueing into trigger_static from
1011//  sc_event::notify.
1012//
1013// Revision 1.26  2011/02/18 20:27:14  acg
1014//  Andy Goodrich: Updated Copyrights.
1015//
1016// Revision 1.25  2011/02/17 19:54:33  acg
1017//  Andy Goodrich:
1018//    (1) Changed signature of trigger_dynamic() back to bool, and moved
1019//        run queue processing into trigger_dynamic.
1020//    (2) Simplified process control usage.
1021//
1022// Revision 1.24  2011/02/16 22:37:31  acg
1023//  Andy Goodrich: clean up to remove need for ps_disable_pending.
1024//
1025// Revision 1.23  2011/02/14 17:51:40  acg
1026//  Andy Goodrich: proper pushing an poppping of the module hierarchy for
1027//  start_of_simulation() and end_of_simulation.
1028//
1029// Revision 1.22  2011/02/13 23:09:58  acg
1030//  Andy Goodrich: only remove dynamic events for asynchronous resets.
1031//
1032// Revision 1.21  2011/02/13 21:47:38  acg
1033//  Andy Goodrich: update copyright notice.
1034//
1035// Revision 1.20  2011/02/13 21:37:13  acg
1036//  Andy Goodrich: removed temporary diagnostic. Also there is
1037//  remove_dynamic_events() call in reset code.
1038//
1039// Revision 1.19  2011/02/13 21:35:09  acg
1040//  Andy Goodrich: added error messages for throws before the simulator is
1041//  initialized.
1042//
1043// Revision 1.18  2011/02/11 13:25:24  acg
1044//  Andy Goodrich: Philipp A. Hartmann's changes:
1045//    (1) Removal of SC_CTHREAD method overloads.
1046//    (2) New exception processing code.
1047//
1048// Revision 1.17  2011/02/08 08:18:16  acg
1049//  Andy Goodrich: removed obsolete code.
1050//
1051// Revision 1.16  2011/02/07 19:17:20  acg
1052//  Andy Goodrich: changes for IEEE 1666 compatibility.
1053//
1054// Revision 1.15  2011/02/04 15:27:36  acg
1055//  Andy Goodrich: changes for suspend-resume semantics.
1056//
1057// Revision 1.14  2011/02/01 23:01:53  acg
1058//  Andy Goodrich: removed dead code.
1059//
1060// Revision 1.13  2011/02/01 21:16:36  acg
1061//  Andy Goodrich:
1062//  (1) New version of trigger_dynamic() to implement new return codes and
1063//      proper processing of events with new dynamic process rules.
1064//  (2) Recoding of kill_process(), throw_user() and reset support to
1065//      consolidate preemptive thread execution in sc_simcontext::preempt_with().
1066//
1067// Revision 1.12  2011/01/25 20:50:37  acg
1068//  Andy Goodrich: changes for IEEE 1666 2011.
1069//
1070// Revision 1.11  2011/01/20 16:52:20  acg
1071//  Andy Goodrich: changes for IEEE 1666 2011.
1072//
1073// Revision 1.10  2011/01/19 23:21:50  acg
1074//  Andy Goodrich: changes for IEEE 1666 2011
1075//
1076// Revision 1.9  2011/01/18 20:10:45  acg
1077//  Andy Goodrich: changes for IEEE1666_2011 semantics.
1078//
1079// Revision 1.8  2011/01/06 18:02:16  acg
1080//  Andy Goodrich: added check for disabled thread to trigger_dynamic().
1081//
1082// Revision 1.7  2010/11/20 17:10:57  acg
1083//  Andy Goodrich: reset processing changes for new IEEE 1666 standard.
1084//
1085// Revision 1.6  2010/07/22 20:02:33  acg
1086//  Andy Goodrich: bug fixes.
1087//
1088// Revision 1.5  2009/07/28 01:10:53  acg
1089//  Andy Goodrich: updates for 2.3 release candidate.
1090//
1091// Revision 1.4  2009/05/22 16:06:29  acg
1092//  Andy Goodrich: process control updates.
1093//
1094// Revision 1.3  2008/05/22 17:06:06  acg
1095//  Andy Goodrich: formatting and comments.
1096//
1097// Revision 1.2  2007/09/20 20:32:35  acg
1098//  Andy Goodrich: changes to the semantics of throw_it() to match the
1099//  specification. A call to throw_it() will immediately suspend the calling
1100//  thread until all the throwees have executed. At that point the calling
1101//  thread will be restarted before the execution of any other threads.
1102//
1103// Revision 1.1.1.1  2006/12/15 20:20:05  acg
1104// SystemC 2.3
1105//
1106// Revision 1.8  2006/04/20 17:08:17  acg
1107//  Andy Goodrich: 3.0 style process changes.
1108//
1109// Revision 1.7  2006/04/11 23:13:21  acg
1110//   Andy Goodrich: Changes for reduced reset support that only includes
1111//   sc_cthread, but has preliminary hooks for expanding to method and thread
1112//   processes also.
1113//
1114// Revision 1.6  2006/03/21 00:00:34  acg
1115//   Andy Goodrich: changed name of sc_get_current_process_base() to be
1116//   sc_get_current_process_b() since its returning an sc_process_b instance.
1117//
1118// Revision 1.5  2006/01/26 21:04:55  acg
1119//  Andy Goodrich: deprecation message changes and additional messages.
1120//
1121// Revision 1.4  2006/01/24 20:49:05  acg
1122// Andy Goodrich: changes to remove the use of deprecated features within the
1123// simulator, and to issue warning messages when deprecated features are used.
1124//
1125// Revision 1.3  2006/01/13 18:44:30  acg
1126// Added $Log to record CVS changes into the source.
1127//
1128