}
+/**
+ * @brief Construct a new ModelAction
+ *
+ * @param type The type of action
+ * @param order The memory order of this action. A "don't care" for non-ATOMIC
+ * actions (e.g., THREAD_* or MODEL_* actions).
+ * @param loc The location that this action acts upon
+ * @param value (optional) A value associated with the action (e.g., the value
+ * read or written). Defaults to a given macro constant, for debugging purposes.
+ * @param thread (optional) The Thread in which this action occurred. If NULL
+ * (default), then a Thread is assigned according to the scheduler.
+ */
+ModelAction::ModelAction(action_type_t type, memory_order order, uint64_t value, uint64_t _time) :
+ location(NULL),
+ position(NULL),
+ time(_time),
+ last_fence_release(NULL),
+ uninitaction(NULL),
+ cv(NULL),
+ rf_cv(NULL),
+ value(value),
+ type(type),
+ order(order),
+ original_order(order),
+ seq_number(ACTION_INITIAL_CLOCK)
+{
+ Thread *t = thread_current();
+ this->tid = t!= NULL ? t->get_id() : -1;
+}
+
/**
* @brief Construct a new ModelAction
*
return type == ATOMIC_LOCK;
}
+bool ModelAction::is_sleep() const
+{
+ return type == THREAD_SLEEP;
+}
+
bool ModelAction::is_wait() const {
return type == ATOMIC_WAIT;
}
case THREAD_YIELD: return "thread yield";
case THREAD_JOIN: return "thread join";
case THREAD_FINISH: return "thread finish";
+ case THREAD_SLEEP: return "thread sleep";
case THREADONLY_FINISH: return "pthread_exit finish";
case PTHREAD_CREATE: return "pthread create";
THREADONLY_FINISH, // < A thread completion action
PTHREAD_CREATE, // < A pthread creation action
PTHREAD_JOIN, // < A pthread join action
+ THREAD_SLEEP, // < A sleep operation
ATOMIC_UNINIT, // < Represents an uninitialized atomic
NONATOMIC_WRITE, // < Represents a non-atomic store
ATOMIC_INIT, // < Initialization of an atomic object (e.g., atomic_init())
ModelAction(action_type_t type, memory_order order, void *loc, uint64_t value = VALUE_NONE, Thread *thread = NULL);
ModelAction(action_type_t type, memory_order order, void *loc, uint64_t value, int size);
ModelAction(action_type_t type, const char * position, memory_order order, void *loc, uint64_t value, int size);
+ ModelAction(action_type_t type, memory_order order, uint64_t value, uint64_t time);
ModelAction(action_type_t type, const char * position, memory_order order, void *loc, uint64_t value = VALUE_NONE, Thread *thread = NULL);
~ModelAction();
void print() const;
uint64_t get_write_value() const;
uint64_t get_return_value() const;
ModelAction * get_reads_from() const { return reads_from; }
+ uint64_t get_time() const {return time;}
cdsc::mutex * get_mutex() const;
void set_read_from(ModelAction *act);
bool is_thread_join() const;
bool is_mutex_op() const;
bool is_lock() const;
+ bool is_sleep() const;
bool is_trylock() const;
bool is_unlock() const;
bool is_wait() const;
*/
ModelAction *reads_from;
int size;
+ uint64_t time; //used for sleep
};
/** @brief The last fence release from the same thread */
if (fence_release && *(get_last_action(thread->get_id())) < *fence_release)
return true;
}
+ if (asleep->is_sleep()) {
+ if (fuzzer->shouldWake(asleep))
+ return true;
+ }
+
return false;
}
if (!blocking->is_complete()) {
return false;
}
+ } else if (curr->is_sleep()) {
+ if (!fuzzer->shouldSleep(curr))
+ return false;
}
return true;
#include <stdlib.h>
#include "threads-model.h"
#include "model.h"
+#include "action.h"
int Fuzzer::selectWrite(ModelAction *read, SnapVector<ModelAction *> * rf_set) {
int random_index = random() % rf_set->size();
waiters->erase(it);
return thread;
}
+
+bool Fuzzer::shouldSleep(const ModelAction *sleep) {
+ return true;
+}
+
+bool Fuzzer::shouldWake(const ModelAction *sleep) {
+ struct timespec currtime;
+ clock_gettime(CLOCK_MONOTONIC, &currtime);
+ uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
+
+ return ((sleep->get_time()+sleep->get_value()) >= lcurrtime);
+}
int selectWrite(ModelAction *read, SnapVector<ModelAction *>* rf_set);
Thread * selectThread(int * threadlist, int numthreads);
Thread * selectNotify(action_list_t * waiters);
+ bool shouldSleep(const ModelAction *sleep);
+ bool shouldWake(const ModelAction *sleep);
MEMALLOC
private:
};
/* global "model" object */
#include "model.h"
#include "execution.h"
+extern "C" {
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+}
+
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) {
+ if (model) {
+ uint64_t time = rqtp->tv_sec * 1000000000 + rqtp->tv_nsec;
+ struct timespec currtime;
+ clock_gettime(CLOCK_MONOTONIC, &currtime);
+ uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
+ model->switch_to_master(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime));
+ if (rmtp != NULL) {
+ clock_gettime(CLOCK_MONOTONIC, &currtime);
+ uint64_t lendtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
+ uint64_t elapsed = lendtime - lcurrtime;
+ rmtp->tv_sec = elapsed / 1000000000;
+ rmtp->tv_nsec = elapsed - rmtp->tv_sec * 1000000000;
+ }
+ }
+ return 0;
+}
int pthread_create(pthread_t *t, const pthread_attr_t * attr,
pthread_start_t start_routine, void * arg) {
pthread_mutex_init(p_mutex, NULL);
cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
- cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+ // cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
model->switch_to_master(new ModelAction(NOOP, std::memory_order_seq_cst, v));
// v->wait(*m);