Begin File: scheduler.tgz Description:Round Robin Scheduler Keywords: scheduler Version: Entered-date: July 29 1997 Author: Ported-by: Original-site: QNX Copying-policy: Free Supplemental: 4/16/97 slice.txt dkelly@fdma.com ------------------ Goal: Implement a fixed (but selectable) round robin time-slice mechanism. Problem: QNX timeslicer runs at a fixed 50ms, independent of ticksize (which is adjustable). However, the process manager (independent of the timeslicer) runs the highest priority "ready" task after each hardware interrupt has occured, and each time a running task blocks. Re-evaluation of priorities after an interrupt assures that the interrupt handler's "proxy" task runs immediately. Solution: To effectively select another timeslice, a high priority scheduler task must lower the priority of the current task and raise the priority of the next task to run. This scheduler task must periodically gain control (via proxy) from a hardware timer interrupt. The period of this timer represents the effective timeslice interval. The scheduler then modifies the priorities and blocks - allowing the new highest priority task to run until the timer expires again. Details: The hardware timer sends a proxy to the blocked, high priority scheduler. It unblocks only long enough to lower the priority of one task and raise the priority of another. When it again blocks, the process manager will be required to run the highest blocked task. Of course, this will be the "new" current task, not the previous one. The timesliced tasks themselves must never yield control (block). Implementation: There are two source files, slice.c (main) and handler.c (interrupt). The use of the Makefile is required due to special options for handler.c. The files one.c, two.c, three.c and four.c are the tasks to be started by the scheduler. Notice that they never give up their timeslice - this is the only way that uniform timeslicing can be guaranteed by this example. If I were coding this applications, I would use tfork() rather than spawning separate executables. tfork() spawns a new pid for the tfork'd process but the data segment is common. This produces a pseudo-thread. Advantages I see to tfork()... 1. can share common ram (no need to use shm_open()...) 2. threads are killed when the parent dies (no signal handlers to write) 3. no extra files or extra load time since their code is part of the main executable. Parameters: SLICE_MS selects the number of milliseconds of the timeslice SLICE_TASKS is the nubmer of tasks to switch between SLICE_PRIO is the priority of the scheduler - must be higher then the tasks and higher than "normal" tasks of the o/s. SLICE_RUN is the priority of the running process (below scheduler) SLICE_SLEEP is the priority of the sleeping process (below running process) Testing: I have not actually verified that it is timelicing correctly. I have only verified that the timer is firing 1000 times per second and that priorities are being altered. I do know that 100% of the processor is being spent at priority SLICE_RUN. Problems: The timeslicer itself is also tinkering with the priorities. If it runs AFTER us on every 50th timer event, it could introduce some inconsistency to the time slices. However, this scheduler would restore its own order withing 1 ms. End