brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · 8b42c2f Raw
213 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc4 */5 6#include <stdio.h>7#include <stdlib.h>8#include <stdint.h>9#include <string.h>10#include <limits.h>11#include <cpuidle.h>12 13#include "helpers/helpers.h"14#include "idle_monitor/cpupower-monitor.h"15 16#define CPUIDLE_STATES_MAX 1017static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];18struct cpuidle_monitor cpuidle_sysfs_monitor;19 20static unsigned long long **previous_count;21static unsigned long long **current_count;22static struct timespec start_time;23static unsigned long long timediff;24 25static int cpuidle_get_count_percent(unsigned int id, double *percent,26				     unsigned int cpu)27{28	unsigned long long statediff = current_count[cpu][id]29		- previous_count[cpu][id];30	dprint("%s: - diff: %llu - percent: %f (%u)\n",31	       cpuidle_cstates[id].name, timediff, *percent, cpu);32 33	if (timediff == 0)34		*percent = 0.0;35	else36		*percent = ((100.0 * statediff) / timediff);37 38	dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",39	       cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);40 41	return 0;42}43 44static int cpuidle_start(void)45{46	int cpu, state;47	clock_gettime(CLOCK_REALTIME, &start_time);48	for (cpu = 0; cpu < cpu_count; cpu++) {49		for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;50		     state++) {51			previous_count[cpu][state] =52				cpuidle_state_time(cpu, state);53			dprint("CPU %d - State: %d - Val: %llu\n",54			       cpu, state, previous_count[cpu][state]);55		}56	}57	return 0;58}59 60static int cpuidle_stop(void)61{62	int cpu, state;63	struct timespec end_time;64	clock_gettime(CLOCK_REALTIME, &end_time);65	timediff = timespec_diff_us(start_time, end_time);66 67	for (cpu = 0; cpu < cpu_count; cpu++) {68		for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;69		     state++) {70			current_count[cpu][state] =71				cpuidle_state_time(cpu, state);72			dprint("CPU %d - State: %d - Val: %llu\n",73			       cpu, state, previous_count[cpu][state]);74		}75	}76	return 0;77}78 79void fix_up_intel_idle_driver_name(char *tmp, int num)80{81	/* fix up cpuidle name for intel idle driver */82	if (!strncmp(tmp, "NHM-", 4)) {83		switch (num) {84		case 1:85			strcpy(tmp, "C1");86			break;87		case 2:88			strcpy(tmp, "C3");89			break;90		case 3:91			strcpy(tmp, "C6");92			break;93		}94	} else if (!strncmp(tmp, "SNB-", 4)) {95		switch (num) {96		case 1:97			strcpy(tmp, "C1");98			break;99		case 2:100			strcpy(tmp, "C3");101			break;102		case 3:103			strcpy(tmp, "C6");104			break;105		case 4:106			strcpy(tmp, "C7");107			break;108		}109	} else if (!strncmp(tmp, "ATM-", 4)) {110		switch (num) {111		case 1:112			strcpy(tmp, "C1");113			break;114		case 2:115			strcpy(tmp, "C2");116			break;117		case 3:118			strcpy(tmp, "C4");119			break;120		case 4:121			strcpy(tmp, "C6");122			break;123		}124	}125}126 127#ifdef __powerpc__128void map_power_idle_state_name(char *tmp)129{130	if (!strncmp(tmp, "stop0_lite", CSTATE_NAME_LEN))131		strcpy(tmp, "stop0L");132	else if (!strncmp(tmp, "stop1_lite", CSTATE_NAME_LEN))133		strcpy(tmp, "stop1L");134	else if (!strncmp(tmp, "stop2_lite", CSTATE_NAME_LEN))135		strcpy(tmp, "stop2L");136}137#else138void map_power_idle_state_name(char *tmp) { }139#endif140 141static struct cpuidle_monitor *cpuidle_register(void)142{143	int num;144	char *tmp;145	int this_cpu;146 147	this_cpu = sched_getcpu();148 149	/* Assume idle state count is the same for all CPUs */150	cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(this_cpu);151 152	if (cpuidle_sysfs_monitor.hw_states_num <= 0)153		return NULL;154 155	for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {156		tmp = cpuidle_state_name(this_cpu, num);157		if (tmp == NULL)158			continue;159 160		map_power_idle_state_name(tmp);161		fix_up_intel_idle_driver_name(tmp, num);162		strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);163		free(tmp);164 165		tmp = cpuidle_state_desc(this_cpu, num);166		if (tmp == NULL)167			continue;168		strncpy(cpuidle_cstates[num].desc, tmp,	CSTATE_DESC_LEN - 1);169		free(tmp);170 171		cpuidle_cstates[num].range = RANGE_THREAD;172		cpuidle_cstates[num].id = num;173		cpuidle_cstates[num].get_count_percent =174			cpuidle_get_count_percent;175	}176 177	/* Free this at program termination */178	previous_count = malloc(sizeof(long long *) * cpu_count);179	current_count = malloc(sizeof(long long *) * cpu_count);180	for (num = 0; num < cpu_count; num++) {181		previous_count[num] = malloc(sizeof(long long) *182					cpuidle_sysfs_monitor.hw_states_num);183		current_count[num] = malloc(sizeof(long long) *184					cpuidle_sysfs_monitor.hw_states_num);185	}186 187	cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);188	return &cpuidle_sysfs_monitor;189}190 191void cpuidle_unregister(void)192{193	int num;194 195	for (num = 0; num < cpu_count; num++) {196		free(previous_count[num]);197		free(current_count[num]);198	}199	free(previous_count);200	free(current_count);201}202 203struct cpuidle_monitor cpuidle_sysfs_monitor = {204	.name			= "Idle_Stats",205	.hw_states		= cpuidle_cstates,206	.start			= cpuidle_start,207	.stop			= cpuidle_stop,208	.do_register		= cpuidle_register,209	.unregister		= cpuidle_unregister,210	.flags.needs_root	= 0,211	.overflow_s		= UINT_MAX,212};213