We made two modifications to the Linux kernel to support our clock scheduling algorithms and data recording. The first modification provides a log of the process scheduler activity. This component is implemented as a kernel module with small code modifications to the scheduler that allow the logging to be turned on and off. For each scheduling decision, we record the process identifier of the process being scheduled, the time at which it was scheduled (with microsecond resolution) and the current clock rate.
We also implemented an extensible clock scaling policy module as a kernel module. We modified the clock interrupt handler to call the clock scheduling mechanism if it has been installed, and the Linux scheduler to keep track of CPU utilization. In Linux, the idle process always uses the zero process identifier. The idle process enters a low-power ``nap'' mode that stalls the processor pipeline until the next scheduling interval. If the previous process was not the idle process, the kernel adds the execution time to a running total. On every clock interrupt, this total is examined by the clock scaling module and then cleared. The CPU utilization can be calculated by comparing the time spent non-idle to the time length of a quantum. Our time quantum was set to 10 msec, the default scheduling period in Linux; Pering et al. [5,11] used similar values for their calculations.
Normally, a process can run for several quanta before the scheduler is called. The executing process is interrupted by the 100Hz system clock when the O/S decrements and examines a counter in the process control block at each interrupt. When that counter is zero, the scheduler is called. We set the counter to one each time we schedule a process, forcing the scheduler to be called every 10ms. While this modification adds overhead to the execution of an application, it allows us to control the clock scaling more rapidly. We measured the execution overhead and found it to be very small (about 6 microseconds for each 10ms interval, or 0.06%).