//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
//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));
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()) {
#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();
class snapmutex : public mutex {
public:
- snapmutex() : mutex()
+ snapmutex(int type = 0) : mutex(type)
{ }
SNAPSHOTALLOC
};
#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 {
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()
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);
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;