On Sun, Apr 2, 2017 at 8:10 AM, Ben Coman btc@openinworld.com wrote:
On Sun, Apr 2, 2017 at 3:11 AM, Petr Fischer petr.fischer@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... 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
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/978032196897... 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