laptopd.py is a script that run in the background and that
control various parameters of my laptop, such as frequency scaling,
throttling, and so on, as a function of temperature, battery status, and
more parameters that can influence the computer "behaviour".
Now, someone could ask: why? There are a lot of similar things around. Just to a couple of them I know:
- cpudyn, that controls CPU frequency scaling (and disk stand-by);
- cpufreqd, a similar software although quite different.
I decided to write another one because I would like to have more flexibility. I'd like to control not only the frequency scaling, but throttling too, and maybe someday the LCD intensity; and make decisions not only with temperature or ac power or battery level by with an arbitrary combinations of this variables.
Such a lot of flexibility means just one thing. A programming language. So what I did is write a Python program that will enable to write a very little set of routines to achieve, for example, the following behaviour on my laptop:
- if core temperature raise over 74 Celsius, throttle down the CPU (by trottling to 4 and scaling down frequencies), whatever the AC plug is in or not; resume normal behaviour when cooled down to 72 C.
- if that is not sufficient, and temperature did not goes down, put throttling at 8. If you think it's overprotective, you do not use your laptop in Madrid in summer.
- if I'm running on battery, my main objective is to spare energy, so go to powersave at low clock speed and enable laptop-mode;
- but if battery goes down 10%, disable laptop-mode so that I do not risk losing data.
To understand and modify the behavior, download laptopd.py
and have a look at it.
To tailor the daemon to your personal taste, you have simply to change
the functions ac_changed, temp_changed,
batt_changed. As the name suggest, they are called by the
main loop whenever a change in the AC adapter status, core temperature or
battery charge value do happen. They are passed to arguments, respectively
the old and the new value of the parameter that has changed.
You have available a serie of functions:
| read_thrott() | returns the current throttling value |
| set_thrott(thr) | set the current throttling value |
| read_freq() | returns the current clock frequency |
| set_powersave(min, max) | choose the powersave policy for clock scaling, with frequency variable between min to max (min and max are in percentage units: 0 means minimum, 100 maximum) |
| set_performance(min, max) | As above, but with performance policy. |
| read_laptopmode() | returns 0 if laptopmode is not set, different from 0 otherwise. |
| start_laptopmode() | enable laptopmode (via the script /usr/sbin/laptop-mode) |
| stop_laptopmode() | Guess what? |
| read_ac() | 1 if laptop is running on mains, 0 if on battery |
| read_temp() | returns current core temperature |
| warning(string) | write a message on the syslog facility. |
More info on the meaning of all the above can be found in the
ACPI pages and in the kernel
Documentation/ directory itself.
For laptopd to work, in your kernel
you should have sysfs compiled in and
mounted under /sys, and the ACPI /proc reporting selected (it
is said it's deprecated, but yet I didn't find any way to get the same info
from sysfs). If any of the values cannot be read correctly, the special
value FAIL is returned (it's -10000, btw). That could happen during
suspend/restore, when modules are unloaded and facilities stopped.
laptopd will continue to run, waiting for better times.
I found that throttling is very effective for cooling down the core, much more than frequency scaling. My policy is implemented by this part of the code:
# temperature thresholds
temp_high_threshold = 74
temp_low_threshold = 72
def ac_changed(ac_was, ac_is):
# warning("ac changed: %d -> %d" % (ac_was, ac_is))
# when ac is on, shut off laptop mode
if ac_is==1:
warning("stopping laptopmode")
stop_laptopmode()
if read_temp()<temp_high_threshold:
warning("going full speed")
set_performance(0,100)
else:
warning("start laptopmode and going powersave")
start_laptopmode()
set_powersave(0,0)
return
def temp_changed(temp_was, temp_is):
# warning("temp changed: %d -> %d" % (temp_was, temp_is))
thrott=read_thrott()
ac=read_ac()
if thrott!=0 and temp_is>temp_high_threshold:
warning("WAY TOO HOT, getting drastic!!!")
set_thrott(8)
set_powersave(0,0)
if thrott==0 and temp_is>temp_high_threshold:
warning("too hot, throtthling down")
set_thrott(4)
if ac==1: #on main
set_performance(0,0)
else:
set_powersave(0,0)
if thrott!=0 and temp_is<temp_low_threshold:
warning("cooled down, going fast again")
set_thrott(0)
if ac==1:
set_performance(0, 100)
else:
set_powersave(0, 100)
return
def batt_changed(batt_was, batt_is):
#warning("batt changed: %d -> %d" % (batt_was, batt_is))
if batt_is < 10:
warning("Low on battery. Stop laptopmode for safety")
stop_laptopmode()
return
and yes, it's better if you understand Python, but I think it's quite easy
to understand at a glance.
Now, you can go back to the main Sony vaio page.
