00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #if !defined(sc_thread_process_h_INCLUDED)
00030 #define sc_thread_process_h_INCLUDED
00031
00032 #include "sysc/kernel/sc_spawn_options.h"
00033 #include "sysc/kernel/sc_process.h"
00034 #include "sysc/kernel/sc_cor.h"
00035 #include "sysc/kernel/sc_event.h"
00036 #include "sysc/kernel/sc_except.h"
00037 #include "sysc/kernel/sc_reset.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #if 0
00048 # define DEBUG_NAME ""
00049 # define DEBUG_MSG(NAME,P,MSG) \
00050 { \
00051 if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
00052 std::cout << "**** " << sc_time_stamp() << " (" \
00053 << sc_get_current_process_name() << "): " << MSG \
00054 << " - " << P->name() << std::endl; \
00055 }
00056 #else
00057 # define DEBUG_MSG(NAME,P,MSG)
00058 #endif
00059
00060
00061 #ifndef _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR
00062 #define _SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR "SYSC_PRINT_VERBOSE_MESSAGE"
00063 #endif
00064 namespace sc_core {
00065
00066
00067 class sc_event_and_list;
00068 class sc_event_or_list;
00069 class sc_reset;
00070 void sc_thread_cor_fn( void* );
00071 void sc_set_stack_size( sc_thread_handle, std::size_t );
00072 class sc_event;
00073 class sc_join;
00074 class sc_module;
00075 class sc_process_handle;
00076 class sc_process_table;
00077 class sc_simcontext;
00078 class sc_runnable;
00079
00080 sc_cor* get_cor_pointer( sc_process_b* process_p );
00081 void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size );
00082 void wait( int, sc_simcontext* );
00083 void wait( const sc_event&, int, sc_simcontext* );
00084 void wait( const sc_event_or_list&, int, sc_simcontext* );
00085 void wait( const sc_event_and_list&, int, sc_simcontext* );
00086 void wait( const sc_time&, int, sc_simcontext* );
00087 void wait( const sc_time&, const sc_event&, int, sc_simcontext* );
00088 void wait( const sc_time&, const sc_event_or_list&, int, sc_simcontext* );
00089 void wait( const sc_time&, const sc_event_and_list&, int, sc_simcontext* );
00090
00091
00096 class sc_thread_process : public sc_process_b {
00097 friend void sc_thread_cor_fn( void* );
00098 friend void sc_set_stack_size( sc_thread_handle, std::size_t );
00099 friend class sc_event;
00100 friend class sc_join;
00101 friend class sc_module;
00102
00103
00104 friend class sc_channel;
00105
00106 friend class sc_process_b;
00107 friend class sc_process_handle;
00108 friend class sc_process_table;
00109 friend class sc_simcontext;
00110 friend class sc_runnable;
00111 friend sc_cor* get_cor_pointer( sc_process_b* process_p );
00112
00113
00114 friend void wait( int, sc_simcontext* );
00115 friend void wait( const sc_event&, int, sc_simcontext* );
00116 friend void wait( const sc_event_or_list&, int, sc_simcontext* );
00117 friend void wait( const sc_event_and_list&, int, sc_simcontext* );
00118 friend void wait( const sc_time&, int, sc_simcontext* );
00119 friend void wait( const sc_time&, const sc_event&, int, sc_simcontext* );
00120 friend void wait( const sc_time&, const sc_event_or_list&, int,
00121 sc_simcontext* );
00122 friend void wait( const sc_time&, const sc_event_and_list&, int,
00123 sc_simcontext*);
00124
00125 public:
00126 sc_event* waiting_event;
00127 sc_timestamp first_triggerable_time;
00128 sc_thread_process( const char* name_p, bool free_host,
00129 SC_ENTRY_FUNC method_p, sc_process_host* host_p,
00130 const sc_spawn_options* opt_p );
00131
00132 virtual const char* kind() const
00133 { return "sc_thread_process"; }
00137 bool is_and_list_triggered();
00138 void aux_boundary();
00139 protected:
00140
00141 virtual ~sc_thread_process();
00142
00143 virtual void disable_process(
00144 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00145 virtual void enable_process(
00146 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00147 virtual void kill_process(
00148 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00149 sc_thread_handle next_exist();
00150 sc_thread_handle next_runnable();
00151 virtual void prepare_for_simulation();
00152 virtual void resume_process(
00153 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00154 void set_next_exist( sc_thread_handle next_p );
00155 void set_next_runnable( sc_thread_handle next_p );
00156
00157 void set_stack_size( std::size_t size );
00158 inline void suspend_me();
00159 virtual void suspend_process(
00160 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00161 virtual void throw_reset( bool async );
00162 virtual void throw_user( const sc_throw_it_helper& helper,
00163 sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS );
00164
00165 bool trigger_dynamic( sc_event* );
00166 bool can_be_triggered(sc_timestamp,sc_event*,int);
00171
00172
00173 inline void trigger_static( sc_event* );
00174
00175
00176
00181
00182 void wait( const sc_event&, int );
00183
00188
00189 void wait( const sc_event_or_list&, int );
00190
00195
00196 void wait( const sc_event_and_list&, int );
00197
00202
00203 void wait( const sc_time&, int );
00204
00209
00210 void wait( const sc_time&, const sc_event&, int );
00211
00216
00217 void wait( const sc_time&, const sc_event_or_list&, int );
00218
00223
00224 void wait( const sc_time&, const sc_event_and_list&, int );
00225
00230
00231 void wait_cycles( int, int n=1 );
00232
00233 protected:
00234 void add_monitor( sc_process_monitor* monitor_p );
00235 void remove_monitor( sc_process_monitor* monitor_p);
00236 void signal_monitors( int type = 0 );
00237
00238 protected:
00239 sc_cor* m_cor_p;
00240 std::vector<sc_process_monitor*> m_monitor_q;
00241 std::size_t m_stack_size;
00242 int m_wait_cycle_n;
00243
00244 private:
00245 sc_thread_process( const sc_thread_process& );
00246 const sc_thread_process& operator = ( const sc_thread_process& );
00247
00248 };
00249
00250
00251
00252
00253
00254 inline void sc_thread_process::set_stack_size( std::size_t size )
00255 {
00256 assert( size );
00257 m_stack_size = size;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 inline void sc_thread_process::suspend_me()
00280 {
00281
00282 #ifdef SC_LOCK_CHECK
00283 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00284 #endif
00285
00286
00287
00288 bool unwinding_preempted = m_unwinding;
00289
00290 sc_simcontext* simc_p = simcontext();
00291
00292
00293 simc_p->remove_running_process( (sc_process_b*)this );
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00304 printf("%s is calling suspend_me()\n",this->name());
00305 simc_p->oooschedule( m_cor_p );
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 if ( !simc_p->is_running_process( (sc_process_b*)this ) )
00318 {
00319 DEBUG_MSG( DEBUG_NAME , this, "suspending thread");
00320 simc_p->suspend_cor( m_cor_p );
00321 DEBUG_MSG( DEBUG_NAME , this, "resuming thread");
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331 if ( m_throw_status == THROW_NONE ) return;
00332
00333 if ( m_unwinding ) return;
00334
00335 switch( m_throw_status )
00336 {
00337 case THROW_ASYNC_RESET:
00338 case THROW_SYNC_RESET:
00339 DEBUG_MSG( DEBUG_NAME , this, "throwing reset for");
00340 if ( m_reset_event_p ) m_reset_event_p->notify();
00341 throw sc_unwind_exception( this, true );
00342
00343 case THROW_USER:
00344 DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for");
00345 m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET :
00346 (m_active_reset_n ? THROW_SYNC_RESET :
00347 THROW_NONE);
00348 m_throw_helper_p->throw_it();
00349 break;
00350
00351 case THROW_KILL:
00352 DEBUG_MSG( DEBUG_NAME, this, "throwing kill for");
00353 throw sc_unwind_exception( this, false );
00354
00355 default:
00356 sc_assert( unwinding_preempted );
00357 DEBUG_MSG( DEBUG_NAME, this, "restarting thread");
00358 break;
00359 }
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 inline
00446 void
00447 sc_thread_process::aux_boundary()
00448 {
00449
00450
00451
00452
00453 if( m_unwinding )
00454 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00455
00456 {
00457
00458 sc_kernel_lock lock;
00459
00460 #ifdef SC_LOCK_CHECK
00461 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00462 #endif
00463
00464
00465 set_segment_id( -2 );
00466
00467 unlock_all_channels();
00468
00469
00470
00471 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00472 printf("\n%s is calling wait for nothing\n",this->name());
00473
00474
00475 sc_get_curr_simcontext()->oooschedule( m_cor_p );
00476
00477 }
00478 #ifdef SC_LOCK_CHECK
00479 assert( sc_get_curr_simcontext()->is_not_owner() );
00480 #endif
00481 lock_all_channels();
00482
00483
00484
00485 }
00486
00487 inline
00488 void
00489 sc_thread_process::wait( const sc_event& e, int seg_id )
00490 {
00491
00492
00493
00494 if( m_unwinding )
00495 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00496
00497 {
00498
00499 sc_kernel_lock lock;
00500
00501 #ifdef SC_LOCK_CHECK
00502 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00503 #endif
00504
00505
00506 set_segment_id( seg_id );
00507
00508 unlock_all_channels();
00509 m_event_p = &e;
00510 e.add_dynamic( this );
00511
00512
00513 m_trigger_type = EVENT;
00514
00515
00516 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00517 printf("\n%s is calling wait for event %s\n",this->name(),e.name());
00518 this->m_process_state=2;
00519 sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
00520
00521
00522
00523 suspend_me();
00524
00525 }
00526 #ifdef SC_LOCK_CHECK
00527 assert( sc_get_curr_simcontext()->is_not_owner() );
00528 #endif
00529 lock_all_channels();
00530 }
00531
00532 inline
00533 void
00534 sc_thread_process::wait( const sc_event_or_list& el, int seg_id )
00535 {
00536 if( m_unwinding )
00537 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00538
00539 {
00540
00541 sc_kernel_lock lock;
00542
00543 #ifdef SC_LOCK_CHECK
00544 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00545 #endif
00546
00547
00548 set_segment_id( seg_id );
00549
00550 unlock_all_channels();
00551 el.add_dynamic( this );
00552 m_event_list_p = ⪙
00553 m_trigger_type = OR_LIST;
00554 suspend_me();
00555
00556 }
00557 #ifdef SC_LOCK_CHECK
00558 assert( sc_get_curr_simcontext()->is_not_owner() );
00559 #endif
00560 lock_all_channels();
00561 }
00562
00563 inline
00564 void
00565 sc_thread_process::wait( const sc_event_and_list& el, int seg_id )
00566 {
00567 if( m_unwinding )
00568 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00569
00570 {
00571
00572 sc_kernel_lock lock;
00573
00574 #ifdef SC_LOCK_CHECK
00575 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00576 #endif
00577
00578
00579 set_segment_id( seg_id );
00580
00581 unlock_all_channels();
00582 el.add_dynamic( this );
00583 m_event_list_p = ⪙
00584 m_event_count = el.size();
00585 m_trigger_type = AND_LIST;
00586
00587
00588 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00589 printf("\n%s is calling wait for event list\n",this->name());
00590 this->m_process_state=2;
00591 sc_get_curr_simcontext()->add_to_wait_queue( (sc_process_b*)this ) ;
00592
00593
00594 suspend_me();
00595
00596 }
00597 #ifdef SC_LOCK_CHECK
00598 assert( sc_get_curr_simcontext()->is_not_owner() );
00599 #endif
00600 lock_all_channels();
00601 }
00602
00603 inline
00604 void
00605 sc_thread_process::wait( const sc_time& t, int seg_id )
00606 {
00607
00608 if( m_unwinding )
00609 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00610
00611 {
00612
00613 sc_kernel_lock lock;
00614
00615 #ifdef SC_LOCK_CHECK
00616 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00617 #endif
00618
00619
00620 set_segment_id( seg_id );
00621
00622 unlock_all_channels();
00623 m_timeout_event_p->notify_internal( t );
00624 m_timeout_event_p->add_dynamic( this );
00625
00626 if(t==SC_ZERO_TIME){
00627 this->m_process_state=3;
00628
00629 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00630 printf("\n%s is calling wait for delta time\n",this->name());
00631 }
00632 else {
00633 this->m_process_state=3;
00634 if(getenv(_SYSC_PRINT_VERBOSE_MESSAGE_ENV_VAR))
00635 printf("\n%s is calling wait for time\n",this->name());
00636 }
00637 m_trigger_type = TIMEOUT;
00638
00639 suspend_me();
00640
00641 }
00642 #ifdef SC_LOCK_CHECK
00643 assert( sc_get_curr_simcontext()->is_not_owner() );
00644 #endif
00645 lock_all_channels();
00646 }
00647
00648 inline
00649 void
00650 sc_thread_process::wait( const sc_time& t, const sc_event& e, int seg_id )
00651 {
00652 if( m_unwinding )
00653 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00654
00655 {
00656
00657 sc_kernel_lock lock;
00658
00659 #ifdef SC_LOCK_CHECK
00660 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00661 #endif
00662
00663
00664 set_segment_id( seg_id );
00665
00666 unlock_all_channels();
00667 m_timeout_event_p->notify_internal( t );
00668 m_timeout_event_p->add_dynamic( this );
00669 e.add_dynamic( this );
00670 m_event_p = &e;
00671 m_trigger_type = EVENT_TIMEOUT;
00672 suspend_me();
00673
00674 }
00675 #ifdef SC_LOCK_CHECK
00676 assert( sc_get_curr_simcontext()->is_not_owner() );
00677 #endif
00678 lock_all_channels();
00679 }
00680
00681 inline
00682 void
00683 sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el, int seg_id )
00684 {
00685 if( m_unwinding )
00686 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00687
00688 {
00689
00690 sc_kernel_lock lock;
00691
00692 #ifdef SC_LOCK_CHECK
00693 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00694 #endif
00695
00696
00697 set_segment_id( seg_id );
00698
00699 unlock_all_channels();
00700 m_timeout_event_p->notify_internal( t );
00701 m_timeout_event_p->add_dynamic( this );
00702 el.add_dynamic( this );
00703 m_event_list_p = ⪙
00704 m_trigger_type = OR_LIST_TIMEOUT;
00705 suspend_me();
00706
00707 }
00708 #ifdef SC_LOCK_CHECK
00709 assert( sc_get_curr_simcontext()->is_not_owner() );
00710 #endif
00711 lock_all_channels();
00712 }
00713
00714 inline
00715 void
00716 sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el, int seg_id )
00717 {
00718 if( m_unwinding )
00719 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00720
00721 {
00722
00723 sc_kernel_lock lock;
00724
00725 #ifdef SC_LOCK_CHECK
00726 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00727 #endif
00728
00729
00730 set_segment_id( seg_id );
00731
00732 unlock_all_channels();
00733 m_timeout_event_p->notify_internal( t );
00734 m_timeout_event_p->add_dynamic( this );
00735 el.add_dynamic( this );
00736 m_event_list_p = ⪙
00737 m_event_count = el.size();
00738 m_trigger_type = AND_LIST_TIMEOUT;
00739 suspend_me();
00740
00741 }
00742 #ifdef SC_LOCK_CHECK
00743 assert( sc_get_curr_simcontext()->is_not_owner() );
00744 #endif
00745 lock_all_channels();
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 inline
00758 void
00759 sc_thread_process::wait_cycles( int seg_id, int n )
00760 {
00761 if( m_unwinding )
00762 SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() );
00763
00764 {
00765
00766 sc_kernel_lock lock;
00767
00768 #ifdef SC_LOCK_CHECK
00769 assert( sc_get_curr_simcontext()->is_locked_and_owner() );
00770 #endif
00771
00772
00773 set_segment_id( seg_id );
00774
00775 unlock_all_channels();
00776 m_wait_cycle_n = n-1;
00777 suspend_me();
00778
00779 }
00780 #ifdef SC_LOCK_CHECK
00781 assert( sc_get_curr_simcontext()->is_not_owner() );
00782 #endif
00783 lock_all_channels();
00784 }
00785
00786
00787
00788
00789
00790 inline
00791 void sc_thread_process::add_monitor(sc_process_monitor* monitor_p)
00792 {
00793 m_monitor_q.push_back(monitor_p);
00794 }
00795
00796
00797 inline
00798 void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p)
00799 {
00800 int mon_n = m_monitor_q.size();
00801
00802 for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
00803 {
00804 if ( m_monitor_q[mon_i] == monitor_p )
00805 {
00806 m_monitor_q[mon_i] = m_monitor_q[mon_n-1];
00807 m_monitor_q.resize(mon_n-1);
00808 }
00809 }
00810 }
00811
00812 inline
00813 void sc_thread_process::set_next_exist(sc_thread_handle next_p)
00814 {
00815 m_exist_p = next_p;
00816 }
00817
00818 inline
00819 sc_thread_handle sc_thread_process::next_exist()
00820 {
00821 return (sc_thread_handle)m_exist_p;
00822 }
00823
00824 inline
00825 void sc_thread_process::set_next_runnable(sc_thread_handle next_p)
00826 {
00827 m_runnable_p = next_p;
00828 }
00829
00830 inline
00831 sc_thread_handle sc_thread_process::next_runnable()
00832 {
00833 return (sc_thread_handle)m_runnable_p;
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 inline
00853 void
00854
00855
00856 sc_thread_process::trigger_static( sc_event* e )
00857 {
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 if ( (m_state & ps_bit_disabled) || is_runnable() ||
00872 m_trigger_type != STATIC )
00873 return;
00874
00875 #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS )
00876 if( SC_UNLIKELY_( sc_get_current_process_b() == this ) )
00877 {
00878 report_immediate_self_notification();
00879 return;
00880 }
00881 #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS
00882
00883 if ( m_wait_cycle_n > 0 )
00884 {
00885 --m_wait_cycle_n;
00886 return;
00887 }
00888
00889
00890
00891
00892
00893 if ( m_state & ps_bit_suspended )
00894 {
00895 m_state = m_state | ps_bit_ready_to_run;
00896 }
00897 else
00898 {
00899
00900 sc_time curr_time = m_timestamp.get_time_count();
00901
00902
00903 sc_timestamp ts = e->get_notify_timestamp();
00904 switch( e->m_notify_type )
00905 {
00906 case sc_event::DELTA:
00907 if ( ts > m_timestamp ) {
00908 set_timestamp( sc_timestamp( ts.get_time_count(),
00909 ts.get_delta_count() + 1 ) );
00910 } else {
00911 set_timestamp( sc_timestamp( m_timestamp.get_time_count(),
00912 m_timestamp.get_delta_count()
00913 + 1 ) );
00914 }
00915 break;
00916 case sc_event::TIMED:
00917 set_timestamp( ts );
00918 break;
00919 case sc_event::NONE:
00920 assert( 0 );
00921 }
00922
00923 simcontext()->push_runnable_thread(this);
00924
00925
00926 simcontext()->update_oldest_time( curr_time );
00927 }
00928 }
00929
00930 #undef DEBUG_MSG
00931 #undef DEBUG_NAME
00932
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 #endif // !defined(sc_thread_process_h_INCLUDED)