value(value),
type(type),
original_type(ATOMIC_NOP),
+ swap_flag(false),
order(order),
original_order(order),
seq_number(ACTION_INITIAL_CLOCK)
trace_ref(NULL),
thrdmap_ref(NULL),
action_ref(NULL),
+ func_act_ref(NULL),
value(value),
type(type),
original_type(ATOMIC_NOP),
+ swap_flag(false),
order(order),
original_order(order),
seq_number(ACTION_INITIAL_CLOCK)
trace_ref(NULL),
thrdmap_ref(NULL),
action_ref(NULL),
+ func_act_ref(NULL),
value(value),
type(type),
original_type(ATOMIC_NOP),
+ swap_flag(false),
order(order),
original_order(order),
seq_number(ACTION_INITIAL_CLOCK)
trace_ref(NULL),
thrdmap_ref(NULL),
action_ref(NULL),
+ func_act_ref(NULL),
value(value),
type(type),
original_type(ATOMIC_NOP),
+ swap_flag(false),
order(order),
original_order(order),
seq_number(ACTION_INITIAL_CLOCK)
trace_ref(NULL),
thrdmap_ref(NULL),
action_ref(NULL),
+ func_act_ref(NULL),
value(value),
type(type),
original_type(ATOMIC_NOP),
+ swap_flag(false),
order(order),
original_order(order),
seq_number(ACTION_INITIAL_CLOCK)
*/
uint64_t ModelAction::get_write_value() const
{
- ASSERT(is_write());
+ ASSERT(is_write() || is_free());
return value;
}
action_type_t tmp = type;
type = original_type;
original_type = tmp;
+
+ if (swap_flag)
+ swap_flag = false;
+ else
+ swap_flag = true;
}
* iteself does not indicate no value.
*/
#define VALUE_NONE 0xdeadbeef
-#define HAS_REFERENCE ((void *)0x1)
+#define WRITE_REFERENCED ((void *)0x1)
/**
* @brief The "location" at which a fence occurs
thread_id_t get_tid() const { return tid; }
action_type get_type() const { return type; }
void set_type(action_type _type) { type = _type; }
- action_type get_original_type() const { return type; }
+ action_type get_original_type() const { return original_type; }
void set_original_type(action_type _type) { original_type = _type; }
void set_free() { type = READY_FREE; }
memory_order get_mo() const { return order; }
ModelAction * get_reads_from() const { return reads_from; }
uint64_t get_time() const {return time;}
cdsc::mutex * get_mutex() const;
+ bool get_swap_flag() const { return swap_flag; }
void set_read_from(ModelAction *act);
* set as READY_FREE or weaken from a RMW to a write */
action_type original_type;
+ /** @brief Indicate whether the action type and the original action type
+ * has been swapped. */
+ bool swap_flag;
+
/** @brief The memory order for this operation. */
memory_order order;
//Free if it is invisible or we have set a flag to remove visible actions.
if (actseq <= tid_clock || params->removevisible) {
- // For read actions being used by ModelHistory, mark the reads_from as being used.
- if (act->is_read() && act->getFuncActRef() != NULL) {
- ModelAction * reads_from = act->get_reads_from();
- if (reads_from->getFuncActRef() == NULL)
- reads_from->setFuncActRef(HAS_REFERENCE);
+ // For read or rmw actions being used by ModelHistory, mark the reads_from as being used.
+ if (act->is_read()) {
+ if (act->is_rmw()) {
+ void * func_act_ref = act->getFuncActRef();
+ if (func_act_ref == WRITE_REFERENCED) {
+ // Only the write part of this rmw is referenced, do nothing
+ } else if (func_act_ref != NULL) {
+ // The read part of rmw is potentially referenced
+ ModelAction * reads_from = act->get_reads_from();
+ if (reads_from->getFuncActRef() == NULL)
+ reads_from->setFuncActRef(WRITE_REFERENCED);
+ }
+ } else {
+ if (act->getFuncActRef() != NULL) {
+ ModelAction * reads_from = act->get_reads_from();
+ if (reads_from->getFuncActRef() == NULL)
+ reads_from->setFuncActRef(WRITE_REFERENCED);
+ }
+ }
}
ModelAction * write;
CycleNode * prevnode = node->getInEdge(i);
ModelAction * prevact = prevnode->getAction();
if (prevact->get_type() != READY_FREE) {
- if (prevact->getFuncActRef() != NULL) {
- // Copy the original type if being used by ModelHistory
- prevact->set_original_type(prevact->get_type());
- }
+ // Save the original action type
+ prevact->set_original_type(prevact->get_type());
prevact->set_free();
queue->push_back(prevnode);
}
}
if (act->is_read()) {
- // For read actions being used by ModelHistory, mark the reads_from as being used.
- if (act->getFuncActRef() != NULL) {
- ModelAction * reads_from = act->get_reads_from();
- if (reads_from->getFuncActRef() == NULL)
- reads_from->setFuncActRef(HAS_REFERENCE);
+ // For read or rmw actions being used by ModelHistory, mark the reads_from as being used.
+ if (act->is_rmw()) {
+ void * func_act_ref = act->getFuncActRef();
+ if (func_act_ref == WRITE_REFERENCED) {
+ // Only the write part of this rmw is referenced, do nothing
+ } else if (func_act_ref != NULL) {
+ // The read part of rmw is potentially referenced
+ ModelAction * reads_from = act->get_reads_from();
+ if (reads_from->getFuncActRef() == NULL)
+ reads_from->setFuncActRef(WRITE_REFERENCED);
+ }
+ } else {
+ if (act->getFuncActRef() != NULL) {
+ ModelAction * reads_from = act->get_reads_from();
+ if (reads_from->getFuncActRef() == NULL)
+ reads_from->setFuncActRef(WRITE_REFERENCED);
+ }
}
if (act->get_reads_from()->is_free()) {
if (act->is_rmw()) {
- if (act->getFuncActRef() != NULL) {
- // Copy the original type if being used by ModelHistory
- act->set_original_type(act->get_type());
- }
+ // 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.
+ // Only delete this action if not being using by ModelHistory.
+ // Otherwise, the deletion of action is deferred.
if (act->getFuncActRef() == NULL) {
delete act;
continue;
if (act->is_read()) {
if (act->get_reads_from()->is_free()) {
if (act->is_rmw()) {
- if (act->getFuncActRef() != NULL) {
- // Copy the original type if being used by ModelHistory
- act->set_original_type(act->get_type());
- }
+ // Save the original action type
+ act->set_original_type(act->get_type());
act->set_type(ATOMIC_WRITE);
} else {
removeAction(act);
for (sllnode<ModelAction *> * it = act_list->begin();it != NULL;it = it->getNext()) {
ModelAction * act = it->getVal();
- act->setFuncActRef(NULL); // Remove func_act_ref so that this action can be removed
+
+ // Only ATOMIC_RMW or ATOMIC_WRITE may be swapped with their original types,
+ // which are later added to rw_act_list. Therefore, it is safe to only revert
+ // back action types for actions in rw_act_list whose types have been swapped.
+ if (act->get_original_type() != ATOMIC_NOP && act->get_swap_flag() == false)
+ act->use_original_type();
+
+ // Remove func_act_ref so that actions can be deleted by Execution::collectActions
+ act->setFuncActRef(NULL);
+ if (act->is_read()) {
+ // For every read or rmw actions in this list, the reads_from is not deleted.
+ // So it is safe to call get_reads_from
+ ModelAction * rf = act->get_reads_from();
+ rf->setFuncActRef(NULL);
+ }
+
FuncInst * func_inst = get_inst(act);
void * loc = act->get_location();
}
}
-// model_print("function %s\n", func_name);
-// print_val_loc_map();
-
update_inst_tree(&inst_list);
update_predicate_tree(&rw_act_list);
+ // Revert back action types and free
+ for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL; it = it->getNext()) {
+ ModelAction * act = it->getVal();
+
+ // Revert back action types for actions whose types have been changed.
+ if (act->get_swap_flag() == true)
+ act->use_original_type();
+
+ /** Free actions
+ * case 1. READY_FREE -> delete
+ * case 2. Read action whose read from is READY_FREE -> delete both actions
+ * In both cases, the actions have already been removed from core model
+ * action lists.
+ */
+
+ /* Problematic: could double free actions
+ if (act->is_free()) {
+ model_print("delete free act %d\n", act->get_seq_number());
+ delete act;
+ } else if (act->is_read()) {
+ ModelAction * rf = act->get_reads_from();
+ if (rf->is_free()) {
+ model_print("delete act %d\n", act->get_seq_number());
+ model_print("delete act %d\n", rf->get_seq_number());
+ delete rf;
+ delete act;
+ }
+ }*/
+ }
+
// print_predicate_tree();
}
*/
Predicate * Predicate::follow_write_child(FuncInst * inst)
{
- ASSERT(inst->get_type() == ATOMIC_WRITE);
+ action_type type = inst->get_type();
+ ASSERT(type == ATOMIC_WRITE || type == ATOMIC_INIT);
for (uint i = 0;i < children.size();i++) {
Predicate * child = children[i];