cregit-Linux how code gets into the kernel

Release 4.11 tools/power/cpupower/lib/cpuidle.c

/*
 *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
 *  (C) 2011       Thomas Renninger <trenn@novell.com> Novell Inc.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "cpuidle.h"
#include "cpupower_intern.h"

/*
 * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
 * exists.
 * For example the functionality to disable c-states was introduced in later
 * kernel versions, this function can be used to explicitly check for this
 * feature.
 *
 * returns 1 if the file exists, 0 otherwise.
 */

static unsigned int cpuidle_state_file_exists(unsigned int cpu, unsigned int idlestate, const char *fname) { char path[SYSFS_PATH_MAX]; struct stat statbuf; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", cpu, idlestate, fname); if (stat(path, &statbuf) != 0) return 0; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger67100.00%1100.00%
Total67100.00%1100.00%

/* * helper function to read file from /sys into given buffer * fname is a relative path under "cpuX/cpuidle/stateX/" dir * cstates starting with 0, C0 is not counted as cstate. * This means if you want C1 info, pass 0 as idlestate param */
static unsigned int cpuidle_state_read_file(unsigned int cpu, unsigned int idlestate, const char *fname, char *buf, size_t buflen) { char path[SYSFS_PATH_MAX]; int fd; ssize_t numread; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", cpu, idlestate, fname); fd = open(path, O_RDONLY); if (fd == -1) return 0; numread = read(fd, buf, buflen - 1); if (numread < 1) { close(fd); return 0; } buf[numread] = '\0'; close(fd); return (unsigned int) numread; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger125100.00%1100.00%
Total125100.00%1100.00%

/* * helper function to write a new value to a /sys file * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir * * Returns the number of bytes written or 0 on error */
static unsigned int cpuidle_state_write_file(unsigned int cpu, unsigned int idlestate, const char *fname, const char *value, size_t len) { char path[SYSFS_PATH_MAX]; int fd; ssize_t numwrite; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", cpu, idlestate, fname); fd = open(path, O_WRONLY); if (fd == -1) return 0; numwrite = write(fd, value, len); if (numwrite < 1) { close(fd); return 0; } close(fd); return (unsigned int) numwrite; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger117100.00%1100.00%
Total117100.00%1100.00%

/* read access to files which contain one numeric value */ enum idlestate_value { IDLESTATE_USAGE, IDLESTATE_POWER, IDLESTATE_LATENCY, IDLESTATE_TIME, IDLESTATE_DISABLE, MAX_IDLESTATE_VALUE_FILES }; static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = { [IDLESTATE_USAGE] = "usage", [IDLESTATE_POWER] = "power", [IDLESTATE_LATENCY] = "latency", [IDLESTATE_TIME] = "time", [IDLESTATE_DISABLE] = "disable", };
static unsigned long long cpuidle_state_get_one_value(unsigned int cpu, unsigned int idlestate, enum idlestate_value which) { unsigned long long value; unsigned int len; char linebuf[MAX_LINE_LEN]; char *endp; if (which >= MAX_IDLESTATE_VALUE_FILES) return 0; len = cpuidle_state_read_file(cpu, idlestate, idlestate_value_files[which], linebuf, sizeof(linebuf)); if (len == 0) return 0; value = strtoull(linebuf, &endp, 0); if (endp == linebuf || errno == ERANGE) return 0; return value; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger106100.00%1100.00%
Total106100.00%1100.00%

/* read access to files which contain one string */ enum idlestate_string { IDLESTATE_DESC, IDLESTATE_NAME, MAX_IDLESTATE_STRING_FILES }; static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = { [IDLESTATE_DESC] = "desc", [IDLESTATE_NAME] = "name", };
static char *cpuidle_state_get_one_string(unsigned int cpu, unsigned int idlestate, enum idlestate_string which) { char linebuf[MAX_LINE_LEN]; char *result; unsigned int len; if (which >= MAX_IDLESTATE_STRING_FILES) return NULL; len = cpuidle_state_read_file(cpu, idlestate, idlestate_string_files[which], linebuf, sizeof(linebuf)); if (len == 0) return NULL; result = strdup(linebuf); if (result == NULL) return NULL; if (result[strlen(result) - 1] == '\n') result[strlen(result) - 1] = '\0'; return result; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger117100.00%1100.00%
Total117100.00%1100.00%

/* * Returns: * 1 if disabled * 0 if enabled * -1 if idlestate is not available * -2 if disabling is not supported by the kernel */
int cpuidle_is_state_disabled(unsigned int cpu, unsigned int idlestate) { if (cpuidle_state_count(cpu) <= idlestate) return -1; if (!cpuidle_state_file_exists(cpu, idlestate, idlestate_value_files[IDLESTATE_DISABLE])) return -2; return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_DISABLE); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger55100.00%1100.00%
Total55100.00%1100.00%

/* * Pass 1 as last argument to disable or 0 to enable the state * Returns: * 0 on success * negative values on error, for example: * -1 if idlestate is not available * -2 if disabling is not supported by the kernel * -3 No write access to disable/enable C-states */
int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate, unsigned int disable) { char value[SYSFS_PATH_MAX]; int bytes_written; if (cpuidle_state_count(cpu) <= idlestate) return -1; if (!cpuidle_state_file_exists(cpu, idlestate, idlestate_value_files[IDLESTATE_DISABLE])) return -2; snprintf(value, SYSFS_PATH_MAX, "%u", disable); bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable", value, sizeof(disable)); if (bytes_written) return 0; return -3; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger98100.00%1100.00%
Total98100.00%1100.00%


unsigned long cpuidle_state_latency(unsigned int cpu, unsigned int idlestate) { return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger24100.00%1100.00%
Total24100.00%1100.00%


unsigned long cpuidle_state_usage(unsigned int cpu, unsigned int idlestate) { return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_USAGE); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger24100.00%1100.00%
Total24100.00%1100.00%


unsigned long long cpuidle_state_time(unsigned int cpu, unsigned int idlestate) { return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_TIME); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger25100.00%1100.00%
Total25100.00%1100.00%


char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate) { return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_NAME); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger24100.00%1100.00%
Total24100.00%1100.00%


char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate) { return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_DESC); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger24100.00%1100.00%
Total24100.00%1100.00%

/* * Returns number of supported C-states of CPU core cpu * Negativ in error case * Zero if cpuidle does not export any C-states */
unsigned int cpuidle_state_count(unsigned int cpu) { char file[SYSFS_PATH_MAX]; struct stat statbuf; int idlestates = 1; snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) return 0; snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) return 0; while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state%d", cpu, idlestates); idlestates++; } idlestates--; return idlestates; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger137100.00%1100.00%
Total137100.00%1100.00%

/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/ /* * helper function to read file from /sys into given buffer * fname is a relative path under "cpu/cpuidle/" dir */
static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf, size_t buflen) { char path[SYSFS_PATH_MAX]; snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname); return sysfs_read_file(path, buf, buflen); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger50100.00%1100.00%
Total50100.00%1100.00%

/* read access to files which contain one string */ enum cpuidle_string { CPUIDLE_GOVERNOR, CPUIDLE_GOVERNOR_RO, CPUIDLE_DRIVER, MAX_CPUIDLE_STRING_FILES }; static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = { [CPUIDLE_GOVERNOR] = "current_governor", [CPUIDLE_GOVERNOR_RO] = "current_governor_ro", [CPUIDLE_DRIVER] = "current_driver", };
static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which) { char linebuf[MAX_LINE_LEN]; char *result; unsigned int len; if (which >= MAX_CPUIDLE_STRING_FILES) return NULL; len = sysfs_cpuidle_read_file(cpuidle_string_files[which], linebuf, sizeof(linebuf)); if (len == 0) return NULL; result = strdup(linebuf); if (result == NULL) return NULL; if (result[strlen(result) - 1] == '\n') result[strlen(result) - 1] = '\0'; return result; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger105100.00%1100.00%
Total105100.00%1100.00%


char *cpuidle_get_governor(void) { char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO); if (!tmp) return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR); else return tmp; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger32100.00%1100.00%
Total32100.00%1100.00%


char *cpuidle_get_driver(void) { return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger14100.00%1100.00%
Total14100.00%1100.00%

/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */

Overall Contributors

PersonTokensPropCommitsCommitProp
Thomas Renninger1318100.00%1100.00%
Total1318100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.