cpufreqd-devel Mailing List for cpufreq daemon (Page 4)
Brought to you by:
mattia-san
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(8) |
Jun
(8) |
Jul
(23) |
Aug
(9) |
Sep
|
Oct
(8) |
Nov
|
Dec
(6) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
|
Feb
(2) |
Mar
(1) |
Apr
(1) |
May
(33) |
Jun
|
Jul
(21) |
Aug
(89) |
Sep
(70) |
Oct
(10) |
Nov
(6) |
Dec
(12) |
2006 |
Jan
(5) |
Feb
(4) |
Mar
(9) |
Apr
(11) |
May
(3) |
Jun
(22) |
Jul
(23) |
Aug
(1) |
Sep
(8) |
Oct
|
Nov
(9) |
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
(13) |
Aug
(11) |
Sep
(1) |
Oct
(1) |
Nov
(11) |
Dec
(2) |
2009 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
|
Dec
|
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Mattia D. <mal...@li...> - 2006-07-04 12:27:05
|
On Tue, July 4, 2006 1:21 am, Christian Krafft said: > Mattia Dongili wrote: >> Can you try the attached patches against the source you downloaded? >> They'll hopefully fix both problems. >> >> Thanks again > > Your patches worked out great: Excellent!! If I may ask you one last question: could you send me (even privately if you prefer) the [bg]zipped log of a cpufreqd session on your SMP system (with full verbosity obviously)? Just one or two minutes of cpufreqd running is enough. I'd like to take a look at it, as I've never seen cpufreqd running on an SMP (I had some positive reports but nothing more). Thanks again --=20 mattia :wq! |
From: Christian K. <par...@bo...> - 2006-07-03 23:24:08
|
Mattia Dongili wrote: > Can you try the attached patches against the source you downloaded? > They'll hopefully fix both problems. > > Thanks again Your patches worked out great: <snip> Every 0.1s: ./cpufreq_dump Tue Jul 4 02:11:13 2006 --- CPU cpu0: governor: powersave max speed: 960000 current speed: 320000 min speed: 320000 --- --- CPU cpu1: governor: powersave max speed: 960000 current speed: 320000 min speed: 320000 --- --- CPU cpu2: governor: performance max speed: 3200000 current speed: 3200000 min speed: 320000 --- --- CPU cpu3: governor: performance max speed: 3200000 current speed: 3200000 min speed: 320000 --- </snip> You helped me a lot ;-) I owe you something! cheers, ck PS: I guess youre right about the userspace vs governor, too. |
From: Mattia D. <mal...@li...> - 2006-07-03 18:25:41
|
On Mon, Jul 03, 2006 at 07:04:20PM +0200, Christian Krafft wrote: [...] > I found some problems, but I did not track them down so far. > > 1st, it seems to be not a good idea to create profiles with an > underscore in the name. cpufreqd complains: > > No Profile with name "ondemand" found for Rule "cpu0_ondemand" for CPU0. Ooops I wrongly limited the name of the policy to this set: [a-zA-Z0-9 ] Will fix it, could you try to stick with it in the meantime? :) > 2nd, after removing the underscore cpufreqd segfaults: > > # cpufreqd -V 7 -D -f /etc/cpufreqd.conf [...] > parse_config_profile : [Profile] "ondemandrule" MAX is 3200000, MIN is 320000 > parse_config_profile : [Profile] "powersaverule" MAX is 960000, MIN is 320000 > plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=0:30-100) > cpu_parse : cpu interval: 0:30-100 > cpu_parse : read CPU:0 MIN:30 MAX:100 SCALE:3.00 > plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=2:30-100) > cpu_parse : cpu interval: 2:30-100 > cpu_parse : read CPU:2 MIN:30 MAX:100 SCALE:3.00 > plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=0:10-30) > cpu_parse : cpu interval: 0:10-30 > cpu_parse : read CPU:0 MIN:10 MAX:30 SCALE:3.00 > plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=2:10-30) > cpu_parse : cpu interval: 2:10-30 > cpu_parse : read CPU:2 MIN:10 MAX:30 SCALE:3.00 > init_configuration : Rule "cpu0_ondemand" has Profiles CPU0:ondemandrule CPU1:(null) CPU2:(null) CPU3:(null) > init_configuration : Rule "cpu2_ondemand" has Profiles CPU0:(null) CPU1:(null) CPU2:ondemandrule CPU3:(null) > init_configuration : Rule "cpu0_powersave" has Profiles CPU0:powersaverule CPU1:(null) CPU2:(null) CPU3:(null) > init_configuration : Rule "cpu2_powersave" has Profiles CPU0:(null) CPU1:(null) CPU2:powersaverule CPU3:(null) here we go! all those null-s probably are triggering the segfault later [...] > get_cpu : called > get_cpu : CPU4 c_user=16116 c_nice=0 c_sys=25014 c_idle=459350 c_iowait=778 c_irq=1953 c_softirq=1171. > get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. > get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. > get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. > get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. and this sucks big time too! aargh, it seems I have some bug to fix :) CPU4 is the cumulative for all cpus (first line of /proc/stat) the others are simply wrong... Can you try the attached patches against the source you downloaded? They'll hopefully fix both problems. Thanks again -- mattia :wq! |
From: Mattia D. <mal...@li...> - 2006-07-03 17:34:46
|
Hello! On Mon, Jul 03, 2006 at 04:03:36PM +0200, Christian Krafft wrote: > Hi Mattia, > > Thanks for your quick update ;-) > > I will test it as soon as I can. Maybe I get it running this ev. > Otherwise I'll come back tomorrow. Great!! thanks a lot. running cpufreqd with -D -V7 and grepping for interesting lines should give an idea of what's happening. I also modified cpufreqd-get to be able to read currently applied profiles for each cpu, run 'cpufreqd-get -l' to get it. > In the meantime, I tried to figure out, if inotify with sysfs is an > acceptable use pattern for kernel drivers. > If so, it would be possible, to write a threshold to a file i.e. > /sys/devices/system/cpu/cpu0/temp_threshold > and register for a file i.e. > /sys/devices/system/cpu/cpu0/temp_threshold_exeeded but this would require kernel support which is not in place. Unfortunately, the only temperature monitoring support I know of (and I experienced) are ACPI and lm_sensors, the latter has its sysfs files in /sys/bus/i2c/drivers/asb100/0-002d/... which is a symlink to an even uglier location :) I also don't know (yet) if there's a reliable way to tell _which_ sensor monitors the cpu temperature, eg: I have: # ls /sys/bus/i2c/drivers/asb100/0-002d/temp* /sys/bus/i2c/drivers/asb100/0-002d/temp1_input /sys/bus/i2c/drivers/asb100/0-002d/temp1_max /sys/bus/i2c/drivers/asb100/0-002d/temp1_max_hyst /sys/bus/i2c/drivers/asb100/0-002d/temp2_input /sys/bus/i2c/drivers/asb100/0-002d/temp2_max /sys/bus/i2c/drivers/asb100/0-002d/temp2_max_hyst /sys/bus/i2c/drivers/asb100/0-002d/temp3_input /sys/bus/i2c/drivers/asb100/0-002d/temp3_max /sys/bus/i2c/drivers/asb100/0-002d/temp3_max_hyst /sys/bus/i2c/drivers/asb100/0-002d/temp4_input /sys/bus/i2c/drivers/asb100/0-002d/temp4_max /sys/bus/i2c/drivers/asb100/0-002d/temp4_max_hyst A different approach may be digging into the NETLINK stuff and see which informations are delivered through it, other power management deamons are already using it afaik (through dbus). I found this old thread some time ago: http://lkml.org/lkml/2004/7/23/99 It probably turned into the uevent stuff (lib/kobject_uevent.c) that left out the power management stuff. > If one gets triggered, you can write a new threshold and register for a > change again. With cpu affinity, cpufreqd could send processes to a > colder cpu to avoid heavy load on the hot one. This would let the > on-demand gov slow it down, and thus cool it, without the need of > throttling it down explicitely from userspace side. This would ensure > that the response time does not go down too much. This is starting to sound pretty interesting, if not from a cpufreqd POV, at least from the kernel's. I mean, it would be quite invasive (IMO) implementing it in userspace, you'd need a much more detailed process accounting than cpufreqd currently has and userspace responsiveness is too low IMO for this task. While the kernel already has all the necessary info and can act in the cpu scheduler probably. It could be a nice add-on to existing governors (or a completely new one, or just a listener for cpufreq events that increases a cpu priority when scheduling): moving processes on cpus that have the higer max_freq if they have spare clock cycles to avoid cpufreq switches. > I don't know much about /proc/acpi though, but I guess sysfs is the > better approch to read attributes, instead of parsing prose text acpi > files ;-) unfortunately all the /proc/<pid> will stay there and /proc/acpi is not scheduled to move very soon (afaict), cpufreqd still has to cope with them (at least in some plugins) > acpi is not supported on much platforms, too. but it has a pretty large market share :) Anyway for the sake of this thread, let's say we can live without it :) Thanks again -- mattia :wq! |
From: Christian K. <kr...@de...> - 2006-07-03 17:04:51
|
Christian Krafft wrote: > Hi Mattia, > > Thanks for your quick update ;-) > > I will test it as soon as I can. Maybe I get it running this ev. > Otherwise I'll come back tomorrow. > > In the meantime, I tried to figure out, if inotify with sysfs is an > acceptable use pattern for kernel drivers. > If so, it would be possible, to write a threshold to a file i.e. > /sys/devices/system/cpu/cpu0/temp_threshold > and register for a file i.e. > /sys/devices/system/cpu/cpu0/temp_threshold_exeeded > If one gets triggered, you can write a new threshold and register for a > change again. With cpu affinity, cpufreqd could send processes to a > colder cpu to avoid heavy load on the hot one. This would let the > on-demand gov slow it down, and thus cool it, without the need of > throttling it down explicitely from userspace side. This would ensure > that the response time does not go down too much. > I don't know much about /proc/acpi though, but I guess sysfs is the > better approch to read attributes, instead of parsing prose text acpi > files ;-) > acpi is not supported on much platforms, too. > > Mattia Dongili wrote: > >> On Sun, Jul 02, 2006 at 04:41:06PM +0200, Mattia Dongili wrote: >> >>> On Sun, Jul 02, 2006 at 12:39:19PM +0200, Christian Krafft wrote: >>> >>>> On Sat, 2006-07-01 at 23:08 +0200, Mattia Dongili wrote: >>>> >>>> >>>>> what about modifing the Rule->Profile association directive to allow >>>>> (and understand) things like: >>>>> [Rule] >>>>> ... >>>>> profile=CPU0:profile1;CPU1:profile2;... >>>>> # if CPUn is not covered just don't apply anything >>>>> [/Rule] >>>>> >>>>> This way one could better reuse already written profiles. Yes, I like >>>>> the idea :) >>>> >>>> >>>> sounds good to me, too. >>> >>> >>> I'm implementing it right now, let's see if I can get to a decent point >>> by today. >>> Out of curiosity: do you have an SMP system where you could test the >>> result? :) >> >> >> >> done, the code is in cpufreqd CVS or here: >> http://people.debian.org/~malattia/packages/cpufreqd-2.1.1.tar.bz2 >> >> I didn't bump the version yet (it'll become 2.2.0)... >> The diffstat is pretty big, I didn't expect so many changes were needed: >> >> manpages/cpufreqd-get.1 | 12 +- >> manpages/cpufreqd.conf.5 | 7 + >> src/config_parser.c | 122 ++++++++++++++++++++---- >> src/config_parser.h | 7 - >> src/cpufreqd_exec.c | 40 ++++++-- >> src/cpufreqd_governor_parameters.c | 130 ++++++++++++-------------- >> src/cpufreqd_nforce2.c | 57 +++++++---- >> src/cpufreqd_nvclock.c | 147 ++++++++++++++++++----------- >> src/cpufreqd_plugin.h | 18 ++- >> src/cpufreqd_remote.h | 1 >> src/main.c | 185 >> +++++++++++++++++++++++-------------- >> utils/getspeed.c | 31 ++++-- >> 12 files changed, 499 insertions(+), 258 deletions(-) >> >> I could't test it on an SMP, as I don't have any such system, if >> somebody would like to, please post your result/impressions. >> The only thing I can tell is that it still work on my UP. >> >> Thanks > > > I found some problems, but I did not track them down so far. 1st, it seems to be not a good idea to create profiles with an underscore in the name. cpufreqd complains: No Profile with name "ondemand" found for Rule "cpu0_ondemand" for CPU0. although the rule definition states: [Rule] name=cpu0_ondemand cpu_interval=0:30-100 profile=CPU0:ondemand_rule [/Rule] 2nd, after removing the underscore cpufreqd segfaults: # cpufreqd -V 7 -D -f /etc/cpufreqd.conf read_args : Using configuration file at /etc/cpufreqd.conf get_kversion : read kernel version 2.6.17-SDK-ck. get_kversion : kernel version is 2.6. get_cpu_num : found 4 CPUs main : Limits for cpu0: MIN=320000 - MAX=3200000 main : Limits for cpu1: MIN=320000 - MAX=3200000 main : Limits for cpu2: MIN=320000 - MAX=3200000 main : Limits for cpu3: MIN=320000 - MAX=3200000 init_configuration : reading configuration file /etc/cpufreqd.conf discover_plugins : found plugin: governor_parameters discover_plugins : found plugin: exec discover_plugins : found plugin: pmu discover_plugins : found plugin: apm discover_plugins : found plugin: nforce2 discover_plugins : found plugin: acpi discover_plugins : found plugin: cpu discover_plugins : found plugin: programs load_plugin : Loading "/usr/local/lib/cpufreqd_governor_parameters.so" for plugin "governor_parameters". get_cpufreqd_object : Getting plugin object for "governor_parameters". initialize_plugin : Initializing plugin "governor_parameters-governor_parameters". gov_parameter_init : called gov_parameter_init : sysfs mount path = /sys gov_parameter_init : sysfs path cpu device = /sys/devices/system/cpu load_plugin_list : plugin loaded: governor_parameters load_plugin : Loading "/usr/local/lib/cpufreqd_exec.so" for plugin "exec". get_cpufreqd_object : Getting plugin object for "exec". initialize_plugin : Initializing plugin "exec-exec". load_plugin_list : plugin loaded: exec load_plugin : Loading "/usr/local/lib/cpufreqd_pmu.so" for plugin "pmu". get_cpufreqd_object : Getting plugin object for "pmu". initialize_plugin : Initializing plugin "pmu-pmu_plugin". pmu_init : /proc/pmu/info: No such file or directory load_plugin_list : plugin failed to load: pmu load_plugin_list : discarded plugin pmu load_plugin : Loading "/usr/local/lib/cpufreqd_apm.so" for plugin "apm". get_cpufreqd_object : Getting plugin object for "apm". initialize_plugin : Initializing plugin "apm-apm_plugin". apm_init : /proc/apm: No such file or directory load_plugin_list : plugin failed to load: apm load_plugin_list : discarded plugin apm load_plugin : Loading "/usr/local/lib/cpufreqd_nforce2.so" for plugin "nforce2". get_cpufreqd_object : Getting plugin object for "nforce2". initialize_plugin : Initializing plugin "nforce2-nforce2_atxp1". load_plugin_list : plugin loaded: nforce2_atxp1 load_plugin : Loading "/usr/local/lib/cpufreqd_acpi.so" for plugin "acpi". get_cpufreqd_object : Getting plugin object for "acpi". initialize_plugin : Initializing plugin "acpi-acpi". load_plugin_list : plugin loaded: acpi load_plugin : Loading "/usr/local/lib/cpufreqd_cpu.so" for plugin "cpu". get_cpufreqd_object : Getting plugin object for "cpu". initialize_plugin : Initializing plugin "cpu-cpu_plugin". cpufreqd_cpu_init : called load_plugin_list : plugin loaded: cpu_plugin load_plugin : Loading "/usr/local/lib/cpufreqd_programs.so" for plugin "programs". get_cpufreqd_object : Getting plugin object for "programs". initialize_plugin : Initializing plugin "programs-programs_plugin". load_plugin_list : plugin loaded: programs_plugin parse_config_general : poll_interval is 1.0 seconds parse_config_general : WARNING! "enable_plugins" is now deprecated and ignored, see man 5 cpufreqd.conf parse_config_general : skipping "verbosity", overridden in the command line. parse_config_general : Remote control enabled. parse_config_general : Remote controls will be r/w for group root (0). nforce2_post_conf : Unconfigured, exiting. plugins_post_conf : Unable to configure plugin nforce2_atxp1, removing finalize_plugin : Finalizing plugin "nforce2-nforce2_atxp1". close_plugin : nforce2 plugin closed. acpi_post_conf : Initializing AC acpi_ac_init : no acpi_ac module compiled or inserted? (/proc/acpi/ac_adapter/: No such file or directory) acpi_post_conf : Initializing BATTERY acpi_battery_init : error, acpi_battery module not compiled or inserted (/proc/acpi/battery/: No such file or directory)? acpi_battery_init : exiting. acpi_post_conf : Initializing TEMPERATURE acpi_temperature_init : no acpi_temperature support found /proc/acpi/thermal_zone/ acpi_post_conf : Initializing EVENT acpi_event_init : Couldn't connect to acpid socket /var/run/acpid.socket (No such file or directory). plugins_post_conf : Unable to configure plugin acpi, removing finalize_plugin : Finalizing plugin "acpi-acpi". close_plugin : acpi plugin closed. parse_config_profile : [Profile] "ondemandrule" MAX is 3200000, MIN is 320000 parse_config_profile : [Profile] "powersaverule" MAX is 960000, MIN is 320000 plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=0:30-100) cpu_parse : cpu interval: 0:30-100 cpu_parse : read CPU:0 MIN:30 MAX:100 SCALE:3.00 plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=2:30-100) cpu_parse : cpu interval: 2:30-100 cpu_parse : read CPU:2 MIN:30 MAX:100 SCALE:3.00 plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=0:10-30) cpu_parse : cpu interval: 0:10-30 cpu_parse : read CPU:0 MIN:10 MAX:30 SCALE:3.00 plugin_handle_keyword : Plugin cpu_plugin handles keyword cpu_interval (value=2:10-30) cpu_parse : cpu interval: 2:10-30 cpu_parse : read CPU:2 MIN:10 MAX:30 SCALE:3.00 init_configuration : Rule "cpu0_ondemand" has Profiles CPU0:ondemandrule CPU1:(null) CPU2:(null) CPU3:(null) init_configuration : Rule "cpu2_ondemand" has Profiles CPU0:(null) CPU1:(null) CPU2:ondemandrule CPU3:(null) init_configuration : Rule "cpu0_powersave" has Profiles CPU0:powersaverule CPU1:(null) CPU2:(null) CPU3:(null) init_configuration : Rule "cpu2_powersave" has Profiles CPU0:(null) CPU1:(null) CPU2:powersaverule CPU3:(null) create_temp_dir : Created temporary dir: '/tmp/cpufreqd-ZlJHGb'. main : Remote controls enabled validate_plugins : exec plugin is unused. finalize_plugin : Finalizing plugin "exec-exec". close_plugin : exec plugin closed. validate_plugins : programs plugin is unused. finalize_plugin : Finalizing plugin "programs-programs_plugin". programs_exit : called close_plugin : programs plugin closed. cpufreqd_loop : Current time is: 1151949076::8332 get_cpu : called get_cpu : CPU4 c_user=16116 c_nice=0 c_sys=25014 c_idle=459350 c_iowait=778 c_irq=1953 c_softirq=1171. get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. get_cpu : CPU3 c_user=3828 c_nice=0 c_sys=5583 c_idle=116183 c_iowait=36 c_irq=291 c_softirq=173. update_rule_scores : Considering Rule "cpu0_ondemand" cpu_evaluate : CPU0 user=0 nice=0 sys=0 calculate_cpu_usage : CPU delta_activity=0 delta_time=0 weighted_activity=0. cpu_evaluate : CPU0 100% - min=30 max=100 scale=3.00 rule_score : Rule "cpu0_ondemand": cpu_interval matches. update_rule_scores : Rule "cpu0_ondemand" score: 101% update_rule_scores : Considering Rule "cpu2_ondemand" cpu_evaluate : CPU2 user=0 nice=0 sys=0 calculate_cpu_usage : CPU delta_activity=0 delta_time=0 weighted_activity=0. cpu_evaluate : CPU2 100% - min=30 max=100 scale=3.00 rule_score : Rule "cpu2_ondemand": cpu_interval matches. update_rule_scores : Rule "cpu2_ondemand" score: 101% update_rule_scores : Considering Rule "cpu0_powersave" cpu_evaluate : CPU0 user=0 nice=0 sys=0 calculate_cpu_usage : CPU delta_activity=0 delta_time=0 weighted_activity=0. cpu_evaluate : CPU0 100% - min=10 max=30 scale=3.00 update_rule_scores : Rule "cpu0_powersave" score: 0% update_rule_scores : Considering Rule "cpu2_powersave" cpu_evaluate : CPU2 user=0 nice=0 sys=0 calculate_cpu_usage : CPU delta_activity=0 delta_time=0 weighted_activity=0. cpu_evaluate : CPU2 100% - min=10 max=30 scale=3.00 update_rule_scores : Rule "cpu2_powersave" score: 0% cpufreqd_loop : New Rule ("cpu0_ondemand"), applying. cpufreqd_set_profile : Profile "ondemandrule" set for CPU0 Segmentation fault I will have a closer look tomorrow. Maybe it is caused by one of the plugins, I have not disabled while building (they are not enabled in config file though). Cheers, Christian Krafft |
From: Christian K. <kr...@de...> - 2006-07-03 14:04:37
|
Hi Mattia, Thanks for your quick update ;-) I will test it as soon as I can. Maybe I get it running this ev. Otherwise I'll come back tomorrow. In the meantime, I tried to figure out, if inotify with sysfs is an acceptable use pattern for kernel drivers. If so, it would be possible, to write a threshold to a file i.e. /sys/devices/system/cpu/cpu0/temp_threshold and register for a file i.e. /sys/devices/system/cpu/cpu0/temp_threshold_exeeded If one gets triggered, you can write a new threshold and register for a change again. With cpu affinity, cpufreqd could send processes to a colder cpu to avoid heavy load on the hot one. This would let the on-demand gov slow it down, and thus cool it, without the need of throttling it down explicitely from userspace side. This would ensure that the response time does not go down too much. I don't know much about /proc/acpi though, but I guess sysfs is the better approch to read attributes, instead of parsing prose text acpi files ;-) acpi is not supported on much platforms, too. Mattia Dongili wrote: > On Sun, Jul 02, 2006 at 04:41:06PM +0200, Mattia Dongili wrote: > >>On Sun, Jul 02, 2006 at 12:39:19PM +0200, Christian Krafft wrote: >> >>>On Sat, 2006-07-01 at 23:08 +0200, Mattia Dongili wrote: >>> >>> >>>>what about modifing the Rule->Profile association directive to allow >>>>(and understand) things like: >>>>[Rule] >>>>... >>>>profile=CPU0:profile1;CPU1:profile2;... >>>># if CPUn is not covered just don't apply anything >>>>[/Rule] >>>> >>>>This way one could better reuse already written profiles. Yes, I like >>>>the idea :) >>> >>>sounds good to me, too. >> >>I'm implementing it right now, let's see if I can get to a decent point >>by today. >>Out of curiosity: do you have an SMP system where you could test the >>result? :) > > > done, the code is in cpufreqd CVS or here: > http://people.debian.org/~malattia/packages/cpufreqd-2.1.1.tar.bz2 > > I didn't bump the version yet (it'll become 2.2.0)... > The diffstat is pretty big, I didn't expect so many changes were needed: > > manpages/cpufreqd-get.1 | 12 +- > manpages/cpufreqd.conf.5 | 7 + > src/config_parser.c | 122 ++++++++++++++++++++---- > src/config_parser.h | 7 - > src/cpufreqd_exec.c | 40 ++++++-- > src/cpufreqd_governor_parameters.c | 130 ++++++++++++-------------- > src/cpufreqd_nforce2.c | 57 +++++++---- > src/cpufreqd_nvclock.c | 147 ++++++++++++++++++----------- > src/cpufreqd_plugin.h | 18 ++- > src/cpufreqd_remote.h | 1 > src/main.c | 185 +++++++++++++++++++++++-------------- > utils/getspeed.c | 31 ++++-- > 12 files changed, 499 insertions(+), 258 deletions(-) > > I could't test it on an SMP, as I don't have any such system, if > somebody would like to, please post your result/impressions. > The only thing I can tell is that it still work on my UP. > > Thanks |
From: Mattia D. <mal...@li...> - 2006-07-02 20:21:10
|
On Sun, Jul 02, 2006 at 04:41:06PM +0200, Mattia Dongili wrote: > On Sun, Jul 02, 2006 at 12:39:19PM +0200, Christian Krafft wrote: > > On Sat, 2006-07-01 at 23:08 +0200, Mattia Dongili wrote: > > > > > what about modifing the Rule->Profile association directive to allow > > > (and understand) things like: > > > [Rule] > > > ... > > > profile=CPU0:profile1;CPU1:profile2;... > > > # if CPUn is not covered just don't apply anything > > > [/Rule] > > > > > > This way one could better reuse already written profiles. Yes, I like > > > the idea :) > > > > sounds good to me, too. > > I'm implementing it right now, let's see if I can get to a decent point > by today. > Out of curiosity: do you have an SMP system where you could test the > result? :) done, the code is in cpufreqd CVS or here: http://people.debian.org/~malattia/packages/cpufreqd-2.1.1.tar.bz2 I didn't bump the version yet (it'll become 2.2.0)... The diffstat is pretty big, I didn't expect so many changes were needed: manpages/cpufreqd-get.1 | 12 +- manpages/cpufreqd.conf.5 | 7 + src/config_parser.c | 122 ++++++++++++++++++++---- src/config_parser.h | 7 - src/cpufreqd_exec.c | 40 ++++++-- src/cpufreqd_governor_parameters.c | 130 ++++++++++++-------------- src/cpufreqd_nforce2.c | 57 +++++++---- src/cpufreqd_nvclock.c | 147 ++++++++++++++++++----------- src/cpufreqd_plugin.h | 18 ++- src/cpufreqd_remote.h | 1 src/main.c | 185 +++++++++++++++++++++++-------------- utils/getspeed.c | 31 ++++-- 12 files changed, 499 insertions(+), 258 deletions(-) I could't test it on an SMP, as I don't have any such system, if somebody would like to, please post your result/impressions. The only thing I can tell is that it still work on my UP. Thanks -- mattia :wq! |
From: Mattia D. <mat...@us...> - 2006-07-02 20:14:20
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv19410/src Modified Files: config_parser.c config_parser.h cpufreqd_exec.c cpufreqd_governor_parameters.c cpufreqd_nforce2.c cpufreqd_nvclock.c cpufreqd_plugin.h cpufreqd_remote.h main.c Log Message: introduce the definitive SMP awarness for cpufreqd Index: cpufreqd_nvclock.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_nvclock.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- cpufreqd_nvclock.c 12 Mar 2006 10:42:34 -0000 1.7 +++ cpufreqd_nvclock.c 2 Jul 2006 20:14:13 -0000 1.8 @@ -27,44 +27,84 @@ #include "cpufreqd_plugin.h" #include "nvclock.h" +/* avoid being called for _every_ cpu switching freq, + * just run our stuff on the last one + */ +int nvcore_profile_calls; +int nvmem_profile_calls; + struct nvclock_elem { int card; unsigned int value; /* used for gpu and mem clock */ }; +static void nvcore_change(struct nvclock_elem *nv) { + + if (nv->card < nvclock.num_cards) { + clog(LOG_INFO, "Setting nv_core for card %i to (%u)\n", nv->card, nv->value); + set_card(nv->card); + if(nv_card.supported & GPU_OVERCLOCKING_SUPPORTED) + nv_card.set_gpu_speed(nv->value); + unset_card(); + } +} -static int nvclock_init(void); -static int nvclock_parse(const char *ev, void **obj); +static void nvmem_change(struct nvclock_elem *nv) { + + if (nv->card < nvclock.num_cards) { + clog(LOG_INFO, "Setting nv_mem for card %i to (%u)\n", nv->card, nv->value); + set_card(nv->card); + if(nv_card.supported & MEM_OVERCLOCKING_SUPPORTED) + nv_card.set_memory_speed(nv->value); + unset_card(); + } +} -static void nvcore_change(void *obj, const struct cpufreq_policy *old, const struct cpufreq_policy *new); -static void nvmem_change(void *obj, const struct cpufreq_policy *old, const struct cpufreq_policy *new); +/* pre change events */ +static void nvcore_profile_pre_change(void __UNUSED__ *obj, + const struct cpufreq_policy __UNUSED__ *old, + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + nvcore_profile_calls++; +} -static struct cpufreqd_keyword kw[] = { - { .word = "nv_core", - .parse = &nvclock_parse, - .profile_pre_change = NULL, - .profile_post_change = &nvcore_change, - .rule_post_change = &nvcore_change - }, - { .word = "nv_mem", - .parse = &nvclock_parse, - .profile_pre_change = NULL, - .profile_post_change = &nvmem_change, - .rule_post_change = &nvmem_change - }, - { .word = NULL } -}; +static void nvmem_profile_pre_change(void __UNUSED__ *obj, + const struct cpufreq_policy __UNUSED__ *old, + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + nvmem_profile_calls++; +} -static struct cpufreqd_plugin nvclock_plugin = { - .plugin_name = "nvclock", - .keywords = kw, - .plugin_init = nvclock_init, - .plugin_exit = NULL, - .plugin_update = NULL, - .plugin_conf = NULL, - .plugin_post_conf= NULL, -}; +/* post change events */ +static void nvcore_rule_post_change(void *obj, + const struct rule __UNUSED__ *old, + const struct rule __UNUSED__ *new) { + nvcore_change(obj); +} +static void nvcore_profile_post_change(void *obj, + const struct cpufreq_policy __UNUSED__ *old, + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + nvcore_profile_calls--; + if (nvcore_profile_calls == 0) + nvcore_change(obj); +} + +static void nvmem_rule_post_change(void *obj, + const struct rule __UNUSED__ *old, + const struct rule __UNUSED__ *new) { + nvmem_change(obj); +} + +static void nvmem_profile_post_change(void *obj, + const struct cpufreq_policy __UNUSED__ *old, + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + nvmem_profile_calls--; + if (nvmem_profile_calls == 0) + nvmem_change(obj); +} static int nvclock_init(void) { return !init_nvclock(); @@ -100,34 +140,31 @@ return 0; } +static struct cpufreqd_keyword kw[] = { + { .word = "nv_core", + .parse = &nvclock_parse, + .profile_pre_change = &nvcore_profile_pre_change, + .profile_post_change = &nvcore_profile_post_change, + .rule_post_change = &nvcore_rule_post_change + }, + { .word = "nv_mem", + .parse = &nvclock_parse, + .profile_pre_change = &nvmem_profile_pre_change, + .profile_post_change = &nvmem_profile_post_change, + .rule_post_change = &nvmem_rule_post_change + }, + { .word = NULL } +}; -static void nvcore_change(void *obj, - const struct cpufreq_policy __UNUSED__ *old, - const struct cpufreq_policy __UNUSED__ *new) { - struct nvclock_elem *nv = obj; - - if (nv->card < nvclock.num_cards) { - clog(LOG_INFO, "Setting nv_core for card %i to (%u)\n", nv->card, nv->value); - set_card(nv->card); - if(nv_card.supported & GPU_OVERCLOCKING_SUPPORTED) - nv_card.set_gpu_speed(nv->value); - unset_card(); - } -} - -static void nvmem_change(void *obj, - const struct cpufreq_policy __UNUSED__ *old, - const struct cpufreq_policy __UNUSED__ *new) { - struct nvclock_elem *nv = obj; - - if (nv->card < nvclock.num_cards) { - clog(LOG_INFO, "Setting nv_mem for card %i to (%u)\n", nv->card, nv->value); - set_card(nv->card); - if(nv_card.supported & MEM_OVERCLOCKING_SUPPORTED) - nv_card.set_memory_speed(nv->value); - unset_card(); - } -} +static struct cpufreqd_plugin nvclock_plugin = { + .plugin_name = "nvclock", + .keywords = kw, + .plugin_init = nvclock_init, + .plugin_exit = NULL, + .plugin_update = NULL, + .plugin_conf = NULL, + .plugin_post_conf= NULL, +}; struct cpufreqd_plugin *create_plugin (void) { return &nvclock_plugin; Index: cpufreqd_exec.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_exec.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- cpufreqd_exec.c 12 Mar 2006 10:42:34 -0000 1.4 +++ cpufreqd_exec.c 2 Jul 2006 20:14:13 -0000 1.5 @@ -156,12 +156,38 @@ pthread_mutex_unlock(&exe_q_mtx); } -static void change (void *obj, +/* avoid being called for each cpu profile change, + * only act on the last one + */ +static int profile_change_calls; +static void exec_profile_pre_change(void __UNUSED__ *obj, const struct cpufreq_policy __UNUSED__ *old, - const struct cpufreq_policy __UNUSED__ *new) { + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + if (profile_change_calls == 0) + exec_enqueue((char *)obj); + profile_change_calls++; +} +static void exec_profile_post_change(void *obj, + const struct cpufreq_policy __UNUSED__ *old, + const struct cpufreq_policy __UNUSED__ *new, + const unsigned int __UNUSED__ cpu) { + profile_change_calls--; + if (profile_change_calls == 0) + exec_enqueue((char *)obj); +} + +static void exec_rule_change(void *obj, + const struct rule __UNUSED__ *old, + const struct rule __UNUSED__ *new) { exec_enqueue((char *)obj); } +static int exec_update(void) { + profile_change_calls = 0; + return 0; +} + /* Launch the thread that will wait on the queue * to have some command available. */ @@ -211,9 +237,9 @@ .parse = exec_parse, .evaluate = NULL, .profile_pre_change = NULL, - .profile_post_change = &change, + .profile_post_change = &exec_profile_post_change, .rule_pre_change = NULL, - .rule_post_change = &change, + .rule_post_change = &exec_rule_change, .free = NULL, }, { @@ -221,9 +247,9 @@ .word = "exec_pre", .parse = exec_parse, .evaluate = NULL, - .profile_pre_change = &change, + .profile_pre_change = &exec_profile_pre_change, .profile_post_change = NULL, - .rule_pre_change = &change, + .rule_pre_change = &exec_rule_change, .rule_post_change = NULL, .free = NULL, }, @@ -235,7 +261,7 @@ .keywords = kw, .plugin_init = exec_init, .plugin_exit = exec_exit, - .plugin_update = NULL, + .plugin_update = &exec_update, .plugin_conf = NULL, .plugin_post_conf = NULL, }; Index: config_parser.h =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/config_parser.h,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- config_parser.h 13 Mar 2006 22:05:16 -0000 1.17 +++ config_parser.h 2 Jul 2006 20:14:13 -0000 1.18 @@ -42,9 +42,10 @@ struct rule { char name[MAX_STRING_LEN]; - char profile_name[MAX_STRING_LEN]; + char profile_name[MAX_STRING_LEN]; /* this is a list actually, eg: "CPU0:prof0;CPU1:prof1" */ struct LIST directives; /* list of struct directive */ - struct profile *prof; + struct profile **prof; /* profiles per CPU */ + unsigned long assigned_cpus; /* bit map holding which cpus have been assigned a Profile for this rule */ unsigned int score; unsigned int directives_count; }; @@ -70,7 +71,7 @@ }; -int init_configuration (struct cpufreqd_conf *config, struct cpufreqd_info *info); +int init_configuration (struct cpufreqd_conf *config); void free_configuration (struct cpufreqd_conf *config); #endif /* _CONFIG_PARSER_H */ Index: cpufreqd_plugin.h =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_plugin.h,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- cpufreqd_plugin.h 23 Apr 2006 20:29:07 -0000 1.15 +++ cpufreqd_plugin.h 2 Jul 2006 20:14:13 -0000 1.16 @@ -18,7 +18,7 @@ */ #ifndef __CPUFREQD_PLUGIN_H__ -#define __CPUFREQD_PLUGIN_H__ +#define __CPUFREQD_PLUGIN_H__ 1 #include <cpufreq.h> #include <sys/types.h> @@ -26,6 +26,7 @@ #include <signal.h> #include <unistd.h> #include "cpufreqd.h" +#include "config_parser.h" #include "cpufreqd_log.h" #define FALSE 0 @@ -42,7 +43,6 @@ * Shared struct containing useful global informations * probed from the core cpufreqd at noostrap time. */ - struct cpufreq_limits { unsigned long min; unsigned long max; @@ -67,6 +67,8 @@ struct cpufreqd_plugin; +struct rule; + /* * A cpufreqd keyword consists of the proper word to match at the * beginning of the Rule line. The struct consists of two other function @@ -113,7 +115,7 @@ * Can be NULL. */ void (*profile_pre_change) (void *obj, const struct cpufreq_policy *old, - const struct cpufreq_policy *new); + const struct cpufreq_policy *new, const unsigned int cpu); /* function pointer to the profile_post_change event. The same as * profile_pre_change applies except for the fact that everything is @@ -122,7 +124,7 @@ * Can be NULL. */ void (*profile_post_change) (void *obj, const struct cpufreq_policy *old, - const struct cpufreq_policy *new); + const struct cpufreq_policy *new, const unsigned int cpu); /* function pointer to the rule_pre_change event. obj is the structure * previously provided by the parse function, old and new are the old @@ -135,8 +137,8 @@ * * Can be NULL. */ - void (*rule_pre_change) (void *obj, const struct cpufreq_policy *old, - const struct cpufreq_policy *new); + void (*rule_pre_change) (void *obj, const struct rule *old, + const struct rule *new); /* function pointer to the rule_post_change event. The same as * rule_pre_change applies except for the fact that everything is @@ -144,8 +146,8 @@ * * Can be NULL. */ - void (*rule_post_change) (void *obj, const struct cpufreq_policy *old, - const struct cpufreq_policy *new); + void (*rule_post_change) (void *obj, const struct rule *old, + const struct rule *new); /* Allows the owner to define a specific function to be called when freeing Index: cpufreqd_governor_parameters.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_governor_parameters.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- cpufreqd_governor_parameters.c 23 Apr 2006 18:46:47 -0000 1.3 +++ cpufreqd_governor_parameters.c 2 Jul 2006 20:14:13 -0000 1.4 @@ -92,86 +92,84 @@ /* Sets the value of 'parameter' of 'governor' to 'value'. */ -static void set_parameter(const char *governor, const char *parameter, long int value, int is_percentage) +static void set_parameter(const unsigned int cpu, const char *governor, + const char *parameter, long int value, int is_percentage) { - unsigned int cpu; char value_str[BUFLEN_PARAMETER_VALUE]; struct sysfs_device *govdev = NULL; struct sysfs_attribute *govattr = NULL; /* For each CPU */ - for (cpu = 0; cpu < number_of_cpus; ++cpu) { - govdev = open_governor_device(cpu, governor); - if (govdev == NULL) { - return; - } - if (is_percentage) { - long int min, max; - long long int abs_value; - char min_name[SYSFS_NAME_LEN]; - char max_name[SYSFS_NAME_LEN]; - - /* Read minimum allowed value */ - snprintf(min_name, SYSFS_NAME_LEN, "%s_min", parameter); - min = get_parameter(govdev, min_name); - if (min < 0) { - sysfs_close_device(govdev); - clog(LOG_WARNING, "warning: minimum value for %s could not be read: ignored.\n", parameter); - return; - } - clog(LOG_DEBUG, "minimum value for %s: %ld\n", parameter, min); - - /* Read maximum allowed value */ - snprintf(max_name, SYSFS_NAME_LEN, "%s_max", parameter); - max = get_parameter(govdev, max_name); - if (max < 0) { - sysfs_close_device(govdev); - clog(LOG_WARNING, "warning: maximum value for %s could not be read: ignored.\n", parameter); - return; - } - clog(LOG_DEBUG, "maximum value for %s: %ld\n", parameter, max); + govdev = open_governor_device(cpu, governor); + if (govdev == NULL) { + return; + } + if (is_percentage) { + long int min, max; + long long int abs_value; + char min_name[SYSFS_NAME_LEN]; + char max_name[SYSFS_NAME_LEN]; - /* Convert percentage to absolute value in a string */ - abs_value = (long long int)value * (max - min) / 100 + min; - snprintf(value_str, BUFLEN_PARAMETER_VALUE, "%lu", (long int)abs_value); - clog(LOG_DEBUG, "converted percentage %ld to absolute value: %s\n", value, value_str); - } else { - /* Convert value to string */ - snprintf(value_str, BUFLEN_PARAMETER_VALUE, "%lu", value); + /* Read minimum allowed value */ + snprintf(min_name, SYSFS_NAME_LEN, "%s_min", parameter); + min = get_parameter(govdev, min_name); + if (min < 0) { + sysfs_close_device(govdev); + clog(LOG_WARNING, "warning: minimum value for %s could not be read: ignored.\n", parameter); + return; } + clog(LOG_DEBUG, "minimum value for %s: %ld\n", parameter, min); - /* Get sysfs attribute for the parameter */ - govattr = sysfs_get_device_attr(govdev, parameter); - - /* Kernel compatibility issue: - * The parameter name "ignore_nice" changed to "ignore_nice_load" in kernel >= 2.6.16. - * We are accepting both names silently, regardless the kernel version by trying to get - * a sysfs device for the other name when the specified name doesn't exist in sysfs. - */ - if (govattr == NULL) { - if (strcmp(parameter, "ignore_nice") == 0) { - govattr = sysfs_get_device_attr(govdev, "ignore_nice_load"); - } else if (strcmp(parameter, "ignore_nice_load") == 0) { - govattr = sysfs_get_device_attr(govdev, "ignore_nice"); - } - } - if (govattr == NULL) { + /* Read maximum allowed value */ + snprintf(max_name, SYSFS_NAME_LEN, "%s_max", parameter); + max = get_parameter(govdev, max_name); + if (max < 0) { sysfs_close_device(govdev); - clog(LOG_WARNING, "warning: attribute %s not found in sysfs.\n", parameter); + clog(LOG_WARNING, "warning: maximum value for %s could not be read: ignored.\n", parameter); return; } + clog(LOG_DEBUG, "maximum value for %s: %ld\n", parameter, max); - /* Write new value to sysfs' parameter attribute */ - if (sysfs_write_attribute(govattr, value_str, strlen(value_str)) < 0) { - clog(LOG_ERR, "ERROR: could not set parameter %s to %s for %s governor on cpu%u: %s\n", - parameter, value_str, governor, cpu, strerror(errno)); - } - clog(LOG_DEBUG, "parameter %s set to %s for %s governor on cpu%u\n", - parameter, value_str, governor, cpu); + /* Convert percentage to absolute value in a string */ + abs_value = (long long int)value * (max - min) / 100 + min; + snprintf(value_str, BUFLEN_PARAMETER_VALUE, "%lu", (long int)abs_value); + clog(LOG_DEBUG, "converted percentage %ld to absolute value: %s\n", value, value_str); + } else { + /* Convert value to string */ + snprintf(value_str, BUFLEN_PARAMETER_VALUE, "%lu", value); + } - /* Close governor device. This will free all structures allocated by libsysfs */ + /* Get sysfs attribute for the parameter */ + govattr = sysfs_get_device_attr(govdev, parameter); + + /* Kernel compatibility issue: + * The parameter name "ignore_nice" changed to "ignore_nice_load" in kernel >= 2.6.16. + * We are accepting both names silently, regardless the kernel version by trying to get + * a sysfs device for the other name when the specified name doesn't exist in sysfs. + */ + if (govattr == NULL) { + if (strcmp(parameter, "ignore_nice") == 0) { + govattr = sysfs_get_device_attr(govdev, "ignore_nice_load"); + } else if (strcmp(parameter, "ignore_nice_load") == 0) { + govattr = sysfs_get_device_attr(govdev, "ignore_nice"); + } + } + if (govattr == NULL) { sysfs_close_device(govdev); + clog(LOG_WARNING, "warning: attribute %s not found in sysfs.\n", parameter); + return; + } + + /* Write new value to sysfs' parameter attribute */ + if (sysfs_write_attribute(govattr, value_str, strlen(value_str)) < 0) { + clog(LOG_ERR, "ERROR: could not set parameter %s to %s for %s governor on cpu%u: %s\n", + parameter, value_str, governor, cpu, strerror(errno)); } + clog(LOG_DEBUG, "parameter %s set to %s for %s governor on cpu%u\n", + parameter, value_str, governor, cpu); + + /* Close governor device. This will free all structures allocated by libsysfs */ + sysfs_close_device(govdev); } @@ -339,7 +337,7 @@ * Called when cpufreqd just changed the profile. */ static void gov_parameter_post_change(void *obj, const struct cpufreq_policy *not_needed, - const struct cpufreq_policy *new_policy) + const struct cpufreq_policy *new_policy, const unsigned int cpu) { int i; const char *parameter; @@ -360,7 +358,7 @@ if (strcmp(supported_governors[i], new_policy->governor) == 0) { clog(LOG_INFO, "setting governor parameter %s = %ld%c\n", parameter, value, is_percentage ? '%' : ' '); - set_parameter(new_policy->governor, parameter, value, is_percentage); + set_parameter(cpu, new_policy->governor, parameter, value, is_percentage); return; } ++i; Index: cpufreqd_nforce2.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_nforce2.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- cpufreqd_nforce2.c 12 Mar 2006 10:42:34 -0000 1.10 +++ cpufreqd_nforce2.c 2 Jul 2006 20:14:13 -0000 1.11 @@ -127,32 +127,51 @@ static unsigned int cur_freq = 0; +/* avoid being called for _every_ cpu switching freq, + * just run our stuff on the first one on -pre events, + * on the last one on -post events + */ +int vcore_profile_calls; + static void vcore_pre_change(void *obj, const struct cpufreq_policy __UNUSED__ *old, - const struct cpufreq_policy *new) { - - cur_freq = cpufreq_get(0); - - if (cur_freq <= new->max) { - int vcore = *(int *)obj; + const struct cpufreq_policy *new, + const unsigned int __UNUSED__ cpu) { + + if (vcore_profile_calls == 0) { + cur_freq = cpufreq_get(0); - clog(LOG_INFO, "Setting Vcore to (%d)\n", vcore); - set_vcore(vcore); + if (cur_freq <= new->max) { + int vcore = *(int *)obj; + + clog(LOG_INFO, "Setting Vcore to (%d)\n", vcore); + set_vcore(vcore); + } } + vcore_profile_calls++; } static void vcore_post_change(void *obj, const struct cpufreq_policy __UNUSED__ *old, - const struct cpufreq_policy *new) { - - if (cur_freq > new->max) { - int vcore = *(int *)obj; - - clog(LOG_INFO, "Setting Vcore to (%d)\n", vcore); - set_vcore(vcore); + const struct cpufreq_policy *new, + const unsigned int __UNUSED__ cpu) { + + vcore_profile_calls--; + if (vcore_profile_calls == 0) { + if (cur_freq > new->max) { + int vcore = *(int *)obj; + + clog(LOG_INFO, "Setting Vcore to (%d)\n", vcore); + set_vcore(vcore); + } } } +static int nforce2_update(void) { + vcore_profile_calls = 0; + return 0; +} + static struct cpufreqd_keyword kw[] = { { .word = "vcore", .parse = &vcore_parse, @@ -166,10 +185,10 @@ .plugin_name = "nforce2_atxp1", .keywords = kw, .plugin_init = NULL, - .plugin_exit = nforce2_exit, - .plugin_update = NULL, - .plugin_conf = nforce2_conf, - .plugin_post_conf= nforce2_post_conf, + .plugin_exit = &nforce2_exit, + .plugin_update = &nforce2_update, + .plugin_conf = &nforce2_conf, + .plugin_post_conf= &nforce2_post_conf, }; struct cpufreqd_plugin *create_plugin (void) { Index: config_parser.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/config_parser.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- config_parser.c 11 Jun 2006 20:09:59 -0000 1.37 +++ config_parser.c 2 Jul 2006 20:14:13 -0000 1.38 @@ -498,6 +498,11 @@ continue; if (strcmp(name, "profile") == 0) { + /* allow associations for a single cpu + * profile=CPU0:prof1;CPU1:prof2 + * keep it as-is, will parse the thing later + * when associating Rules to Profiles. + */ strncpy(r->profile_name, value, MAX_STRING_LEN); r->profile_name[MAX_STRING_LEN - 1] = '\0'; state |= HAS_PROFILE; @@ -607,7 +612,7 @@ /* intialize the cpufreqd_conf object * by reading the configuration file */ -int init_configuration(struct cpufreqd_conf *configuration, struct cpufreqd_info *info) +int init_configuration(struct cpufreqd_conf *configuration) { FILE *fp_config = NULL; struct NODE *n = NULL; @@ -616,7 +621,9 @@ struct plugin_obj *plugin = NULL; char *clean = NULL; char buf[256]; + unsigned int i = 0; int plugins_post_confed = 0; /* did I already run post_conf for all? */ + struct cpufreqd_info *cinfo = get_cpufreqd_info(); /* configuration file */ clog(LOG_INFO, "reading configuration file %s\n", configuration->config_file); @@ -689,7 +696,7 @@ } if (parse_config_profile(fp_config, tmp_profile, &configuration->plugins, - info->limits, info->sys_info->frequencies) < 0) { + cinfo->limits, cinfo->sys_info->frequencies) < 0) { clog(LOG_CRIT, "[Profile] error parsing %s, see logs for details.\n", configuration->config_file); node_free(n); @@ -786,32 +793,104 @@ */ LIST_FOREACH_NODE(node, &configuration->rules) { tmp_rule = (struct rule *)node->content; + char tmp_name[MAX_STRING_LEN]; + char profile_name[MAX_STRING_LEN]; + char *token; + unsigned int cpu_num = 0; int profile_found = 0; - LIST_FOREACH_NODE(node1, &configuration->profiles) { - tmp_profile = (struct profile *)node1->content; - /* go through profiles */ - if (strcmp(tmp_rule->profile_name, tmp_profile->name)==0) { - /* a profile is allowed to be addressed by more than 1 rule */ - tmp_rule->prof = tmp_profile; - profile_found = 1; - break; - } - } + strncpy(tmp_name, tmp_rule->profile_name, MAX_STRING_LEN); + tmp_name[MAX_STRING_LEN - 1] = '\0'; - if (!profile_found) { - clog(LOG_CRIT, "ERROR! no Profile section found for Rule \"%s\" " - "(requested Profile \"%s\")\n", - tmp_rule->name, tmp_rule->profile_name); + /* this allocation can result being very piggy in large SMP systems */ + tmp_rule->prof = calloc(cinfo->cpus, sizeof(struct profile *)); + if (tmp_rule->prof == NULL) { + clog(LOG_CRIT, "ERROR! couldn't make room for the Rule/Profile " + " association, exiting.\n"); return -1; } + + /* split profile names and associate */ + token = strtok(tmp_name, ";"); + do { + if (strstr(token, "CPU") != token) { + + if (strstr(token, "ALL:") == token) { + strncpy(profile_name, token+4, MAX_STRING_LEN); + } + else { + strncpy(profile_name, token, MAX_STRING_LEN); + } + profile_name[MAX_STRING_LEN - 1] = '\0'; + /* set this profile for all unassigned cpus */ + LIST_FOREACH_NODE(node1, &configuration->profiles) { + tmp_profile = (struct profile *)node1->content; + if (strcmp(profile_name, tmp_profile->name) == 0) { + for (i = 0; i < cinfo->cpus; i++) + tmp_rule->prof[i] = tmp_profile; + profile_found = 1; + break; + } + tmp_profile = NULL; + } + if (tmp_profile == NULL) { + clog(LOG_ERR, "No Profile with name \"%s\" found for Rule \"%s\".\n", + profile_name, tmp_rule->name); + return -1; + } + + } + else { + /* assign profile for a single CPU */ + + if (sscanf(token, "CPU%d:%[a-zA-Z0-9 ]", &cpu_num, profile_name) != 2) { + clog(LOG_ERR, "Wrong format for Profile name \"%s\".\n", + token); + return -1; + } + if (cpu_num >= cinfo->cpus) { + clog(LOG_ERR, "Unknown cpu CPU%d for Rule \"%s\".\n", + cpu_num, tmp_rule->name); + return -1; + } + + LIST_FOREACH_NODE(node1, &configuration->profiles) { + tmp_profile = (struct profile *)node1->content; + + /* go through profiles */ + if (strcmp(profile_name, tmp_profile->name) == 0) { + /* bail out if the rule has a profile already for that CPU */ + if (tmp_rule->assigned_cpus & cpu_num) { + clog(LOG_ERR, "Rule \"%s\" has a Profile for " + "CPU%d already, exiting\n", + tmp_rule->name, cpu_num); + return -1; + } + tmp_rule->prof[cpu_num] = tmp_profile; + tmp_rule->assigned_cpus |= 1 << cpu_num; + break; + } + tmp_profile = NULL; + + } /* end foreach profile */ + if (tmp_profile == NULL) { + clog(LOG_ERR, "No Profile with name \"%s\" found for Rule \"%s\" " + "for CPU%d.\n", profile_name, tmp_rule->name, cpu_num); + return -1; + } + } + } while ((token = strtok(NULL,";")) != NULL); + } LIST_FOREACH_NODE(node, &configuration->rules) { tmp_rule = (struct rule *)node->content; - clog(LOG_INFO, "Rule \"%s\" has Profile \"%s\"\n", - tmp_rule->name, tmp_rule->prof->name); + clog(LOG_INFO, "Rule \"%s\" has Profiles ", tmp_rule->name); + for (i = 0; i < cinfo->cpus; i++) + cpufreqd_log(LOG_INFO, "CPU%d:%s ", i, tmp_rule->prof[i]->name); + cpufreqd_log(LOG_INFO, "\n"); } + /* TODO: spit a WARNING if no rule with a global cpu profile is found */ return 0; } @@ -825,7 +904,7 @@ struct directive *tmp_directive; struct plugin_obj *o_plugin; - /* cleanup rule directives */ + /* cleanup rule directives and profile arrays */ clog(LOG_INFO, "freeing rules directives.\n"); LIST_FOREACH_NODE(node, &configuration->rules) { tmp_rule = (struct rule *) node->content; @@ -835,9 +914,10 @@ free_keyword_object(tmp_directive->keyword, tmp_directive->obj); } list_free_sublist(&tmp_rule->directives, tmp_rule->directives.first); + if (tmp_rule->prof) + free(tmp_rule->prof); } - - /* cleanup config structs */ + /* cleanup rule structs */ clog(LOG_INFO, "freeing rules.\n"); list_free_sublist(&(configuration->rules), configuration->rules.first); configuration->rules.first = configuration->rules.last = NULL; Index: main.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/main.c,v retrieving revision 1.53 retrieving revision 1.54 diff -u -d -r1.53 -r1.54 --- main.c 21 May 2006 11:53:39 -0000 1.53 +++ main.c 2 Jul 2006 20:14:13 -0000 1.54 @@ -44,7 +44,7 @@ #include "plugin_utils.h" #include "sock_utils.h" -#define TRIGGER_EVENT(event_func, directives, dir, old, new) \ +#define TRIGGER_RULE_EVENT(event_func, directives, dir, old, new) \ do { \ LIST_FOREACH_NODE(__node, (directives)) { \ dir = (struct directive *)__node->content; \ @@ -55,9 +55,20 @@ } \ } while (0); +#define TRIGGER_PROFILE_EVENT(event_func, directives, dir, old, new, cpu_num) \ +do { \ + LIST_FOREACH_NODE(__node, (directives)) { \ + dir = (struct directive *)__node->content; \ + if (dir->keyword->event_func != NULL) { \ + clog(LOG_DEBUG, "Triggering " #event_func " for %s\n", dir->keyword->word); \ + dir->keyword->event_func(dir->obj, (old), (new), (cpu_num)); \ + } \ + } \ +} while (0); + static struct cpufreqd_info *cpufreqd_info; static struct rule *current_rule; -static struct profile *current_profile; +static struct profile **current_profiles; static int force_reinit = 0; static int force_exit = 0; static int timer_expired = 1; /* expired in order to run on the first loop */ @@ -173,55 +184,73 @@ * Returns always 0 (success) except if double checking is enabled and setting * the policy fails in which case -1 is returned. */ -static int cpufreqd_set_profile (struct profile *old, struct profile *new) { +static int cpufreqd_set_profile (struct profile **old, struct profile **new) { unsigned int i; struct directive *d; + struct profile *old_profile = NULL, *new_profile = NULL; - /* profile prechange event */ - if (new->directives.first) { - TRIGGER_EVENT(profile_pre_change, &new->directives, d, - old!=NULL? &old->policy : NULL, &new->policy); - } - /* int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) */ for (i = 0; i < cpufreqd_info->cpus; i++) { - if (cpufreq_set_policy(i, &(new->policy)) == 0) { - clog(LOG_NOTICE, "Profile \"%s\" set for cpu%d\n", new->name, i); + new_profile = new[i]; + if (old != NULL) + old_profile = old[i]; + + /* profile prechange event */ + if (new_profile->directives.first) { + TRIGGER_PROFILE_EVENT(profile_pre_change, &new_profile->directives, d, + old_profile != NULL ? &old_profile->policy : NULL, + &new_profile->policy, i); + } + + /* don't even try to set the profile if it hasn't changed */ + if (new_profile == old_profile) { + clog(LOG_DEBUG, "Profile unchanged (\"%s\"-\"%s\"), for CPU%d doing nothing.\n", + old_profile->name, new_profile->name, i); + } + /* int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) */ + else if (cpufreq_set_policy(i, &(new_profile->policy)) == 0) { + clog(LOG_NOTICE, "Profile \"%s\" set for CPU%d\n", new_profile->name, i); + /* double check if everything is OK (configurable) */ if (configuration->double_check) { struct cpufreq_policy *check = NULL; check = cpufreq_get_policy(i); - if (check->max != new->policy.max || check->min != new->policy.min || - strcmp(check->governor, new->policy.governor) != 0) { + if (check->max != new_profile->policy.max + || check->min != new_profile->policy.min + || strcmp(check->governor, new_profile->policy.governor) != 0) { /* written policy and subsequent read disagree */ clog(LOG_ERR, "I haven't been able to set the chosen policy " "for CPU%d.\n" "I set %d-%d-%s\n" "System says %d-%d-%s\n", - i, new->policy.max, new->policy.min, - new->policy.governor, check->max, + i, new_profile->policy.max, new_profile->policy.min, + new_profile->policy.governor, check->max, check->min, check->governor); cpufreq_put_policy(check); return -1; } else { clog(LOG_INFO, "Policy correctly set %d-%d-%s\n", - new->policy.max, new->policy.min, new->policy.governor); + new_profile->policy.max, + new_profile->policy.min, + new_profile->policy.governor); } cpufreq_put_policy(check); - - } + } /* end if double_check */ } else { - clog(LOG_WARNING, "Couldn't set profile \"%s\" set for cpu%d\n", new->name, i); + clog(LOG_WARNING, "Couldn't set profile \"%s\" set for cpu%d\n", + new_profile->name, i); return -1; } + + /* profile postchange event */ + if (new_profile->directives.first) { + TRIGGER_PROFILE_EVENT(profile_post_change, &new_profile->directives, d, + old != NULL ? &old_profile->policy : NULL, + &new_profile->policy, i); + } } - /* profile postchange event */ - if (new->directives.first) { - TRIGGER_EVENT(profile_post_change, &new->directives, d, - old!=NULL? &old->policy : NULL, &new->policy); - } - current_profile = new; - cpufreqd_info->cur_policy = &new->policy; + current_profiles = new; + cpufreqd_info->cur_policy = &new_profile->policy; return 0; } @@ -363,7 +392,7 @@ static struct rule *cpufreqd_loop(struct cpufreqd_conf *conf, struct rule *current) { struct rule *best_rule = NULL; - struct directive *d; + struct directive *d = NULL; /* update timestamp */ if (gettimeofday(&cpufreqd_info->timestamp, NULL) < 0) { @@ -398,9 +427,8 @@ best_rule->name); /* pre change event */ if (best_rule->directives.first != NULL) { - TRIGGER_EVENT(rule_pre_change, &best_rule->directives, d, - current != NULL ? ¤t->prof->policy : NULL, - &best_rule->prof->policy); + TRIGGER_RULE_EVENT(rule_pre_change, &best_rule->directives, d, + current, best_rule); } /* change frequency */ @@ -408,16 +436,12 @@ cpufreqd_set_profile(NULL, best_rule->prof); } else if (best_rule->prof != current->prof) { cpufreqd_set_profile(current->prof, best_rule->prof); - } else { - clog(LOG_DEBUG, "Profile unchanged (\"%s\"-\"%s\"), doing nothing.\n", - current->prof->name, best_rule->prof->name); } /* post change event */ if (best_rule->directives.first != NULL) { - TRIGGER_EVENT(rule_post_change, &best_rule->directives, d, - current != NULL ? ¤t->prof->policy : NULL, - &best_rule->prof->policy); + TRIGGER_RULE_EVENT(rule_post_change, &best_rule->directives, d, + current, best_rule); } } else { @@ -434,9 +458,11 @@ static void execute_command(int sock, struct cpufreqd_conf *conf) { struct pollfd fds; char buf[MAX_STRING_LEN]; - unsigned int buflen = 0, counter = 0; - struct profile *p; + unsigned int buflen = 0, counter = 0, i = 0; + struct profile *p = NULL, **pp = NULL; uint32_t command = INVALID_CMD; + struct cpufreqd_info *cinfo = get_cpufreqd_info(); + /* we have a valid sock, wait for command * don't wait more tha 0.5 sec */ @@ -465,14 +491,49 @@ clog(LOG_DEBUG, "CMD_LIST_PROFILES\n"); LIST_FOREACH_NODE(node, &conf->profiles) { p = (struct profile *) node->content; + /* FIXME: the current profile is not checked + * as it may well be different from each cpu. + * See command CMD_CUR_PROFILES. + */ + /* format is: + * 1 always 0, currently unused + * 2 profile name + * 3 min freq + * 4 max freq + * 5 active governor + */ buflen = snprintf(buf, MAX_STRING_LEN, "%d/%s/%lu/%lu/%s\n", - p == current_profile ? 1 : 0, + 0, p->name, p->policy.min, p->policy.max, p->policy.governor); write(sock, buf, buflen); } break; + case CMD_CUR_PROFILES: + clog(LOG_DEBUG, "CMD_CUR_PROFILES\n"); + if (!current_profiles) + break; + + for (i = 0; i < cinfo->cpus; i++) { + if (!current_profiles[i]) + continue; + /* format is: + * 1 cpu where the profile is active + * 2 profile name + * 3 min freq + * 4 max freq + * 5 active governor + */ + buflen = snprintf(buf, MAX_STRING_LEN, "%d/%s/%lu/%lu/%s\n", + i, + current_profiles[i]->name, + current_profiles[i]->policy.min, + current_profiles[i]->policy.max, + current_profiles[i]->policy.governor); + write(sock, buf, buflen); + } + break; case CMD_SET_RULE: clog(LOG_DEBUG, "CMD_SET_RULE\n"); clog(LOG_ALERT, "Ignoring unimplemented command %0.8x\n", command); @@ -480,16 +541,6 @@ case CMD_SET_MODE: clog(LOG_DEBUG, "CMD_SET_MODE\n"); set_cpufreqd_runmode((int)REMOTE_ARG(command)); -#if 0 - cpufreqd_mode = REMOTE_ARG(command); - if (cpufreqd_mode == MODE_MANUAL) { - /* reset alarm */ - if (setitimer(ITIMER_REAL, NULL, 0) < 0) - clog(LOG_CRIT, "Couldn't set timer: %s\n", strerror(errno)); - } else { - timer_expired = 1; - } -#endif break; case CMD_SET_PROFILE: clog(LOG_DEBUG, "CMD_SET_PROFILE\n"); @@ -507,10 +558,26 @@ p = (struct profile *) node->content; counter++; if (counter == REMOTE_ARG(command)) { - cpufreqd_set_profile(NULL, p); + + /* set this profile for every cpu */ + pp = calloc(cinfo->cpus, sizeof(struct profile *)); + if (pp == NULL) { + clog(LOG_ERR, "Couldn't allocate enough memory " + " to set profile \"%s\"\n", + p->name); + /* return immediately */ + return; + } + + for(i = 0; i < cinfo->cpus; i++) + pp[i] = p; + + cpufreqd_set_profile(NULL, pp); + free(pp); + /* reset the current rule to let * the cpufreqd_loop set the correct - * on if going back to dynamic mode + * one when going back to dynamic mode */ current_rule = NULL; counter = 0; @@ -676,7 +743,7 @@ cpufreqd_start: - if (init_configuration(configuration, cpufreqd_info) < 0) { + if (init_configuration(configuration) < 0) { clog(LOG_CRIT, "Unable to parse config file: %s\n", configuration->config_file); ret = EINVAL; goto out_config_read; @@ -742,21 +809,7 @@ * if running in DYNAMIC mode AND the timer is expired */ if (cpufreqd_mode == MODE_DYNAMIC && timer_expired) { -#if 0 - new_timer.it_interval.tv_usec = configuration->poll_intv.tv_usec; - new_timer.it_interval.tv_sec = configuration->poll_intv.tv_sec; - new_timer.it_value.tv_usec = configuration->poll_intv.tv_usec; - new_timer.it_value.tv_sec = configuration->poll_intv.tv_sec; -#endif current_rule = cpufreqd_loop(configuration, current_rule); -#if 0 - /* set next alarm */ - if (setitimer(ITIMER_REAL, &new_timer, 0) < 0) { - ret = errno; - clog(LOG_CRIT, "Couldn't set timer: %s\n", strerror(errno)); - break; - } -#endif /* can safely reset the expired flag now */ timer_expired = 0; } Index: cpufreqd_remote.h =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_remote.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- cpufreqd_remote.h 16 Apr 2006 13:26:14 -0000 1.4 +++ cpufreqd_remote.h 2 Jul 2006 20:14:13 -0000 1.5 @@ -38,6 +38,7 @@ #define CMD_SET_RULE 4 /* <rule index> */ #define CMD_LIST_RULES 5 /* no arguments */ #define CMD_SET_MODE 6 /* <mode> */ +#define CMD_CUR_PROFILES 7 /* no argument */ #define ARG_MASK 0x0000ffff #define MODE_DYNAMIC (1) |
From: Mattia D. <mat...@us...> - 2006-07-02 20:14:19
|
Update of /cvsroot/cpufreqd/sources2/manpages In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv19410/manpages Modified Files: cpufreqd-get.1 cpufreqd.conf.5 Log Message: introduce the definitive SMP awarness for cpufreqd Index: cpufreqd.conf.5 =================================================================== RCS file: /cvsroot/cpufreqd/sources2/manpages/cpufreqd.conf.5,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- cpufreqd.conf.5 1 Jul 2006 18:49:00 -0000 1.21 +++ cpufreqd.conf.5 2 Jul 2006 20:14:13 -0000 1.22 @@ -145,7 +145,12 @@ .TP .B "profile" -A character string that must match a [Profile] section name property. [REQUIRED] +A character string that must match a [Profile] section name property. +A Rule can also associate profiles to single cpus providing a list of the format +CPU%d:%s separated by semicolons (";"), e.g.: profile=CPU0:profile0;CPU1:profile1. +The keyword "ALL" can be used to indicate that all cpus must have the profile applied. +The "ALL" keyword has a lower priority so you can mix up CPU%d and ALL meaning that +if no specific profile is supplied, the "ALL" one will be used. [REQUIRED] .TP .B "other plugin entries" Index: cpufreqd-get.1 =================================================================== RCS file: /cvsroot/cpufreqd/sources2/manpages/cpufreqd-get.1,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- cpufreqd-get.1 11 Sep 2005 18:56:11 -0000 1.2 +++ cpufreqd-get.1 2 Jul 2006 20:14:13 -0000 1.3 @@ -14,14 +14,18 @@ cpufreqd\-get \- Issues "get" commands to cpufreqd. .SH "SYNTAX" .LP -cpufreqd\-get +.B "cpufreqd\-get [-l]" + +.SH "PARAMETERS" +.TP +.B "-l" +list applied Profiles for all cpus. .SH "DESCRIPTION" .LP cpufreqd\-get issues a command to cpufreqd and reads the returned output. -At the moment the only supported command is the "LIST_PROFILES", useful -for usage with cpufreqd\-set. -Currently no arguments are allowed to this command. +When run without arguments it will issue a "LIST_PROFILES" command, useful +for usage with cpufreqd\-set. See the PARAMETERS above for more. .SH "COMMANDS" .LP |
From: Mattia D. <mat...@us...> - 2006-07-02 20:14:18
|
Update of /cvsroot/cpufreqd/sources2/utils In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv19410/utils Modified Files: getspeed.c Log Message: introduce the definitive SMP awarness for cpufreqd Index: getspeed.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/utils/getspeed.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- getspeed.c 3 Sep 2005 20:40:18 -0000 1.7 +++ getspeed.c 2 Jul 2006 20:14:13 -0000 1.8 @@ -24,12 +24,19 @@ struct stat st; time_t last_mtime = 0; unsigned int cmd = 0; + unsigned int full_cmd = 0; char buf[4096] = {0}, name[256] = {0}, policy[255] = {0}; char *in; int min, max, active, n; - if (argc > 1) { - fprintf(stdout, "%s: No arguments allowed\n", argv[0]); + if (argc == 2 && !strcmp(argv[1], "-l")) + cmd = CMD_CUR_PROFILES; + else if (argc == 1) + cmd = CMD_LIST_PROFILES; + else { + fprintf(stdout, "%s: Wrong arguments\n", argv[0]); + fprintf(stdout, "%s [-l]\n", argv[0]); + fprintf(stdout, " -l list applied profiles\n"); return 1; } @@ -66,7 +73,7 @@ return ENOENT; } fprintf(stdout, "socket I'll try to connect: %s\n", sck.sun_path); - + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket()"); return 1; @@ -76,22 +83,30 @@ perror("connect()"); return 1; } - - cmd = MAKE_COMMAND(CMD_LIST_PROFILES, 0); - if (write(sock, &cmd, 4) != 4) + full_cmd = MAKE_COMMAND(cmd, 0); + if (write(sock, &full_cmd, 4) != 4) perror("write()"); n = 0; while (read(sock, buf, 4096)) { in = buf; - while (sscanf(in, "%d/%[^/]/%d/%d/%[^\n]\n", &active, name, &min, &max, policy) == 5) { - printf("\nName (#%d):\t%s %s\n", ++n, name, active ? "*" : ""); + while (cmd == CMD_LIST_PROFILES + && sscanf(in, "%d/%[^/]/%d/%d/%[^\n]\n", &active, name, &min, &max, policy) == 5) { + /* ignoring "active" as it's not used anymore */ + printf("\nName (#%d):\t%s\n", ++n, name); printf("Governor:\t%s\n", policy); printf("Min freq:\t%d\n", min); printf("Max freq:\t%d\n", max); in = strchr(in, '\n') + 1; } + + while (cmd == CMD_CUR_PROFILES + && sscanf(in, "%d/%[^/]/%d/%d/%[^\n]\n", &active, name, &min, &max, policy) == 5) { + printf("\nCPU#%d: \"%s\" ", active, name); + printf("%s %d-%d\n", policy, min, max); + in = strchr(in, '\n') + 1; + } } close(sock); |
From: Mattia D. <mal...@li...> - 2006-07-02 19:53:27
|
On Sun, Jul 02, 2006 at 12:39:19PM +0200, Christian Krafft wrote: > On Sat, 2006-07-01 at 23:08 +0200, Mattia Dongili wrote: > > > what about modifing the Rule->Profile association directive to allow > > (and understand) things like: > > [Rule] > > ... > > profile=CPU0:profile1;CPU1:profile2;... > > # if CPUn is not covered just don't apply anything > > [/Rule] > > > > This way one could better reuse already written profiles. Yes, I like > > the idea :) > > sounds good to me, too. I'm implementing it right now, let's see if I can get to a decent point by today. Out of curiosity: do you have an SMP system where you could test the result? :) [...] > > I'm already experimenting with it (inotify) but last time I checked > > /proc doesn't trigger inotify events > > I would like to have a look into that from kernel side. The problem is, > that the userspace doesn't know, if the kernel side triggers such > events. It would also make sense for only a few parameters. we are mostly reading from /proc and writing to /sys (well, maybe the lm_sensors stuff reads from there too). thanks -- mattia :wq! |
From: Christian K. <par...@bo...> - 2006-07-02 10:40:02
|
On Sat, 2006-07-01 at 23:08 +0200, Mattia Dongili wrote: > what about modifing the Rule->Profile association directive to allow > (and understand) things like: > [Rule] > ... > profile=CPU0:profile1;CPU1:profile2;... > # if CPUn is not covered just don't apply anything > [/Rule] > > This way one could better reuse already written profiles. Yes, I like > the idea :) sounds good to me, too. > > > You could fork a process for each physical cpu, using the general > > section plus the cpu based, if specified. With affinity, there would be > > less overhead on kernel side when the cpufreqd process reads from sysfs > > files, because the kernel thread that is writing to the file is already > > running on the cpu, that contains the pm registers. > > Hmmm... don't know how much we would win, we'd need to cohordinate more > processes for just a cache hit every now and then. It'd also need some > major rewrite for that. Maybe youre right, the communication between has to occur anyway. So this would be more or less a micro-optimization. > I'm already experimenting with it (inotify) but last time I checked > /proc doesn't trigger inotify events I would like to have a look into that from kernel side. The problem is, that the userspace doesn't know, if the kernel side triggers such events. It would also make sense for only a few parameters. ciao, ck |
From: Mattia D. <mal...@li...> - 2006-07-01 21:09:07
|
On Thu, Jun 29, 2006 at 01:05:30AM +0200, Christian Krafft wrote: > Hi Mattia, > > sorry, if this is a double post again, but my email client doesn't show, > that the email got send correctly, and I did'got the mail from the lis, > unfortunately I don't have it in my clipboard :-( > > why not having a general section in the config file, and per cpu based > rules in special sections, if want. better per device, if you introduce > rules for graphic card and stuff. > This way, it would be easy to keep it simple for all the single cpu > users (haha), but also to configure advanced rules, that would be needed > in large smp environments. what about modifing the Rule->Profile association directive to allow (and understand) things like: [Rule] ... profile=CPU0:profile1;CPU1:profile2;... # if CPUn is not covered just don't apply anything [/Rule] This way one could better reuse already written profiles. Yes, I like the idea :) > You could fork a process for each physical cpu, using the general > section plus the cpu based, if specified. With affinity, there would be > less overhead on kernel side when the cpufreqd process reads from sysfs > files, because the kernel thread that is writing to the file is already > running on the cpu, that contains the pm registers. Hmmm... don't know how much we would win, we'd need to cohordinate more processes for just a cache hit every now and then. It'd also need some major rewrite for that. > Maybe it is also possible, to register for file changes. this way, it > would be possible, to switch profiles within a guarranteed time, and not > in polling mode. Maybe that comes usefull, if one needs to react on > critical temperature or other events. I'm already experimenting with it (inotify) but last time I checked /proc doesn't trigger inotify events > On such system the on-demand governor is not good enough, because it is > not so configurable. That is where cpufreqd comes in. What I meant before was using cpufreqd to fine grain the on-demand usage, thus leaving the cpu-load control to ondemand and let cpufreqd govern frequency bounds to which ondemand has to operate. > I would like to contribute, but I'm quite new to C, so it will take it's > time. Great, you're welcome! -- mattia :wq! |
From: Mattia D. <mat...@us...> - 2006-07-01 18:49:16
|
Update of /cvsroot/cpufreqd/sources2/manpages In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv22960/manpages Modified Files: cpufreqd.conf.5 Log Message: document the undocumented... Index: cpufreqd.conf.5 =================================================================== RCS file: /cvsroot/cpufreqd/sources2/manpages/cpufreqd.conf.5,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- cpufreqd.conf.5 17 Jun 2006 18:09:01 -0000 1.20 +++ cpufreqd.conf.5 1 Jul 2006 18:49:00 -0000 1.21 @@ -237,6 +237,20 @@ Rules with overlapping cpu_intervals are allowed. .PP +.SS "exec plugin" +Executes command on Rule/Profile selection. Available Rule and Profile entries: +.TP +.B "exec_pre" +.TP +.B "exec_post" +You can give commands that you want to be executed when a Rule or Profile is +applied. As the names suggest, +.B exec_pre +will be run before a Rule or Profile is applied, +.B exec_post +will be run after. + +.PP .SS "programs plugin" Monitors active processes. Available entries: .TP |
From: Mattia D. <mal...@li...> - 2006-06-28 17:55:54
|
Hello, On Wed, Jun 28, 2006 at 06:45:12PM +0200, Christian Krafft wrote: > Hi, > > is there already someone working on SMT/SMP support ? > > I recognized, that cpu plugin is using the average of all logical cpus. Not only, see the manpage for cpufreqd.conf, you can setup very fancy cpu monitoring rules since 2.1.0. eg: cpu_interval=0:50-100;1:0-50 cpu_interval=ANY:80-100 cpu_interval=ALL:0-10 > Also cpufreqd is applying the same rule for each CPU. this is true... :( but there's a big chance your cpus won't be able to switch separately. This is true for any SMT and also for current Intel Duo-s. Anyway my current suggestion is that if you need cpu load based monitoring you should use the ondemand governor that is already SMP aware. I like figuring cpufreqd as a deamon for defining "higher level" policies, the simplest example of that being the configuration that gentoo provides[1]. One can then define finer rules with the available directives and maybe limit ondemand (or the other governors) to specific frequencies (0%-75%). [1]: http://www.gentoo.org/doc/en/power-management-guide.xml#doc_chap3 > If there is a fix available, I would like to test it. If there is nobody > working on that, it woule be nice, if someone could point out, where to > look at. It is very easy to implement, the thing I'm most unsure is how to manage it in the config file. I don't even have an SMP system and I'm a little stuck on the usability side of the issue. The easiest implementation would be adding a "cpu" parameter to "Profiles" (or even "Rules") but I fear it could turn the configuration of cpufreqd into a nightmare pretty soon, having to write a separate profile for each cpu. How would you expect it to be working if it was already in place? I'm very open to suggestions :) [just thinking] hmmm, I could bind a profile to a specific cpu based _only_ on the load of such cpu... oh, and the cpu temperature could also be taken into consideration (but this is tricky as lm_sensors doesn't tell enough about that). What about the cpu affinity in "programs" directives? :) bye -- mattia :wq! |
From: Christian K. <kr...@de...> - 2006-06-28 16:45:49
|
Hi, is there already someone working on SMT/SMP support ? I recognized, that cpu plugin is using the average of all logical cpus. Also cpufreqd is applying the same rule for each CPU. It looks like /sys/devices/system/cpu/cpu0/cpufreq/affected_cpus is not taken into account. If there is a fix available, I would like to test it. If there is nobody working on that, it woule be nice, if someone could point out, where to look at. Cheers, Christian Krafft |
From: Christian K. <kr...@de...> - 2006-06-28 16:44:14
|
Hi, is there already someone working on SMT/SMP support ? I recognized, that cpu plugin is using the average of all logical cpus. Also cpufreqd is applying the same rule for each CPU. It looks like /sys/devices/system/cpu/cpu0/cpufreq/affected_cpus is not taken into account. If there is a fix available, I would like to test it. If there is nobody working on that, it woule be nice, if someone could point out, where to look at. Cheers, Christian Krafft |
From: Mattia D. <mat...@us...> - 2006-06-25 15:47:41
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv9762/src Modified Files: cpufreqd_acpi_temperature.c Log Message: fix log for the tempaerature read from acpi Index: cpufreqd_acpi_temperature.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_acpi_temperature.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- cpufreqd_acpi_temperature.c 12 May 2006 18:08:40 -0000 1.16 +++ cpufreqd_acpi_temperature.c 25 Jun 2006 15:47:38 -0000 1.17 @@ -202,7 +202,7 @@ temperature += t; atz_list[i].temperature = t; clog(LOG_INFO, "temperature for %s is %ldC\n", - atz_list[i].name, temperature); + atz_list[i].name, atz_list[i].temperature); } fclose(fp); |
From: Mattia D. <mat...@us...> - 2006-06-25 15:43:53
|
Update of /cvsroot/cpufreqd/sources2 In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv8042 Modified Files: configure.in Log Message: damn damn! this one missed the tag! Index: configure.in =================================================================== RCS file: /cvsroot/cpufreqd/sources2/configure.in,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- configure.in 16 Apr 2006 16:23:30 -0000 1.18 +++ configure.in 25 Jun 2006 15:43:50 -0000 1.19 @@ -1,5 +1,5 @@ # Process this file with autoconf to produce a configure script. -AC_INIT([cpufreqd],[2.1.0],[mal...@li...], [cpufreqd]) +AC_INIT([cpufreqd],[2.1.1],[mal...@li...], [cpufreqd]) AC_CANONICAL_TARGET([]) AM_INIT_AUTOMAKE(1.8 dist-bzip2 foreign) |
From: Mattia D. <mat...@us...> - 2006-06-25 15:40:01
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv6225/src Modified Files: cpufreqd_log.c cpufreqd.h Log Message: damn damn! this one missed the tag! Index: cpufreqd.h =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd.h,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- cpufreqd.h 13 Mar 2006 22:05:16 -0000 1.15 +++ cpufreqd.h 25 Jun 2006 15:39:54 -0000 1.16 @@ -20,7 +20,7 @@ #ifndef __CPUFREQD_H__ #define __CPUFREQD_H__ -#define __CPUFREQD_VERSION__ "2.1.0" +#define __CPUFREQD_VERSION__ "2.1.1" #define __CPUFREQD_MAINTAINER__ "mal...@li..." #ifdef __GNUC__ Index: cpufreqd_log.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_log.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- cpufreqd_log.c 12 Mar 2006 10:42:34 -0000 1.7 +++ cpufreqd_log.c 25 Jun 2006 15:39:54 -0000 1.8 @@ -44,12 +44,14 @@ */ void cpufreqd_log(int prio, const char *fmt, ...) { va_list argp; + va_list argp2; /* do we need to write? */ if (configuration->log_level < prio) return; va_start(argp, fmt); + va_copy(argp2, argp); if (configuration->no_daemon) { if (configuration->log_level <= LOG_ERR) { @@ -67,9 +69,10 @@ } vsyslog(prio, fmt, argp); if (configuration->log_level <= LOG_ERR) { - vfprintf(stderr, fmt, argp); + vfprintf(stderr, fmt, argp2); /* fflush(stderr); */ } } va_end(argp); + va_end(argp2); } |
From: Mattia D. <mat...@us...> - 2006-06-25 15:40:00
|
Update of /cvsroot/cpufreqd/sources2 In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv6225 Modified Files: ChangeLog Log Message: damn damn! this one missed the tag! Index: ChangeLog =================================================================== RCS file: /cvsroot/cpufreqd/sources2/ChangeLog,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- ChangeLog 21 May 2006 11:53:39 -0000 1.12 +++ ChangeLog 25 Jun 2006 15:39:54 -0000 1.13 @@ -1,3 +1,9 @@ +version 2.1.1 +------------- +* fixed incorrect use of va_args in cpufreqd_log +* fix acpi_ac to not rely on acpi_events to poll the ac status +* acpi: do not depend (that much) on acpi_events + version 2.1.0 ------------- * grouped some useful info in struct cpufreqd_info to let plugins peek important data |
From: Mattia D. <mat...@us...> - 2006-06-21 21:20:10
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv1254/src Modified Files: cpufreqd_acpi.c cpufreqd_acpi_event.c Log Message: try to fix sf bug 1509522 Index: cpufreqd_acpi.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_acpi.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- cpufreqd_acpi.c 11 Jun 2006 20:13:47 -0000 1.3 +++ cpufreqd_acpi.c 21 Jun 2006 21:20:00 -0000 1.4 @@ -104,11 +104,10 @@ static int acpi_update(void) { - acpi_event_lock(); - if ((!acpi_ac_failed && acpi_ev_failed) - || (!acpi_ac_failed && !acpi_ev_failed && is_event_pending())) + if (!acpi_ac_failed) acpi_ac_update(); + acpi_event_lock(); if (!acpi_batt_failed) acpi_battery_update(); Index: cpufreqd_acpi_event.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_acpi_event.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- cpufreqd_acpi_event.c 11 Jun 2006 20:11:52 -0000 1.6 +++ cpufreqd_acpi_event.c 21 Jun 2006 21:20:01 -0000 1.7 @@ -46,6 +46,8 @@ struct acpi_event *next; }; +static int acpi_event_active; + static pthread_t event_thread; static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; static int event_fd; @@ -109,11 +111,15 @@ wake_cpufreqd(); rfd.revents = 0; } + + /* set acpi_event as inactive */ + acpi_event_active = 0; + return NULL; } int is_event_pending(void) { - return event_pending; + return event_pending && acpi_event_active; } void reset_event(void) { @@ -179,6 +185,7 @@ clog(LOG_ERR, "Unable to launch thread: %s\n", strerror(ret)); return -1; } + acpi_event_active = 1; return 0; } |
From: Mattia D. <mal...@li...> - 2006-06-18 18:09:54
|
Hi there! just dropping a note for those following these MLs to tell about new cpufreqd. It contains big improvements (in my eyes at least), the changelog says: version 2.1.0 ------------- * grouped some useful info in struct cpufreqd_info to let plugins peek impo= rtant data * added -m switch to start cpufreqd in manual mode * reset timer when entering manual mode * forcing update when exiting manual mode * sanitized set/reset of SIGALRM * added cpufreqd_exec plugin * added cpufreqd_acpi_event plugin * added cpufreqd_governor_parameters plugin * merged all ACPI plugins into one to let them cohoperate (eg: wait for eve= nts) * acpi_battery now can read /proc/acpi files at longer intervals and estima= tes battery level in between them * acpi_ac waits for ACPI events instead of polling Files at: http://sourceforge.net/project/showfiles.php?group_id=3D58904 Thanks --=20 mattia :wq! |
From: Mattia D. <mat...@us...> - 2006-06-18 15:22:32
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv1350/src Modified Files: cpufreqd_cpu.c Log Message: fix warning float/double conversion (bah, damn gcc) Index: cpufreqd_cpu.c =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/cpufreqd_cpu.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- cpufreqd_cpu.c 12 Jun 2006 18:55:01 -0000 1.16 +++ cpufreqd_cpu.c 18 Jun 2006 15:22:25 -0000 1.17 @@ -100,7 +100,7 @@ unsigned int cpu_num = 0; unsigned int min = 0; unsigned int max = 0; - float nice_scale = 0.0; + float nice_scale = 0.0f; struct cpu_interval *ret = NULL, **temp_cint = NULL; struct cpufreqd_info *cinfo = get_cpufreqd_info(); @@ -116,7 +116,7 @@ cpu_num = cinfo->cpus; min = 0; max = 0; - nice_scale = 3.0; + nice_scale = 3.0f; /* parse formats */ if ((sscanf(cpu_cmd, "%d:%d-%d,%f", &cpu_num, &min, &max, &nice_scale) == 4 @@ -124,7 +124,7 @@ } else if (sscanf(cpu_cmd, "%d:%d-%d", &cpu_num, &min, &max) == 3 && cpu_num < cinfo->cpus) { - nice_scale = 3.0; + nice_scale = 3.0f; } /* ALL or ANY cpus */ else if (sscanf(cpu_cmd, "%3[a-zA-Z]:%d-%d,%f", wcards, &min, &max, &nice_scale) == 4) { @@ -154,7 +154,7 @@ } else if (sscanf(cpu_cmd, "%d-%d", &min, &max) == 2) { cpu_num = cinfo->cpus; - nice_scale = 3.0; + nice_scale = 3.0f; } else { clog(LOG_ERR, "Discarded wrong format for cpu_interval: %s\n", cpu_cmd); @@ -164,11 +164,11 @@ cpu_num, min, max, nice_scale); /* validate values */ - if (nice_scale <= 0.0) { + if (nice_scale <= 0.0f) { clog(LOG_WARNING, "nice_scale value out of range(%.2f), " "resetting to the default value(3).\n", nice_scale); - nice_scale = 3; + nice_scale = 3.0f; } if (min > max) { @@ -197,7 +197,7 @@ return 0; } -static int calculate_cpu_usage(struct cpu_usage *cur, struct cpu_usage *old, float nice_scale) { +static int calculate_cpu_usage(struct cpu_usage *cur, struct cpu_usage *old, double nice_scale) { unsigned long weighted_activity = cur->c_user + cur->c_nice / nice_scale + cur->c_sys; unsigned long weighted_activity_old = old->c_user + old->c_nice / nice_scale + old->c_sys; unsigned long delta_activity = weighted_activity - weighted_activity_old; |
From: Mattia D. <mat...@us...> - 2006-06-17 18:11:44
|
Update of /cvsroot/cpufreqd/sources2/src In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv14858/src Modified Files: Makefile.am Log Message: remove some use of "enable_plugins" and add necessary headers for dist Index: Makefile.am =================================================================== RCS file: /cvsroot/cpufreqd/sources2/src/Makefile.am,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- Makefile.am 12 May 2006 18:08:40 -0000 1.17 +++ Makefile.am 17 Jun 2006 18:09:02 -0000 1.18 @@ -182,6 +182,7 @@ cpufreqd.h \ cpufreqd_plugin.h \ cpufreqd_log.h \ + cpufreqd_acpi.h \ cpufreqd_acpi_ac.h \ cpufreqd_acpi_battery.h \ cpufreqd_acpi_event.h \ |