Skip to content

Commit a730669

Browse files
committed
pct_strategy: run round robin for livelock avoding
1 parent 5030643 commit a730669

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

runtime/include/pct_strategy.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ struct PctStrategy : public BaseStrategyWithThreads<TargetObj, Verifier> {
3434
size_t NextThreadId() override {
3535
auto& threads = this->threads;
3636
int max = std::numeric_limits<int>::min();
37-
int snd_max = std::numeric_limits<int>::min();
38-
size_t index_of_max = 0, index_of_snd_max = 0;
37+
size_t index_of_max = 0;
3938
// Have to ignore waiting threads, so can't do it faster than O(n)
4039
for (size_t i = 0; i < threads.size(); ++i) {
4140
// Ignore waiting tasks
@@ -51,21 +50,31 @@ struct PctStrategy : public BaseStrategyWithThreads<TargetObj, Verifier> {
5150
}
5251

5352
if (max <= priorities[i]) {
54-
index_of_snd_max = index_of_max;
55-
snd_max = max;
5653
max = priorities[i];
5754
index_of_max = i;
58-
} else if (snd_max <= priorities[i]) {
59-
snd_max = priorities[i];
60-
index_of_snd_max = i;
55+
}
56+
}
57+
58+
if (round_robin_stage > 0) {
59+
for (size_t attempt = 0; attempt < threads.size(); ++attempt) {
60+
auto i = (++last_chosen) % threads.size();
61+
if (!threads[i].empty() && threads[i].back()->IsBlocked()) {
62+
continue;
63+
}
64+
index_of_max = i;
65+
max = priorities[i];
66+
break;
67+
}
68+
debug(stderr, "round robin choose: %d\n", index_of_max);
69+
if (round_robin_start == index_of_max) {
70+
--round_robin_stage;
6171
}
6272
}
6373

6474
// TODO: Choose wiser constant
65-
if (count_chosen_same == 100 && index_of_max == last_chosen &&
66-
snd_max != std::numeric_limits<int>::min()) {
67-
priorities[index_of_max] = snd_max - 1;
68-
index_of_max = index_of_snd_max;
75+
if (count_chosen_same == 1000 && index_of_max == last_chosen) {
76+
round_robin_stage = 5;
77+
round_robin_start = index_of_max;
6978
}
7079

7180
if (index_of_max == last_chosen) {
@@ -179,6 +188,7 @@ struct PctStrategy : public BaseStrategyWithThreads<TargetObj, Verifier> {
179188
k_statistics.push_back(current_schedule_length);
180189
current_schedule_length = 0;
181190
count_chosen_same = 0;
191+
round_robin_stage = 0;
182192

183193
// current_depth have been increased
184194
size_t new_k = std::reduce(k_statistics.begin(), k_statistics.end()) /
@@ -211,6 +221,8 @@ struct PctStrategy : public BaseStrategyWithThreads<TargetObj, Verifier> {
211221
// original article)
212222
size_t count_chosen_same;
213223
size_t last_chosen;
224+
size_t round_robin_start;
225+
size_t round_robin_stage{0};
214226
std::vector<int> priorities;
215227
std::vector<size_t> priority_change_points;
216228
std::mt19937 rng;

runtime/include/scheduler.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ struct BaseStrategyWithThreads : public Strategy {
164164
size_t tasks_in_thread = thread.size();
165165
for (size_t i = 0; i < tasks_in_thread; ++i) {
166166
if (!IsTaskRemoved(thread[i]->GetId())) {
167-
thread[i] = thread[i]->Restart(&*state);
167+
thread[i] = thread[i]->Restart(state.get());
168168
}
169169
}
170170
}
@@ -220,7 +220,7 @@ struct BaseStrategyWithThreads : public Strategy {
220220
}
221221
threads[thread_index].emplace_back(
222222
this->constructors[verified_constructor].Build(
223-
&*this->state, thread_index, this->new_task_id++));
223+
this->state.get(), thread_index, this->new_task_id++));
224224
TaskWithMetaData task{threads[thread_index].back(), true, thread_index};
225225
return task;
226226
}
@@ -264,7 +264,7 @@ struct BaseStrategyWithThreads : public Strategy {
264264
return b.GetName() == *releaseTask;
265265
});
266266
auto task =
267-
constructor.Build(&*this->state, thread_index, task_index);
267+
constructor.Build(this->state.get(), thread_index, task_index);
268268
auto verified = this->sched_checker.Verify(CreatedTaskMetaData{
269269
std::string(task->GetName()), true, thread_index});
270270
assert(verified && "wrong release task at termination");
@@ -615,7 +615,7 @@ struct TLAScheduler : Scheduler {
615615
if (frame.is_new) {
616616
// It was a new task.
617617
// So restart it from the beginning with the same args.
618-
*task = (*task)->Restart(&*state);
618+
*task = (*task)->Restart(state.get());
619619
} else {
620620
// It was a not new task, hence, we recreated in early.
621621
}
@@ -732,7 +732,7 @@ struct TLAScheduler : Scheduler {
732732
for (size_t cons_num = 0; auto cons : constructors) {
733733
frame.is_new = true;
734734
auto size_before = tasks.size();
735-
tasks.emplace_back(cons.Build(&*state, i, -1 /* TODO: fix task id for tla, because it is Scheduler and not Strategy class for some reason */));
735+
tasks.emplace_back(cons.Build(state.get(), i, -1 /* TODO: fix task id for tla, because it is Scheduler and not Strategy class for some reason */));
736736

737737
auto [is_over, res] = ResumeTask(frame, step, switches, thread, true);
738738
if (is_over || res.has_value()) {

0 commit comments

Comments
 (0)