This is a specification for a project idea that I had. Basically, it is to implement a working suspend/resume/hibernate system into FreeBSD. Due to the amount of work required to add functionality to device drivers for the suspend/resume events, this project, if approved, will be a community effort. This proposal include some basic outlines of the procedures that I think are required to facilitate an effective suspend/resume/hibernate system.
The best way that I think to do this is to use a kernel thread to monitor the interrupt counters for various hardware interrupts. See vmstat(8) -i option to illustrate my point. If the watched interrupt counts do not change within a certain time frame, then the suspend system procedures are invoked. Same applies to harddisk spin down (this is independent of suspend during normal operation) and monitor timeout (screen saver mechanism?). The checks are done once a minute to minimize system overhead. The resume thread checks interrupt counts once every second. If something happens (interrupt received), then the system is brought back up. During suspend mode, the CPU is placed in either a suspend or halt mode after the thread checks counters to minimize power consumption (a good thing for laptops).
Speaking of the CPU, the automated CPU throttling thread would evaluate the system load statistics periodically and if the utilization exceeds a preset percentage threshold, then the clock frequency of the CPU is increased to bring more computational bandwidth to bear. However, if the system idle percentage exceeds a preset threshold, then the clock frequency of the CPU is scaled back to reduce power consumption. The reason why this works is because of the CMOS fabrication technology. If the digital states of CMOS logic circuits are not changing, then the power draw is usually in the picoamperes. But starting increasing the rate that the digital states change and more power is drawn. This is due to the physical construction of a CMOS transistor, which is technically known as an Insulated Gate Field Effect Transistor. The control gate is insulated from the conduction channel and therefore forms a capacitor. Capacitors are like little batteries as they store an electrical charge. When the digital state transitions from 0 to 1 or 1 to 0, that capacitor has to either charge or discharge. That causes current flow, which translates to increased power consumption and increased heat generation. This is why lowering the clock frequency of the CPU can save a considerable amount of power. This will balance system performance with power consumption as the CPU is not wasting clock cycles during the idle loop (Also a good thing for laptops).
I think that the hardest part to implement will be hibernate. I have come up with two different methods to use. I kinda like method 1 better because of the hardware issue discussed at the end of the proposal, but method 1 is far more challenging to implement than method 2. However, if there is a way to also save the hardware state of all the devices, then method 2 would be the way to go.
Please review and comment.
Thanks.
NOTE: School just started for the semester, so my personal time will be extremely limited as I am taking some pretty hard hitting classes this time around.
The best way that I think to do this is to use a kernel thread to monitor the interrupt counters for various hardware interrupts. See vmstat(8) -i option to illustrate my point. If the watched interrupt counts do not change within a certain time frame, then the suspend system procedures are invoked. Same applies to harddisk spin down (this is independent of suspend during normal operation) and monitor timeout (screen saver mechanism?). The checks are done once a minute to minimize system overhead. The resume thread checks interrupt counts once every second. If something happens (interrupt received), then the system is brought back up. During suspend mode, the CPU is placed in either a suspend or halt mode after the thread checks counters to minimize power consumption (a good thing for laptops).
Speaking of the CPU, the automated CPU throttling thread would evaluate the system load statistics periodically and if the utilization exceeds a preset percentage threshold, then the clock frequency of the CPU is increased to bring more computational bandwidth to bear. However, if the system idle percentage exceeds a preset threshold, then the clock frequency of the CPU is scaled back to reduce power consumption. The reason why this works is because of the CMOS fabrication technology. If the digital states of CMOS logic circuits are not changing, then the power draw is usually in the picoamperes. But starting increasing the rate that the digital states change and more power is drawn. This is due to the physical construction of a CMOS transistor, which is technically known as an Insulated Gate Field Effect Transistor. The control gate is insulated from the conduction channel and therefore forms a capacitor. Capacitors are like little batteries as they store an electrical charge. When the digital state transitions from 0 to 1 or 1 to 0, that capacitor has to either charge or discharge. That causes current flow, which translates to increased power consumption and increased heat generation. This is why lowering the clock frequency of the CPU can save a considerable amount of power. This will balance system performance with power consumption as the CPU is not wasting clock cycles during the idle loop (Also a good thing for laptops).
I think that the hardest part to implement will be hibernate. I have come up with two different methods to use. I kinda like method 1 better because of the hardware issue discussed at the end of the proposal, but method 1 is far more challenging to implement than method 2. However, if there is a way to also save the hardware state of all the devices, then method 2 would be the way to go.
Please review and comment.
Thanks.
NOTE: School just started for the semester, so my personal time will be extremely limited as I am taking some pretty hard hitting classes this time around.
Code:
Project: Complete rewrite of FreeBSD APM system to allow a working
suspend/resume/hibernate function.
Operational Characteristics:
Operates compeletly within the kernel via new kernel process/thread
"apmanproc"
sysctl(8) turning of operational parameters
Supports two profiles
Battery
A/C
Keyboard/Mouse timeout to suspend
Keyboard/Mouse timeout to monitor off
Automatic HD spin down inactivity timeout (HD activity only)
Automatic CPU throttling based on current load/strategy
Full Speed (No control)
Fixed Speed (No control)
Control based on system load
Adaptive (10-20% CPU reserve, 80-90% utilization)
Degraded (0% CPU reserve, always < 75% speed regardless of load)
Sleep/Suspend Events
Keyboard/Mouse inactivity timeout
Network inactivity timeout
Modem inactivity timeout
Serial Port inactivity timeout (for serial console)
Configurable via bit mask
Wake up/Resume Events
Keyboard/Mouse interrupt received
Network interrupt received
Modem interrupt received
Serial Port interrupt received
Configurable via bit mask
Sleep/Suspend Actions:
1. Send pause signal to all userland processes
2. Suspend all non-essential threads/processes via scheduler
3. Save screen data and power off monitor
4. Power down/suspend other hardware devices
5. Spin down harddisks
6. Launch watch thread that checks interrupt counters once
every second to look for wake up events according to
bit mask.
Wake up/Resume Actions:
1. Spin up harddisks
2. Wake up/resume hardware devices
- No device probe needed (already known)
- Reinit devices if needed (this is a device driver function)
3. Restore screen data and power on monitor
4. Resume threads/processes via scheduler
5. Send resume signal to all userland processes
6. Launch watch thread that checks interrupt counters once
every minute to check interrupt counters for inactivity
timeouts according to bit mask.
Hibernate:
Procedure 1:
** Each process is saved in it's own file
/boot/hibernate ?
/var/hibernate ?
File contains following information
VM Map
Core Image
Network Data
Thread/Process Data (proc/thread structures)
VNode Data
Machine State
Any other platform specific data
Suspend all processes via the scheduler
Flush all I/O buffers and deallocate
Loop for each userland process:
Read in swapped out pages (if swapon)
Write core image to disk
Write kernel data to disk (VM Map, VNode, etc)
Deallocate memory resources
Write hibernate flag to disk
Power Off
Procedure 2:
** Entire memory is written to disk in one big file
Suspend all processes via the scheduler
Flush all I/O buffers
Write hardware peripheral state to disk (If Possible)
Write all physical memory out to disk
Write hibernate flag to disk
Power Off
Resume From Hibernate:
In both cases, if the hibernate flag is found on disk, a very
small module is loaded into memory. This module reads the
file(s) from disk. However, the device probe will need to
be done again because we are resuming from a power off state
so the hardware will not be in the same state as it was
before the power off. This makes Procedure 1 more attractive
because then once the kernel boots, the processes that were
running at the time are restored. More involved to write,
but quite possibly the better solution.