07.11.2010

CPU governors and power supply status

Update: As announced, this script collection has been incorporated into my PPA as a package. Check it out here.

As promised, here's an article on CPU governors. As You might know by now, I use Ubuntu on my laptop. Unfortunately, it was kind of useless (until now) if I didn't plug in the power supply, since the battery was drained in less than an our of work (using nothing more than a text editor, kile). The problem source: The system doesn't change the cpu governor when the power cord is plugged out. Thus, the ondemand governor is used instead of the powersave one.
Luckily, there's an easy way to cope with this. The ACPI daemon acpid can be taught to execute arbitrary code upon any ACPI event. That means You can use it to automatically change the CPU governor depending on Your power supply status. Here's how it works:
  1. Create a script to change the CPU governor. You can use mine, too:
    Code:
    #! /bin/bash

    # Note: AC connection is in:
    # /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/AC/online
    # 0 is disconnected, 1 is connected

    # If no arguments are passed, print governors
    if [ -z "$1" ]
    then
       for MYCPU in /sys/devices/system/cpu/cpu[0-9]*
       do :
          echo "$(basename $MYCPU): $(cat ${MYCPU}/cpufreq/scaling_governor)"
       done
       echo "Available (on cpu0): $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors)"
       exit 0
    fi

    # Bring governor in control
    if [ "$UID" -ne "0" ]
    then
       echo "Error: Must be run as root!"
       exit 1
    fi
    echo -n "Handling over control to $1 governor... "
    if [ "$1" == "conservative" -o "$1" == "powersave" -o "$1" == "performance" -o "$1" == "ondemand" ]
    then
       for MYCPU in /sys/devices/system/cpu/cpu[0-9]*
       do :
          echo "$1" > ${MYCPU}/cpufreq/scaling_governor
       done
    # userspace governor needs speed argument
    elif [ "$1" == "userspace" ]
    then
       if [ "$2" -gt "0" ]
       then
          for MYCPU in /sys/devices/system/cpu/cpu[0-9]*
          do :
             echo "$1" > ${MYCPU}/cpufreq/scaling_governor
             echo "$(expr $2 \* 1000)" > ${MYCPU}/cpufreq/scaling_setspeed
          done
       else
          echo "userspace governor needs speed argument > 0!"
       fi
    else
       echo "Unknown governor: '$1'"
       exit 1
    fi
    echo "done"
    Make the script executable and place it somewhere, e.g. in /usr/local/bin. You can also use the script manually from the command line, e.g. with sudo cpufreq performance if You feel like You need everything Your computer got.
  2. Create a script for the acpid and place it in /etc/acpi (the script must be executable). Mine is called powersave.sh and looks like this:
    Code:
    #! /bin/bash

    # Called by /etc/acpi/events/powersave
    # Calls cpufreq script to set cpu governor
    # Author: Frederik Möllers

    if [ "$4" -eq 0 ]
    then
       /usr/local/bin/cpufreq powersave
    else
       /usr/local/bin/cpufreq ondemand
    fi
  3. Create a rule for the acpid and place it in /etc/acpi/events. Mine is called powersave and looks like this:
    Code:
    # /etc/acpi/events/powersave
    # Calls /etc/acpi/powersave to set cpu governor when ac adapter status changes
    # Author: Frederik Möllers

    event=ac_adapter
    action=/etc/acpi/powersave.sh %e
  4. Make acpid reload its configuration (as root):
    Code:
    $ reload acpid
  5. You might think You're done now, but actually You've only finished half of the job yet. When the system boots up, there will be no ACPI event telling acpid the status of Your power supply. Thus, if You boot with the power cord plugged out, Your system will still use the ondemand governor. To deal with that, You can create an upstart script which sets the CPU governor depending on the status of the power supply. Create a file /etc/init/cpufreq.conf (or with any other filename, but keep the .conf extension!) and fill it with something like the following.
    Code:
    # cpufreq
    #
    # Sets CPU governor to ondemand if AC is plugged in and powersave if not
    # Default is performance which is kind of overkill.

    description "CPU frequency scaling"
    author "Frederik Möllers"

    start on (virtual-filesystems and local-filesystems)

    script
       if [ "$(cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/AC/online)" -eq 0 ]
       then
          sudo /usr/local/bin/cpufreq powersave
       else
          sudo /usr/local/bin/cpufreq ondemand
       fi
    end script
    WARNING: Depending on Your system, the path (/sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/) on the /sys filesystem where the status of Your power supply can be found, may differ from the one I use. It shouldn't be miles away, but especially the number following ACPI may be another one on other laptop. You might need to search for the power_supply directory manually and change the path.
  6. You're almost done! Since the default CPU governor is performance which, as I said in my script, is kind of overkill, Ubuntu ships with an init-script to set the governor to ondemand upon startup. This, however, collides with the upstart script You just created, so You need to disable that init-script (as root):
    Code:
    $ update-rc.d ondemand disable
    This will safely disable the ondemand script but will still offer You the chance to turn it back on if You ever want to revert the changes You made.
That's it! You're done!

4 Kommentare:

  1. so i dont think that i need this but i'll test it! i have no problems with the Ubuntu original script to set the governor to ondemand, because i have an applet on my desktop panel to set the CPU frequency.

    AntwortenLöschen
  2. soo i think i did erverything as ur instructions were...
    how can i test it? because my applet show for example 1.3ghz with ac-power plugged if i unplug the ac-adapter nothing happens :S
    maybe my applet (the one which ships with ubuntu) is missing something

    AntwortenLöschen
  3. If You click the applet, it should give You a list of available governors (some numbers and "ondemand", "powersave", "performance", "conservative"). Depending on the status of Your power supply, either "ondemand" or "powersave" should be selected.
    You can also use the command "cpufreq" to show the governors which are currently used.

    AntwortenLöschen