-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add test for round robin threads #125
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1038,7 +1038,7 @@ periodic_thread(int id, volatile unsigned long *counters) | |
while (1) { | ||
counters[id]++; | ||
test_leq(counters[id], (unsigned long) 10000); | ||
printf("Tick\n"); | ||
printf("Tick (%d)\n", id); | ||
seL4_Yield(); | ||
} | ||
} | ||
|
@@ -1695,3 +1695,72 @@ static int test_changing_affinity(struct env *env) | |
} | ||
DEFINE_TEST(SCHED0022, "test changing a helper threads core", test_changing_affinity, | ||
(config_set(CONFIG_KERNEL_MCS) &&(CONFIG_MAX_NUM_NODES > 1))); | ||
|
||
|
||
/* busy wait for a number of iterations */ | ||
static void delay_loop(unsigned iterations) { | ||
for (int i = 0; i < iterations; i++) { | ||
__asm__ __volatile__ (""); | ||
} | ||
} | ||
|
||
#define SCHED0023_NUM_ROUNDS 5 | ||
|
||
/* used in test_round_robin below */ | ||
static void round_robin_thread(int id, volatile unsigned long *counters) | ||
{ | ||
delay_loop(id * 10000); | ||
|
||
/* assumes counters are initialised already */ | ||
while (counters[id] < SCHED0023_NUM_ROUNDS) { | ||
counters[id]++; | ||
/* thread "id" should run after thread "id-1", so we should be at the same | ||
count after incrementing if we are scheduled round robin. */ | ||
if (0 < id) { | ||
test_eq(counters[id], counters[id - 1]); | ||
} | ||
printf("Tick (%d)\n", id); | ||
/* busy wait so we can be preempted at least once before we increment | ||
the counter again */ | ||
delay_loop(5000000); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a note here why this magic value seem quite safe based on the assumption about time slice and core frequency/IPS. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like it isn’t safe yet on all machines, esp when printing is off. I might have to actually try to compute a value here instead. Just wanted to avoid making any syscalls in these threads that could affect scheduling. |
||
} | ||
|
||
test_eq(counters[id], (unsigned long) SCHED0023_NUM_ROUNDS); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a note there why this would ever fail. Is there any other cause besides memory corruption? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just making sure every thread is only writing to its own counter. |
||
} | ||
|
||
/* Test that round robin threads are indeed round robin. */ | ||
static int test_round_robin(struct env *env) | ||
{ | ||
const int num_threads = 5; | ||
helper_thread_t helpers[num_threads]; | ||
volatile unsigned long counters[num_threads]; | ||
|
||
for (int i = 0; i < num_threads; i++) { | ||
counters[i] = 0; | ||
create_helper_thread(env, &helpers[i]); | ||
/* keep at lower priority first, we will drop our own priority when they are all started */ | ||
set_helper_priority(env, &helpers[i], env->priority - 1); | ||
/* budget == priority makes them round robin */ | ||
set_helper_sched_params(env, &helpers[i], 1 * US_IN_MS, 1 * US_IN_MS, 0); | ||
} | ||
|
||
/* start in reverse order, because most recently started is first in scheduling | ||
queue and we want id 0 to run first */ | ||
for (int i = num_threads - 1; i >= 0; i--) { | ||
start_helper(env, &helpers[i], | ||
(helper_fn_t) round_robin_thread, i, (seL4_Word) counters, 0, 0); | ||
} | ||
|
||
int error = seL4_TCB_SetPriority(env->tcb, env->tcb, env->priority - 2); | ||
test_error_eq(error, seL4_NoError); | ||
|
||
/* We will only get to run again when the round robin threads have all finished, | ||
because they are higher priority */ | ||
for (int i = 0; i < num_threads; i++) { | ||
test_eq(counters[i], (unsigned long) SCHED0023_NUM_ROUNDS); | ||
} | ||
|
||
return sel4test_get_result(); | ||
} | ||
DEFINE_TEST(SCHED0023, "test round robin threads", test_round_robin, | ||
(config_set(CONFIG_KERNEL_MCS))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a explicit note here that the blocking printing is not interfering with the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not sure it isn’t actually, I’m still experimenting. A good 30% of the configs where this test is enabled are still failing. But of course not when I’m trying to run it manually..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will interfere with the test, as it messes up all timing and hence scheduling.