[Vm-dev] [Pharo-dev] Problem with OSSubprocess / signals / heartbeat ?

Ben Coman btc at openinworld.com
Sun Apr 2 08:59:27 UTC 2017


On Sun, Apr 2, 2017 at 8:10 AM, Ben Coman <btc at openinworld.com> wrote:
>
>
>
> On Sun, Apr 2, 2017 at 3:11 AM, Petr Fischer <petr.fischer at me.com> wrote:
>>
>>
>> > On Thu, 30 Mar 2017, Eliot Miranda wrote:
>> >
>> > > Once the active process is in a tight loop the delay is effectively
>> > disabled because the tight loop effectively shuts out the heartbeat
thread
>> > and hence the system never notices that the delay has expired.
>> >
>> > I think that won't happen, because the process scheduler (O(1), CFS,
BFS) on
>> > linux is not cooperative. So, the kernel will periodically preempt the
main
>> > thread and run the heartbeat thread no matter what their priorities
are. The
>> > higher priority only provides lower jitter on the heartbeat thread.
>> >
>> > Levente
>>
>> Is there some test case or code, that I can run in Pharo and evaluate if
kernel sheduler is working correctly (with heartbeat thread at normal
priority).
>> I need to test it under FreeBSD.
>>
>> Thanks! pf
>
>
> Just for starters, what result do you get for my multi-priority fibonacci
stress test...
>
http://forum.world.st/Unix-heartbeat-thread-vs-itimer-tp4928943p4938456.html

>
> cheers -ben
>

I got curious to read up on the FreeBSD scheduler.

FreeBSD has the same constraint as Linux such that "Only the super-user may
lower priorities."
https://www.freebsd.org/cgi/man.cgi?query=setpriority&sektion=2


From
https://classes.cs.uoregon.edu/13F/cis607distcomp/PPT/FreeBSDscheduler(McKay).pdf
Each CPU has (a KSeq) three arrays of run queue indexed by priority
* The Current queue receives interactive, real time and interrupt threads
* The Next queue receives everything else except idle threads
* When Current queue is empty, the two queues swap.
* The third queue hold idle threads, and is only used when there are no
other runnable threads


>From http://web.cs.ucdavis.edu/~roper/ecs150/ULE.pdf
ULE: A Modern Scheduler For FreeBSD

A thread is assigned to a queue until it sleeps, or for the duration of a
slice.
The base priority, slice size, and interactivity score are recalculated
each time a slice expires.
The thread is assigned to the Current queue if it is interactive or to the
Next queue otherwise.
Inserting interactive tasks onto the Current queue and giving them a higher
priority
results in a very low latency response.

In ULE the interactivity of a thread is determined using its voluntary
sleep time and run time.
The voluntary sleep time is recorded by counting the number of ticks that
have passed between
a sleep() and wakeup() or while sleeping on a condition variable.
The run time is simply the number of ticks while the thread is running.
The scheduler uses the interactivity score to determine whether or not a
thread
should be assigned to the Current queue when it becomes runnable.

On x86, FreeBSD has a default HZ of 100,
and a minimum slice value of 10ms and maximum slice value of 140ms.
Interactive tasks receive the minimum slice value.
This allows us to more quickly discover that an interactive task is no
longer interactive.


From
http://ptgmedia.pearsoncmg.com/images/9780321968975/samplepages/9780321968975.pdf
The Design and Implementation of the FreeBSD Operating System

The scheduling policy initially assigns a high execution priority to each
thread
and allows that thread to execute for a fixed time slice.
Threads that execute for the duration of their slice have their priority
lowered,
whereas threads that give up the CPU (usually because they do I/O) are
allowed to remain at their priority.
Threads that are inactive have their priority raised.

