I’m puzzled by the way priorities seem to be handled on SMP systems
(with RTP CD version).
I was trying to run a thread at the highest priority with FIFO
scheduling, assigned to a CPU, thinking that the availability of other
CPU(s) would let that thread run with practically no interruption, since
other processes and the OS have CPU time. There were no other 63f
priority threads, and my 63f thread does no system call during its loop,
except possibly semaphore tests and posts.
It turns out that that 63f thread is disturbed by running other, normal
priority threads. This does not happen on the uniprocessor kernel:
there, the 63f thread effectively locks the machine, which is expected,
and it is not affected by other processes. But with the SMP kernel, this
high priority thread is slowed down (a lot!) by low priority processes.
I’ve inserted a test program that duplicates this: it sets itself to
priority 63f and loops for n iterations. It calculates the fastest and
slowest times through the loop. It accepts an optional argument, which
is a mask for the ThreadCtl(_NTO_TCTL_RUNMASK…) call.
Running this on a uniprocessor, you should get a fairly constant time.
Running this on the SMP kernel, I saw a 12-fold(!) increase in maximum
loop time (comparing the machine when quiet, and the machine running
other processes, for example pidin, continually during the test run).
So, my question is: how can I get the 63f thread’s priority honored on
SMP machines ?
Thanks in advance.
===================================================================
#include <stdio.h>
#include <errno.h>
#include <sched.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <inttypes.h>
#include <limits.h>
#define LOOP_LIMIT 1000000
main(int argc, char *argv[])
{
unsigned long count, j;
double fast, slow;
struct sched_param mysched;
uint64_t cps, currTime, cycleTime, maxTime, minTime, prevTime;
mysched.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(0, SCHED_FIFO, &mysched) == -1 )
{
printf(“Error changing scheduler to SCHED_FIFO, priority %d, error %d
%s\n”,
mysched.sched_priority, errno, strerror(errno));
}
if (argc > 1)
{
int mask;
mask = atoi(argv[1]);
if (ThreadCtl(_NTO_TCTL_RUNMASK, (void *)mask) == -1)
{
printf(“Could not assign to CPU mask %d (error %d %s)\n”,
mask, errno, strerror(errno));
}
}
for (count = 0; count < LOOP_LIMIT; ++count)
{
currTime = ClockCycles();
if (count > 0)
{
if (prevTime < currTime)
{
cycleTime = currTime - prevTime;
}
else
{
cycleTime = ULONGLONG_MAX - prevTime + currTime;
}
if (cycleTime > maxTime)
{
maxTime = cycleTime;
}
if (count > 10 && cycleTime < minTime)
{
minTime = cycleTime;
}
}
else
{
maxTime = 0;
minTime = ULONGLONG_MAX;
// Filler junk
if (maxTime < minTime)
{
cycleTime = maxTime;
}
else
{
cps = minTime;
}
}
// Filler junk
for (j = 0; j < 1000; ++j)
{
cps = count * j;
}
prevTime = currTime;
}
cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec;
fast = (double)minTime / cps;
slow = (double)maxTime / cps;
printf(“fastest %lld slowest %lld (cycles)\n”, minTime, maxTime);
printf(“fastest %f slowest %f (seconds)\n”, fast, slow);
}