Jump to content
e6daniel

implementing a fair mutex

Recommended Posts

   Hi!

I am using this fair_mutex implementation in a SystemC application of mine. It is almost doing what it should albeit the mutex accidently slips through the odd user. I cannot spot the prblem :(

Best Regards

    class fair_mutex : public sc_mutex
    {
        std::queue<sc_process_b *> s_queue;
    public:
        virtual int
            lock()
        {

            if (m_owner == sc_get_current_process_b()) return 0;

            s_queue.push(sc_get_current_process_b());
            while (in_use()) {
                sc_core::wait(m_free);
                if (s_queue.front() == sc_get_current_process_b())
                    break;
            }
            m_owner = sc_get_current_process_b();
            sc_core::wait(SC_ZERO_TIME);
            s_queue.pop();
            return 0;

        }
    };

Share this post


Link to post
Share on other sites

Your current implementation still depends on the scheduling order of the simulation kernel: If the mutex is not locked, the first scheduled process will obtain the lock, irrespectively of any current or future locking attempts in the same evaluation phase.

For example, if one process repeatedly tries to lock the mutex directly after releasing it, the lock will be granted, even if there are other processes already waiting:

void procA() {
  while(true) {
    mtx.lock();
    // do some work
    wait( 10, sc_core::SCNS );
    mtx.unlock();
    // will get the lock back again immediately!
  }
}

void procB {
  // ask for the lock slightly later
  wait( 5, sc_core::SC_NS );
  // continue as procA
  procA();
}


In order to fix it, you'll at least need to check the queue before granting the lock (untested):

     while (s_queue.front() != sc_get_current_process_b() || in_use()) {
         sc_core::wait(m_free);
     }


That said, you should not be using the implementation-defined sc_process_b class and use sc_process_handle and sc_get_current_process_handle() instead, to be more standards-compliant.

Hope that helps,
  Philipp

 

Share this post


Link to post
Share on other sites

    Thank you soo much Philipp!

 

You were absolutely correct that the implementation was not treating re-locks correctly.

The below implemenation works in my scenarios "at least". I think it is a correct generic solution.

    class fair_mutex : public sc_mutex
    {
        std::queue<sc_process_handle> s_queue;
    public:
        virtual int
            lock()
        {

            if (m_owner == sc_get_current_process_handle()) return 0;

            s_queue.push(sc_get_current_process_handle());
            while (s_queue.front() != sc_get_current_process_handle() || in_use()) {
                sc_core::wait(m_free);
            }
            m_owner = sc_get_current_process_handle();
            s_queue.pop();
            return 0;

        }

    };

Edited by e6daniel

Share this post


Link to post
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...