Thanks, wentao, for the suggested code fragment.
The call to sched_setscheduler() successfully changed the scheduling policy without returning
an error.
I had tried something more like this:
struct sched_param schp;
sched_getparam(getpid(), &schp);
schp.sched_priority = sched_get_priority_max(SCHED_RR);
if (sched_setscheduler(getpid(), SCHED_RR, &schp) != 0) {
perror("sched_setscheduler");
exit(1);
}
Apparently, one needs to pass the root process ID of 0 in order to change
the policy. Whatever, a subsequent call to sched_getparam passing it the
calling process returns the changed schedule policy value, and a subsequent
sched_setparam call with getpid() also works, so there it is.
However, I'm not sure changing the policy did anything:
My test case, minus the# includes and various queries and printf() calls, is:
static int done;
void* threaddie(void* arg)
{
int i;
char c = *((char*) arg);
for(i = 0; i < 20; i++) {
putchar(c);
}
done++;
pthread_exit(NULL);
return NULL;
}
int main(int argc, char** argv)
{
pthread_t t1, t2, t3, t4;
char c1 = '1';
char c2 = '2';
char c3 = '3';
char c4 = '4';
int policy;
struct sched_param schp;
policy = SCHED_RR;
memset(&schp, 0, sizeof(schp));
schp.sched_priority = sched_get_priority_min(policy);
if (sched_setscheduler(0, policy, &schp) != 0) {
perror("sched_setscheduler");
exit(1);
}
done = 0;
pthread_create(&t1, NULL, threaddie, (void*) &c1);
pthread_create(&t2, NULL, threaddie, (void*) &c2);
pthread_create(&t3, NULL, threaddie, (void*) &c3);
pthread_create(&t4, NULL, threaddie, (void*) &c4);
while (done < 4) {
sched_yield();
}
return 0;
The output from this test case, regardless of whether policy is set to SCHED_RR, SCHED_FIFO,
or SCHED_OTHER, is:
11111111111111111111222222222222222222223333333333333333333344444444444444444444
...so linux is not preempting the first thread to run the second, and so on, which indicates
to me that the scheduling policy change didn't work. Increasing the number of iterations just
increases the number of 1's in a row etc. Inserting some busywork code (for example,
declaring int j, then inserting j = i * 2 in the loop after the putchar) also has no effect.
If I insert a call to sched_yield() after the putchar, I get:
(for SCHED_RR)
11121212123123123412341234123412341234123412341234123412341234123423423434343444
(SCHED_OTHER is slightly different)
12123412341234123412341234123412341234123412341234123412341234123412341234123434
If I replace the sched_yield() call with usleep(1), I get (regardless of policy):
12341234123412341234123412341234123412341234123412341234123412341234123412341234
Maybe there's something I'm not understanding about pre-emption. Is it possible that the
scheduler isn't being called because the first thread is in the kernel with interrupts off (because
of the putchar call) every time the interval timer goes off? Seems far fetched to me.
At any rate, I'm further along than I was, so I appreciate the suggestion.