Do not report deadlock on relocking a recursive mutex; lock count not implemented yet
authorweiyu <weiyuluo1232@gmail.com>
Fri, 3 Apr 2020 22:37:22 +0000 (15:37 -0700)
committerweiyu <weiyuluo1232@gmail.com>
Fri, 3 Apr 2020 22:37:22 +0000 (15:37 -0700)
execution.cc
include/mutex.h
include/mypthread.h
mutex.cc
pthread.cc
threads.cc

index 97e58511e0307c3d4d2fe06177178e53718f5675..d455b5161e988fa3fe9ef00da1402a9782b6409b 100644 (file)
@@ -376,6 +376,8 @@ bool ModelExecution::process_mutex(ModelAction *curr)
                //TODO: FIND SOME BETTER WAY TO CHECK LOCK INITIALIZED OR NOT
                //if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock)
                //      assert_bug("Lock access before initialization");
+
+               // TODO: lock count for recursive mutexes
                state->locked = get_thread(curr);
                ModelAction *unlock = get_last_unlock(curr);
                //synchronize with the previous unlock statement
@@ -417,6 +419,7 @@ bool ModelExecution::process_mutex(ModelAction *curr)
                //FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS
                //MUST EVENMTUALLY RELEASE...
 
+               // TODO: lock count for recursive mutexes
                /* wake up the other threads */
                for (unsigned int i = 0;i < get_num_threads();i++) {
                        Thread *t = get_thread(int_to_id(i));
@@ -691,8 +694,15 @@ bool ModelExecution::check_action_enabled(ModelAction *curr) {
        if (curr->is_lock()) {
                cdsc::mutex *lock = curr->get_mutex();
                struct cdsc::mutex_state *state = lock->get_state();
-               if (state->locked)
+               if (state->locked) {
+                       Thread *lock_owner = (Thread *)state->locked;
+                       Thread *curr_thread = get_thread(curr);
+                       if (lock_owner == curr_thread && state->type == PTHREAD_MUTEX_RECURSIVE) {
+                               return true;
+                       }
+
                        return false;
+               }
        } else if (curr->is_thread_join()) {
                Thread *blocking = curr->get_thread_operand();
                if (!blocking->is_complete()) {
index f5894952282be7024867a8880793383f82b8e5f7..1f573bd1e51dd128e0b5b8982aa113f5f70a212c 100644 (file)
@@ -8,17 +8,20 @@
 
 #include "modeltypes.h"
 #include "mymemory.h"
+#include "mypthread.h"
 
 namespace cdsc {
 struct mutex_state {
        void *locked;   /* Thread holding the lock */
        thread_id_t alloc_tid;
        modelclock_t alloc_clock;
+       int type;
+       int lock_count;
 };
 
 class mutex {
 public:
-       mutex();
+       mutex(int type = PTHREAD_MUTEX_DEFAULT);
        ~mutex() {}
        void lock();
        bool try_lock();
@@ -31,7 +34,7 @@ private:
 
 class snapmutex : public mutex {
 public:
-       snapmutex() : mutex()
+       snapmutex(int type = 0) : mutex(type)
        { }
        SNAPSHOTALLOC
 };
index 4b2b615f61f9b1c0bcd0f64311e1edacd05824e1..660a8197e5084ca920cf46c99762915dafd62f15 100644 (file)
@@ -9,6 +9,15 @@
 #include <sched.h>
 #include <pthread.h>
 
+/* pthread mutex types
+enum
+{
+  PTHREAD_MUTEX_NORMAL
+  PTHREAD_MUTEX_RECURSIVE
+  PTHREAD_MUTEX_ERRORCHECK
+  PTHREAD_MUTEX_DEFAULT
+};*/
+
 typedef void *(*pthread_start_t)(void *);
 
 struct pthread_params {
index 0776db8eef5857b34c47bdbf3493194c9672097a..10fb5e3248b0550dd8b18afea34164380306ff23 100644 (file)
--- a/mutex.cc
+++ b/mutex.cc
@@ -8,13 +8,17 @@
 
 namespace cdsc {
 
-mutex::mutex()
+mutex::mutex(int type)
 {
        state.locked = NULL;
        thread_id_t tid = thread_current()->get_id();
        state.alloc_tid = tid;
        ClockVector *cv = model->get_execution()->get_cv(tid);
        state.alloc_clock = cv  == NULL ? 0 : cv->getClock(tid);
+
+       // For recursive mutex
+       state.type = type;
+       state.lock_count = 0;
 }
 
 void mutex::lock()
index 706f1b75602ef6ae33e2876be5064dcd10ab18a3..50214c34b31d6d578e4d732c11865eab9b3a3a89 100644 (file)
@@ -66,13 +66,18 @@ void pthread_exit(void *value_ptr) {
        real_pthread_exit(NULL);
 }
 
-int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t *) {
+int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t * attr) {
        if (!model) {
                snapshot_system_init(10000, 1024, 1024, 40000);
                model = new ModelChecker();
                model->startChecker();
        }
-       cdsc::snapmutex *m = new cdsc::snapmutex();
+
+       int mutex_type = PTHREAD_MUTEX_DEFAULT;
+       if (attr != NULL)
+               pthread_mutexattr_gettype(attr, &mutex_type);
+
+       cdsc::snapmutex *m = new cdsc::snapmutex(mutex_type);
 
        ModelExecution *execution = model->get_execution();
        execution->getMutexMap()->put(p_mutex, m);
index 8b55a91b186b61534ec124ca2a990283c11a3ffb..ee0df19ca338bd20e2a3dc0e4bd85b00ab059354 100644 (file)
@@ -490,6 +490,14 @@ Thread * Thread::waiting_on() const
 bool Thread::is_waiting_on(const Thread *t) const
 {
        Thread *wait;
+
+       // One thread relocks a recursive mutex
+       if (waiting_on() == t && pending->is_lock()) {
+               int mutex_type = pending->get_mutex()->get_state()->type;
+               if (mutex_type == PTHREAD_MUTEX_RECURSIVE)
+                       return false;
+       }
+
        for (wait = waiting_on();wait != NULL;wait = wait->waiting_on())
                if (wait == t)
                        return true;