scheduler(scheduler),
thread_map(2), /* We'll always need at least 2 threads */
pthread_map(0),
- pthread_counter(1),
+ pthread_counter(2),
action_trace(),
obj_map(),
condvar_waiters_map(),
//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
/* unlock the lock - after checking who was waiting on it */
state->locked = NULL;
- /* disable this thread */
- get_safe_ptr_action(&condvar_waiters_map, curr->get_location())->push_back(curr);
+ /* remove old wait action and disable this thread */
+ action_list_t * waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
+ for (sllnode<ModelAction *> * it = waiters->begin(); it != NULL; it = it->getNext()) {
+ ModelAction * wait = it->getVal();
+ if (wait->get_tid() == curr->get_tid()) {
+ waiters->erase(it);
+ break;
+ }
+ }
+
+ waiters->push_back(curr);
scheduler->sleep(get_thread(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));
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()) {
}
+void ModelExecution::print_tail()
+{
+ model_print("Execution trace %d:\n", get_execution_number());
+
+ sllnode<ModelAction*> *it;
+
+ model_print("------------------------------------------------------------------------------------\n");
+ model_print("# t Action type MO Location Value Rf CV\n");
+ model_print("------------------------------------------------------------------------------------\n");
+
+ unsigned int hash = 0;
+
+ int length = 25;
+ int counter = 0;
+ SnapList<ModelAction *> list;
+ for (it = action_trace.end(); it != NULL; it = it->getPrev()) {
+ if (counter > length)
+ break;
+
+ ModelAction * act = it->getVal();
+ list.push_front(act);
+ counter++;
+ }
+
+ for (it = list.begin();it != NULL;it=it->getNext()) {
+ const ModelAction *act = it->getVal();
+ if (act->get_seq_number() > 0)
+ act->print();
+ hash = hash^(hash<<3)^(it->getVal()->hash());
+ }
+ model_print("HASH %u\n", hash);
+ model_print("------------------------------------------------------------------------------------\n");
+}
+
/**
* Add a Thread to the system for the first time. Should only be called once
* per thread.
* @return A Thread reference
*/
Thread * ModelExecution::get_pthread(pthread_t pid) {
+ // pid 1 is reserved for the main thread, pthread ids should start from 2
+ if (pid == 1)
+ return get_thread(pid);
+
union {
pthread_t p;
uint32_t v;
} x;
x.p = pid;
uint32_t thread_id = x.v;
- if (thread_id < pthread_counter + 1) return pthread_map[thread_id];
- else return NULL;
+
+ if (thread_id < pthread_counter + 1)
+ return pthread_map[thread_id];
+ else
+ return NULL;
}
/**
CycleNode * prevnode = node->getInEdge(i);
ModelAction * prevact = prevnode->getAction();
if (prevact->get_type() != READY_FREE) {
- // Save the original action type
- prevact->set_original_type(prevact->get_type());
prevact->set_free();
queue->push_back(prevnode);
}
if (act->is_read()) {
if (act->get_reads_from()->is_free()) {
if (act->is_rmw()) {
- // Save the original action type
- act->set_original_type(act->get_type());
//Weaken a RMW from a freed store to a write
act->set_type(ATOMIC_WRITE);
} else {
fixupLastAct(act);
}
- // Only delete this action if not being using by ModelHistory.
- // Otherwise, the deletion of action is deferred.
- if (act->get_func_ref_count() == 0) {
- delete act;
- continue;
- }
+ delete act;
+ continue;
}
}
}
if (act->is_read()) {
if (act->get_reads_from()->is_free()) {
if (act->is_rmw()) {
- // Save the original action type
- act->set_original_type(act->get_type());
act->set_type(ATOMIC_WRITE);
} else {
removeAction(act);
if (islastact) {
fixupLastAct(act);
}
- if (act->get_func_ref_count() == 0) {
- delete act;
- continue;
- }
+ delete act;
+ continue;
}
}
} else if (act->is_free()) {
if (islastact) {
fixupLastAct(act);
}
- if (act->get_func_ref_count() == 0) {
- delete act;
- continue;
- }
+ delete act;
+ continue;
} else if (act->is_write()) {
//Do nothing with write that hasn't been marked to be freed
} else if (islastact) {