Some tasks, such as the compilation of a large application, may be done in
many
small steps in which each component is compiled in a separate process.
No individual step runs long enough to have its priority degraded,
so the compilation as a whole impacts the interactive programs.
To detect and avoid this problem, the scheduling priority of a child
process is propagated back to its parent. When a new child process is
started,
it begins running with its parent’s current priority.
As the program that coordinates the compilation (typically make) starts
many compilation steps,
its priority is dropped because of the CPU-intensive behavior of its
children.
Later compilation steps started by make begin running and stay at a lower
priority,
which allows higher-priority interactive programs to run in preference to
them as desired.

Resuming a thread ...
If any threads are placed on the run queue and one of them has a scheduling
priority higher than that of the currently executing thread,
it will request that the CPU be rescheduled as soon as possible.
Real-time and interrupt threads do preempt lower-priority threads.
The kernel can be configured to preempt timeshare threads executing
in the kernel with other higher-priority timeshare threads.
This option is not used by default as the increase in context switches
adds overhead and does not help make timeshare threads response time more
predictable


>From https://github.com/freebsd/freebsd/blame/master/sys/kern/sched_ule.c
and substituting defined constants...
PRIO_MIN               -20
PRIO_MAX                20
SCHED_INTERACT_THRESH   30
SCHED_INTERACT_HALF     50 = (SCHED_INTERACT_MAX / 2)
SCHED_INTERACT_MAX     100
PRI_MIN_TIMESHARE   120
PRI_MAX_TIMESHARE   223 = (PRI_MIN_IDLE - 1)
PRI_MIN_IDLE            224

SCHED_PRI_NRESV           40 = (PRIO_MAX - PRIO_MIN)
PRI_TIMESHARE_RANGE 104 = (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE + 1)
PRI_INTERACT_RANGE    32 = ((PRI_TIMESHARE_RANGE - SCHED_PRI_NRESV) / 2)

PRI_MIN_INTERACT   120 = (PRI_MIN_TIMESHARE)
PRI_MAX_INTERACT   153 = (120 + PRI_INTERACT_RANGE - 1)

PRI_MIN_BATCH   152 = (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE)
PRI_MAX_BATCH   223 = (PRI_MAX_TIMESHARE)
SCHED_PRI_NHALF  20 = (SCHED_PRI_NRESV / 2)
SCHED_PRI_MIN   172 = (PRI_MIN_BATCH + SCHED_PRI_NHALF)
SCHED_PRI_MAX   203 = (PRI_MAX_BATCH - SCHED_PRI_NHALF)
SCHED_PRI_RANGE            30 = (SCHED_PRI_MAX - SCHED_PRI_MIN + 1)

sched_interact                  30 = (SCHED_INTERACT_THRESH)


sched_interact_score()
  if (sleep/run)>1,  interact_score = 50 / (sleep/run)
  if (sleep/run)=1,  interact_score = 50
  if (sleep/run)<1,  interact_score = 50 * (2 - (sleep/run))


sched_priority()
  * If the score is interactive we place the thread in the realtime
  * queue with a priority that is less than kernel and interrupt
  * priorities.  These threads are not subject to nice restrictions.
  *
  * Scores greater than this are placed on the normal timeshare queue
  * where the priority is partially decided by the most recent cpu
  * utilization and the rest is decided by nice value.
  *
  * The nice value of the process has a linear effect on the calculated
  * score.  Negative nice values make it easier for a thread to be
  * considered interactive. Default nice is 0.
  *
  score = sched_interact_score() + nice);
  if (score < (30))
     priority = 120 + score*34/30    // = 120 + (153 - 120 + 1) / 30 *
score
  else
     priority = 201 + nice           // = 172 + 30 - 1 + nice


sched_add(struct thread *td, int flags)
  * Select the target thread queue and add a thread to it.
  * Request preemption or IPI a remote processor if required.
  * Recalculate the priority before we select the target cpu or run-queue.
  *
  if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE)
     sched_priority(td);
  ...

So it seems as long as "sleep/run > 2" then it seems
FreeBSD heatbeat-thread will get an interactive priority bump.

cheers -ben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20170402/d8e0f577/attachment-0001.html>


More information about the Vm-dev mailing list