Jump to content

Can sc_mutex mechanism be implemented inside an sc_spawned thread?


kcai1107

Recommended Posts

I am using SystemC 2.3.2. To run-time configuration needs, I have to create a dynamic thread process by sc_spawn (by default), and a wait() statement works normally as in a static SC_THREAD process. However, when adding a pair of sc_mutex lock() and unlock() calls for some synchronization work, I get such a run-time error:  

     Error: (E519) wait() is only allowed in SC_THREADs and SC_CTHREADs:

                  in SC_METHODs use next_trigger() instead

Obviously, this error message is of a misleading because the dynamic process I create is undoubtedly a thread type process and wait() works well. I read some examples where sc_mutext can be used with SC_THREADs and this is the very reason I create a dynamic thread rather than a dynamic method. Can anybody in this community let me know if I do something wrong or the SystemC 2.3.2 still does not support sc_mutex implementation inside a spawned thread process?

This issue already becomes a show-stopper in my work, so I do sincerely appreciate your prompt attention and help!

KC

  

Link to comment
Share on other sites

Hi David,

Many thanks for your help!

As I mentioned, the reason to put sc_mutex inside a (with sc_spawn) dynamic thread instead of dynamic method is because I see some sc_mutex examples where concurrent SC_THREADs are used. But I still prefer to spawn a dynamic method to implement sc_mutex if allowed. Hence, I am also wondering if sc_mutex could be somehow used in either static or dynamic method even though sc_mutex may implicitly contains wait statements.    

Back to your requirement for the code sharing, I feel like a detailed enough code segment will show you how I've implemented sc_mutex inside a dynamic thread process. This FIFO item issue is essentially of bounded buffer producer-consumer problem.  The errors are originated from the sc_mutex implementation on "consumer side" inside dynamic_thread_process, and there is no complaint on sc_mutex implementation on "producer side" in fifo_item_producer() routine.  The thing is that once commenting out the two lines of sc_mutex inside dynamic_thread_process the run-time errors aforementioned are all gone. The wait statement inside while loop has never a problem, so the wait() is irrelevant to the run-time error (but that run-time error message still points to it).

The code segments are as follows:


class network : sc_module 
{
    ...

    void end_of_elaboration( )
    {
        
        // FIFO and mutex (to synchronize FIFO item insertion and removal) setup
        // NOTE: n_inits and n_targs become certain at end of elaboration

        fifo_mutex            = new sc_mutex*[n_inits];
        my_fifo                  = new std::deque<item_type>*[n_inits];        
        select_value          = new int[n_inits];
  
        for( int i = 0; i < n_inits; i++ )
        {
            fifo_mutex[i]     = new sc_mutex[n_targs];
            my_fifo[i]           = new std::deque<item_type>[n_targs];
            select_value[i]  = -1;
        }

        // Spawn a dynamic thread process (by default) per target       
        for( int i = 0; i < n_targs; i++ )
        {
            sc_spawn_options* opt = new sc_spawn_options;
            ostringstream oss;
            oss << "dynamic_thread_process" << i;
            sc_spawn( sc_bind(&network::dynamic_thread_process, this, i), oss.str().c_str(), opt );
        }
    }

    ...

    void fifo_item_producer( item_type item );
    void dynamic_thread_process( int targ );

    ...

    int n_inits;
    int n_targs;

    // Dynamically define a 2D STL deque array and a 2D-array for sc_mutex
 
    std::deque<item_type>** my_fifo;
    sc_mutex**                        fifo_mutex;
    int*                                     select_value;                                     

    ...

};

// The FIFO item producer that contains a critical section to be synchronized with sc_mutex mechanism
void network::fifo_item_producer( item_type item )
{
    // Extract init and targ information from item

    ...

    //********* Beginning of protection of the item insertion with fifo_mutex *************//

    fifo_mutex[init][targ].lock( );        
    my_fifo[init][targ].push_back( item );
    fifo_mutex[init][targ].unlock();

    //************ End of protection of the item insertion with fifo_mutex ************//

    ...

// This dynamic thread process that is essentially a FIFO item consumer, also needs synchronizing with sc_mutex mechanism 
void network::dynamic_thread_process ( int targ )
{
    while( true )
    {        
        int       select;
        item_type item;
        bool      popped = false;
                        
        for( int iters = 0; iters < n_inits; iters++ )
        {
             select = (++select_value[targ]) % n_inits;

             //************ Beginning of protection of the item removal with fifo_mutex ************//
 
             // NOTE: if the next line is commented out, run-time error message is gone                
             fifo_mutex[select][targ].lock( );
                
             if( my_fifo[select][targ].size() )
             {                   
                 item = my_fifo[select][targ].front();                    
                 my_fifo[select][targ].pop_front( );                 
                 popped = true;
                 break;
             }

             // NOTE: if the next line is commented out, run-time error message is gone    
             fifo_mutex[select][target].unlock( );

             //************ End of protection of the item removal with fifo_mutex ************//
        }
            
        if( popped == true )
        {
           // process the popped item

           ...               
        }
                    
        wait( sc_time(10, SC_NS) );    
    
    } // end of while loop

} // end of dynamic_thread_process     

  

 

 

 

Link to comment
Share on other sites

  • 3 weeks later...

@kcai1107: Thanks for sharing the code snippet. A minimal self-contained example exposing the issue would be helpful to replicate the issue on our side though -- especially if it is a real issue to be addressed in the SystemC proof-of-concept implementation. sc_mutex are derived from sc_object and therefore, it is recommended to manage a collection of such objects using sc_vector. The minimum benefit would be the possibility to give them a good (hierarchical) instance name, which would facilitate debugging. Have you tried to modify your implementation to use the non-blocking trylock() + wait in your dynamic process instead of the blocking lock() to work around the issue?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...