Final fix; needs to be careful about the side effect of NewFuzzer::find_threads
[c11tester.git] / newfuzzer.cc
index cb25d7635f2cb728ffe9317dae6cac55daf66722..6eb57d88f23fba5d4a68295ec48f07ea651b2e58 100644 (file)
@@ -65,24 +65,28 @@ int NewFuzzer::selectWrite(ModelAction *read, SnapVector<ModelAction *> * rf_set
        while ( rf_set->size() == 0 ) {
                Thread * read_thread = execution->get_thread(tid);
                Predicate * selected_branch = get_selected_child_branch(tid);
+               bool should_sleep = should_conditional_sleep(selected_branch);
                bool should_reselect_predicate = false;
+
                //model_print("the %d read action of thread %d at %p is unsuccessful\n", read->get_seq_number(), read_thread->get_id(), read->get_location());
 
-               if (!find_threads(read)) {
+               if ( find_threads(read, should_sleep) ) {
+                       if (should_sleep) {
+                               // reset thread pending action and revert sequence numbers
+                               read_thread->set_pending(read);
+                               read->reset_seq_number();
+                               execution->restore_last_seq_num();
+
+                               conditional_sleep(read_thread);
+                               // Returning -1 stops the while loop of ModelExecution::process_read
+                               return -1;
+                       } else {
+                               update_predicate_score(selected_branch, SLEEP_FAIL_TYPE2);
+                               should_reselect_predicate = true;
+                       }
+               } else {
                        update_predicate_score(selected_branch, SLEEP_FAIL_TYPE1);
                        should_reselect_predicate = true;
-               } else if (!should_conditional_sleep(selected_branch)) {
-                       update_predicate_score(selected_branch, SLEEP_FAIL_TYPE2);
-                       should_reselect_predicate = true;
-               } else {
-                       // reset thread pending action and revert sequence numbers
-                       read_thread->set_pending(read);
-                       read->reset_seq_number();
-                       execution->restore_last_seq_num();
-
-                       conditional_sleep(read_thread);
-                       // Returning -1 stops the while loop of ModelExecution::process_read
-                       return -1;
                }
 
                if (should_reselect_predicate) {
@@ -271,9 +275,9 @@ bool NewFuzzer::prune_writes(thread_id_t tid, Predicate * pred,
                                        break;
                                case NULLITY:
                                        equality = ((void*)write_val == NULL);
-                                        if (equality != expression->value)
-                                                satisfy_predicate = false;
-                                        break;
+                                       if (equality != expression->value)
+                                               satisfy_predicate = false;
+                                       break;
                                default:
                                        model_print("unknown predicate token\n");
                                        break;
@@ -322,9 +326,23 @@ void NewFuzzer::conditional_sleep(Thread * thread)
        /* history->add_waiting_thread is already called in find_threads */
 }
 
-bool NewFuzzer::should_conditional_sleep(Predicate *)
+/**
+ * Decides whether a thread should condition sleep based on
+ * the sleep score of the chosen predicate.
+ *
+ * sleep_score = 100: never sleeps
+ * sleep_score = 0: always sleeps
+ **/
+bool NewFuzzer::should_conditional_sleep(Predicate * predicate)
 {
-       return true;
+       int sleep_score = predicate->get_sleep_score();
+       int random_num = random() % 100;
+
+       /* should sleep if random_num falls within [sleep_score, 100] */
+       if (random_num >= sleep_score)
+               return true;
+
+       return false;
 }
 
 bool NewFuzzer::has_paused_threads()
@@ -397,10 +415,13 @@ void NewFuzzer::notify_paused_thread(Thread * thread)
        model_print("** thread %d is woken up\n", tid);
 }
 
-/* Find threads that may write values that the pending read action is waiting for
+/* Find threads that may write values that the pending read action is waiting for.
+ * Side effect: waiting threads are added if should_sleep is true
+ *
+ * @param should_sleep Indicate whether waiting threads should be added or not
  * @return True if any thread is found
  */
-bool NewFuzzer::find_threads(ModelAction * pending_read)
+bool NewFuzzer::find_threads(ModelAction * pending_read, bool should_sleep)
 {
        ASSERT(pending_read->is_read());
 
@@ -423,9 +444,12 @@ bool NewFuzzer::find_threads(ModelAction * pending_read)
 
                        int distance = node->compute_distance(target_node);
                        if (distance != -1) {
-                               history->add_waiting_thread(self_id, tid, target_node, distance);
                                finds_waiting_for = true;
                                //model_print("thread: %d; distance from node %d to node %d: %d\n", tid, node->get_func_id(), target_node->get_func_id(), distance);
+
+                               if (should_sleep) {
+                                       history->add_waiting_thread(self_id, tid, target_node, distance);
+                               }
                        }
                }
        }