bool ModelChecker::read_from(ModelAction *act, const ModelAction *rf)
{
ASSERT(rf);
+ ASSERT(rf->is_write());
+
act->set_read_from(rf);
if (act->is_acquire()) {
rel_heads_list_t release_heads;
int uninit_id = -1;
action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
if (list->empty() && act->is_atomic_var()) {
- uninit = new_uninitialized_action(act->get_location());
+ uninit = get_uninitialized_action(act);
uninit_id = id_to_int(uninit->get_tid());
- list->push_back(uninit);
+ list->push_front(uninit);
}
list->push_back(act);
}
/**
- * @brief Create a new action representing an uninitialized atomic
- * @param location The memory location of the atomic object
- * @return A pointer to a new ModelAction
+ * @brief Get an action representing an uninitialized atomic
+ *
+ * This function may create a new one or try to retrieve one from the NodeStack
+ *
+ * @param curr The current action, which prompts the creation of an UNINIT action
+ * @return A pointer to the UNINIT ModelAction
*/
-ModelAction * ModelChecker::new_uninitialized_action(void *location) const
+ModelAction * ModelChecker::get_uninitialized_action(const ModelAction *curr) const
{
- ModelAction *act = (ModelAction *)snapshot_malloc(sizeof(class ModelAction));
- act = new (act) ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, location, 0, model_thread);
+ Node *node = curr->get_node();
+ ModelAction *act = node->get_uninit_action();
+ if (!act) {
+ act = new ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, curr->get_location(), 0, model_thread);
+ node->set_uninit_action(act);
+ }
act->create_cv(NULL);
return act;
}
bool resolve_release_sequences(void *location, work_queue_t *work_queue);
void add_future_value(const ModelAction *writer, ModelAction *reader);
- ModelAction * new_uninitialized_action(void *location) const;
+ ModelAction * get_uninitialized_action(const ModelAction *curr) const;
ModelAction *diverge;
ModelAction *earliest_diverge;
Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) :
read_from_status(READ_FROM_PAST),
action(act),
+ uninit_action(NULL),
parent(par),
num_threads(nthreads),
explored_children(num_threads),
Node::~Node()
{
delete action;
+ if (uninit_action)
+ delete uninit_action;
if (enabled_array)
model_free(enabled_array);
if (yield_data)
enabled_type_t enabled_status(thread_id_t tid) const;
ModelAction * get_action() const { return action; }
+ void set_uninit_action(ModelAction *act) { uninit_action = act; }
+ ModelAction * get_uninit_action() const { return uninit_action; }
+
bool has_priority(thread_id_t tid) const;
void update_yield(Scheduler *);
bool has_priority_over(thread_id_t tid, thread_id_t tid2) const;
read_from_type_t read_from_status;
ModelAction * const action;
+
+ /** @brief ATOMIC_UNINIT action which was created at this Node */
+ ModelAction *uninit_action;
+
Node * const parent;
const int num_threads;
std::vector< bool, ModelAlloc<bool> > explored_children;