e6daniel 0 Report post Posted June 5, 2017 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; } }; Quote Share this post Link to post Share on other sites
Philipp A Hartmann 240 Report post Posted June 6, 2017 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 Quote Share this post Link to post Share on other sites
e6daniel 0 Report post Posted June 7, 2017 (edited) 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 June 7, 2017 by e6daniel Quote Share this post Link to post Share on other sites