tools/power/cpupower/utils/cpufreq-set.c

Source file repositories/reference/linux-study-clean/tools/power/cpupower/utils/cpufreq-set.c

File Facts

System
Linux kernel
Corpus path
tools/power/cpupower/utils/cpufreq-set.c
Extension
.c
Size
7236 bytes
Lines
338
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct freq_units {
	char		*str_unit;
	int		power_of_ten;
};

const struct freq_units def_units[] = {
	{"hz", -3},
	{"khz", 0}, /* default */
	{"mhz", 3},
	{"ghz", 6},
	{"thz", 9},
	{NULL, 0}
};

static void print_unknown_arg(void)
{
	printf(_("invalid or unknown argument\n"));
}

static unsigned long string_to_frequency(const char *str)
{
	char normalized[NORM_FREQ_LEN];
	const struct freq_units *unit;
	const char *scan;
	char *end;
	unsigned long freq;
	int power = 0, match_count = 0, i, cp, pad;

	while (*str == '0')
		str++;

	for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
		if (*scan == '.' && match_count == 0)
			match_count = 1;
		else if (*scan == '.' && match_count == 1)
			return 0;
	}

	if (*scan) {
		match_count = 0;
		for (unit = def_units; unit->str_unit; unit++) {
			for (i = 0;
			     scan[i] && tolower(scan[i]) == unit->str_unit[i];
			     ++i)
				continue;
			if (scan[i])
				continue;
			match_count++;
			power = unit->power_of_ten;
		}
		if (match_count != 1)
			return 0;
	}

	/* count the number of digits to be copied */
	for (cp = 0; isdigit(str[cp]); cp++)
		continue;

	if (str[cp] == '.') {
		while (power > -1 && isdigit(str[cp+1])) {
			cp++;
			power--;
		}
	}
	if (power >= -1) {		/* not enough => pad */
		pad = power + 1;
	} else {			/* too much => strip */
		pad = 0;
		cp += power + 1;
	}
	/* check bounds */
	if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
		return 0;

	/* copy digits */
	for (i = 0; i < cp; i++, str++) {
		if (*str == '.')
			str++;
		normalized[i] = *str;
	}
	/* and pad */
	for (; i < cp + pad; i++)
		normalized[i] = '0';

	/* round up, down ? */
	match_count = (normalized[i-1] >= '5');
	/* and drop the decimal part */
	normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */

	/* final conversion (and applying rounding) */

Annotation

Implementation Notes