summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2010-07-23 16:46:42 +0000
committeravg <avg@FreeBSD.org>2010-07-23 16:46:42 +0000
commit0152f7748b6882ab922bbc8093b4a81addeb2522 (patch)
treef3124cdc33a7ecac2dece9830c1d39224095b793 /sys/kern
parente886b3fa85f419c13aa645ce9d9c4fb694d6c280 (diff)
downloadFreeBSD-src-0152f7748b6882ab922bbc8093b4a81addeb2522.zip
FreeBSD-src-0152f7748b6882ab922bbc8093b4a81addeb2522.tar.gz
cpufreq: allocate long-lived buffer for handling of sysctl requests
At present the cpufreq sysctl handler for current level setting would allocate and deallocate a temporary buffer of 24KB even to handle a read-only query. This puts unnecessary load on memory subsystem when current level is checked frequently, e.g. when the likes of powerd and system monitoring software are running. Change the strategy to allocating a long-lived buffer for handling the requests. Reviewed by: njl MFC after: 2 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_cpu.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c
index 4c4f961..3429a0f 100644
--- a/sys/kern/kern_cpu.c
+++ b/sys/kern/kern_cpu.c
@@ -76,6 +76,7 @@ struct cpufreq_softc {
device_t dev;
struct sysctl_ctx_list sysctl_ctx;
struct task startup_task;
+ struct cf_level *levels_buf;
};
struct cf_setting_array {
@@ -180,6 +181,8 @@ cpufreq_attach(device_t dev)
CF_DEBUG("initializing one-time data for %s\n",
device_get_nameunit(dev));
+ sc->levels_buf = malloc(CF_MAX_LEVELS * sizeof(*sc->levels_buf),
+ M_DEVBUF, M_WAITOK);
SYSCTL_ADD_PROC(&sc->sysctl_ctx,
SYSCTL_CHILDREN(device_get_sysctl_tree(parent)),
OID_AUTO, "freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
@@ -227,6 +230,7 @@ cpufreq_detach(device_t dev)
numdevs = devclass_get_count(cpufreq_dc);
if (numdevs == 1) {
CF_DEBUG("final shutdown for %s\n", device_get_nameunit(dev));
+ free(sc->levels_buf, M_DEVBUF);
}
return (0);
@@ -870,9 +874,7 @@ cpufreq_curr_sysctl(SYSCTL_HANDLER_ARGS)
devs = NULL;
sc = oidp->oid_arg1;
- levels = malloc(CF_MAX_LEVELS * sizeof(*levels), M_TEMP, M_NOWAIT);
- if (levels == NULL)
- return (ENOMEM);
+ levels = sc->levels_buf;
error = CPUFREQ_GET(sc->dev, &levels[0]);
if (error)
@@ -915,8 +917,6 @@ cpufreq_curr_sysctl(SYSCTL_HANDLER_ARGS)
out:
if (devs)
free(devs, M_TEMP);
- if (levels)
- free(levels, M_TEMP);
return (error);
}
@@ -934,7 +934,7 @@ cpufreq_levels_sysctl(SYSCTL_HANDLER_ARGS)
/* Get settings from the device and generate the output string. */
count = CF_MAX_LEVELS;
- levels = malloc(count * sizeof(*levels), M_TEMP, M_NOWAIT);
+ levels = sc->levels_buf;
if (levels == NULL) {
sbuf_delete(&sb);
return (ENOMEM);
@@ -957,7 +957,6 @@ cpufreq_levels_sysctl(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
out:
- free(levels, M_TEMP);
sbuf_delete(&sb);
return (error);
}
OpenPOWER on IntegriCloud