2021-05-16 04:25:14 -07:00
|
|
|
#if defined(__OpenBSD__)
|
|
|
|
# define CPU_STATES 6
|
|
|
|
#else
|
|
|
|
# define CPU_STATES 5
|
|
|
|
#endif
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
int
|
|
|
|
cores_count(void)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
static int cores = 0;
|
|
|
|
|
|
|
|
if (cores != 0)
|
|
|
|
return cores;
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
char buf[4096];
|
|
|
|
FILE *f;
|
|
|
|
int line = 0;
|
|
|
|
|
|
|
|
f = fopen("/proc/stat", "r");
|
|
|
|
if (!f) return 0;
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof(buf), f))
|
|
|
|
{
|
|
|
|
if (line)
|
|
|
|
{
|
|
|
|
if (!strncmp(buf, "cpu", 3))
|
|
|
|
cores++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
line++;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
#elif defined(__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
|
|
|
size_t len;
|
|
|
|
int mib[2] = { CTL_HW, HW_NCPU };
|
|
|
|
|
|
|
|
len = sizeof(cores);
|
|
|
|
if (sysctl(mib, 2, &cores, &len, NULL, 0) < 0)
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
return cores;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_online_count(void)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
#if defined(__OpenBSD__)
|
|
|
|
static int cores = 0;
|
|
|
|
|
|
|
|
if (cores != 0) return cores;
|
|
|
|
|
|
|
|
size_t len;
|
|
|
|
int mib[2] = { CTL_HW, HW_NCPUONLINE };
|
|
|
|
|
|
|
|
len = sizeof(cores);
|
|
|
|
if (sysctl(mib, 2, &cores, &len, NULL, 0) < 0)
|
2021-05-17 07:55:50 -07:00
|
|
|
return cores_count();
|
2021-05-16 04:25:14 -07:00
|
|
|
|
|
|
|
return cores;
|
|
|
|
#else
|
2021-05-17 07:55:50 -07:00
|
|
|
return cores_count();
|
2021-05-16 04:25:14 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
void
|
2021-05-17 08:19:44 -07:00
|
|
|
cores_update(Eina_List *cores)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
int diff_total, diff_idle;
|
|
|
|
double ratio, percent;
|
|
|
|
unsigned long total, idle, used;
|
2021-05-17 00:58:23 -07:00
|
|
|
Cpu_Core *core;
|
2021-05-17 05:36:40 -07:00
|
|
|
int ncpu = eina_list_count(cores);
|
|
|
|
if (!ncpu) return;
|
|
|
|
|
2021-05-16 04:25:14 -07:00
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
size_t size;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
size = sizeof(unsigned long) * (CPU_STATES * ncpu);
|
|
|
|
unsigned long cpu_times[ncpu][CPU_STATES];
|
|
|
|
|
|
|
|
if (sysctlbyname("kern.cp_times", cpu_times, &size, NULL, 0) < 0)
|
|
|
|
return;
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
for (i = 0; i < ncpu; i++)
|
|
|
|
{
|
|
|
|
core = eina_list_nth(cores, i);
|
2021-05-16 04:25:14 -07:00
|
|
|
unsigned long *cpu = cpu_times[i];
|
|
|
|
|
|
|
|
total = 0;
|
|
|
|
for (j = CP_USER; j <= CP_IDLE; j++)
|
|
|
|
total += cpu[j];
|
|
|
|
|
|
|
|
idle = cpu[CP_IDLE];
|
|
|
|
|
|
|
|
diff_total = total - core->total;
|
|
|
|
diff_idle = idle - core->idle;
|
|
|
|
if (diff_total == 0) diff_total = 1;
|
|
|
|
|
|
|
|
ratio = diff_total / 100.0;
|
|
|
|
used = diff_total - diff_idle;
|
|
|
|
percent = used / ratio;
|
|
|
|
|
|
|
|
if (percent > 100) percent = 100;
|
|
|
|
else if (percent < 0)
|
|
|
|
percent = 0;
|
|
|
|
|
|
|
|
core->percent = percent;
|
|
|
|
core->total = total;
|
|
|
|
core->idle = idle;
|
|
|
|
}
|
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
static struct cpustats cpu_times[CPU_STATES];
|
|
|
|
static int cpu_time_mib[] = { CTL_KERN, KERN_CPUSTATS, 0 };
|
|
|
|
size_t size;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
memset(&cpu_times, 0, CPU_STATES * sizeof(struct cpustats));
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
for (i = 0; i < ncpu; i++)
|
|
|
|
{
|
|
|
|
core = eina_list_nth(cores, i);
|
2021-05-16 04:25:14 -07:00
|
|
|
size = sizeof(struct cpustats);
|
|
|
|
cpu_time_mib[2] = i;
|
|
|
|
if (sysctl(cpu_time_mib, 3, &cpu_times[i], &size, NULL, 0) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
total = 0;
|
|
|
|
for (j = 0; j < CPU_STATES; j++)
|
|
|
|
total += cpu_times[i].cs_time[j];
|
|
|
|
|
|
|
|
idle = cpu_times[i].cs_time[CP_IDLE];
|
|
|
|
|
|
|
|
diff_total = total - core->total;
|
|
|
|
if (diff_total == 0) diff_total = 1;
|
|
|
|
|
|
|
|
diff_idle = idle - core->idle;
|
|
|
|
ratio = diff_total / 100.0;
|
|
|
|
used = diff_total - diff_idle;
|
|
|
|
percent = used / ratio;
|
|
|
|
|
|
|
|
if (percent > 100) percent = 100;
|
|
|
|
else if (percent < 0)
|
|
|
|
percent = 0;
|
|
|
|
|
|
|
|
core->percent = percent;
|
|
|
|
core->total = total;
|
|
|
|
core->idle = idle;
|
|
|
|
}
|
|
|
|
#elif defined(__linux__)
|
|
|
|
char *buf, name[128];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
buf = file_contents("/proc/stat");
|
|
|
|
if (!buf) return;
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
for (i = 0; i < ncpu; i++)
|
|
|
|
{
|
|
|
|
core = eina_list_nth(cores, i);
|
2021-05-16 04:25:14 -07:00
|
|
|
snprintf(name, sizeof(name), "cpu%d", i);
|
|
|
|
char *line = strstr(buf, name);
|
|
|
|
if (line)
|
|
|
|
{
|
|
|
|
line = strchr(line, ' ') + 1;
|
|
|
|
unsigned long cpu_times[4] = { 0 };
|
|
|
|
|
|
|
|
if (4 != sscanf(line, "%lu %lu %lu %lu", &cpu_times[0],
|
|
|
|
&cpu_times[1], &cpu_times[2], &cpu_times[3]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
total = cpu_times[0] + cpu_times[1] + cpu_times[2] + cpu_times[3];
|
|
|
|
idle = cpu_times[3];
|
|
|
|
diff_total = total - core->total;
|
|
|
|
if (diff_total == 0) diff_total = 1;
|
|
|
|
|
|
|
|
diff_idle = idle - core->idle;
|
|
|
|
ratio = diff_total / 100.0;
|
|
|
|
used = diff_total - diff_idle;
|
|
|
|
percent = used / ratio;
|
|
|
|
|
|
|
|
if (percent > 100) percent = 100;
|
|
|
|
else if (percent < 0)
|
|
|
|
percent = 0;
|
|
|
|
|
|
|
|
core->percent = percent;
|
|
|
|
core->total = total;
|
|
|
|
core->idle = idle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
#elif defined(__MacOS__)
|
|
|
|
mach_msg_type_number_t count;
|
|
|
|
processor_cpu_load_info_t load;
|
|
|
|
mach_port_t mach_port;
|
2021-05-17 07:55:50 -07:00
|
|
|
unsigned int cores_count;
|
2021-05-16 04:25:14 -07:00
|
|
|
int i;
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_count = eina_list_count(cores);
|
2021-05-16 04:25:14 -07:00
|
|
|
|
|
|
|
count = HOST_CPU_LOAD_INFO_COUNT;
|
|
|
|
mach_port = mach_host_self();
|
2021-05-17 07:55:50 -07:00
|
|
|
if (host_processor_info(mach_port, PROCESSOR_CPU_LOAD_INFO, &cores_count,
|
2021-05-16 04:25:14 -07:00
|
|
|
(processor_info_array_t *)&load, &count) != KERN_SUCCESS)
|
|
|
|
exit(-1);
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
for (i = 0; i < ncpu; i++)
|
|
|
|
{
|
|
|
|
core = eina_list_nth(cores, i);
|
2021-05-16 04:25:14 -07:00
|
|
|
|
|
|
|
total = load[i].cpu_ticks[CPU_STATE_USER] +
|
|
|
|
load[i].cpu_ticks[CPU_STATE_SYSTEM] +
|
|
|
|
load[i].cpu_ticks[CPU_STATE_IDLE] +
|
|
|
|
load[i].cpu_ticks[CPU_STATE_NICE];
|
|
|
|
idle = load[i].cpu_ticks[CPU_STATE_IDLE];
|
|
|
|
|
|
|
|
diff_total = total - core->total;
|
|
|
|
if (diff_total == 0) diff_total = 1;
|
|
|
|
diff_idle = idle - core->idle;
|
|
|
|
ratio = diff_total / 100.0;
|
|
|
|
used = diff_total - diff_idle;
|
|
|
|
percent = used / ratio;
|
|
|
|
|
|
|
|
if (percent > 100) percent = 100;
|
|
|
|
else if (percent < 0)
|
|
|
|
percent = 0;
|
|
|
|
|
|
|
|
core->percent = percent;
|
|
|
|
core->total = total;
|
|
|
|
core->idle = idle;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-05-17 05:36:40 -07:00
|
|
|
Eina_List *
|
|
|
|
cores_find(void)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
2021-05-17 05:36:40 -07:00
|
|
|
Eina_List *cores = NULL;
|
|
|
|
Cpu_Core *core;
|
|
|
|
int i, ncpu;
|
2021-05-16 04:25:14 -07:00
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
ncpu = cores_count();
|
2021-05-17 05:36:40 -07:00
|
|
|
for (i = 0; i < ncpu; i++)
|
2021-05-17 00:58:23 -07:00
|
|
|
{
|
2021-05-17 05:36:40 -07:00
|
|
|
core = calloc(1, sizeof(Cpu_Core));
|
|
|
|
core->id = i;
|
|
|
|
cores = eina_list_append(cores, core);
|
2021-05-17 00:58:23 -07:00
|
|
|
}
|
2021-05-17 08:19:44 -07:00
|
|
|
cores_topology(cores);
|
2021-05-16 04:25:14 -07:00
|
|
|
return cores;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _cpu_temp_min = 0;
|
|
|
|
static int _cpu_temp_max = 100;
|
|
|
|
static char _core_temps[256][512];
|
|
|
|
static char _hwmon_path[256];
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
_core_n_temperature_read(int n)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
int temp = -1;
|
|
|
|
#if defined(__linux__)
|
|
|
|
|
|
|
|
char *b = file_contents(_core_temps[n]);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
temp = atoi(b) / 1000;
|
|
|
|
free(b);
|
|
|
|
}
|
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
int value;
|
|
|
|
size_t len = sizeof(value);
|
|
|
|
|
|
|
|
if (!_core_temps[n][0])
|
|
|
|
snprintf(_core_temps[n], sizeof(_core_temps[n]), "dev.cpu.%d.temperature", n);
|
|
|
|
|
|
|
|
if ((sysctlbyname(_core_temps[n], &value, &len, NULL, 0)) != -1)
|
|
|
|
{
|
|
|
|
temp = (value - 2732) / 10;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
|
2021-05-17 00:58:23 -07:00
|
|
|
typedef struct _thermal_drv
|
|
|
|
{
|
2021-05-16 04:25:14 -07:00
|
|
|
const char *name;
|
|
|
|
void (*init)(void);
|
|
|
|
char min;
|
|
|
|
char max;
|
|
|
|
} thermal_drv;
|
|
|
|
|
|
|
|
static void
|
|
|
|
_coretemp_init(void)
|
|
|
|
{
|
|
|
|
char buf[4096];
|
2021-05-17 07:55:50 -07:00
|
|
|
int count = cores_count();
|
2021-05-16 04:25:14 -07:00
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
for (int j = 0; j < count; j++)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/topology/core_id", j);
|
|
|
|
char *b = file_contents(buf);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
int core_id = atoi(b);
|
|
|
|
snprintf(_core_temps[j], sizeof(_core_temps[j]), "%s/temp%d_input", _hwmon_path, 2 + core_id);
|
|
|
|
free(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_generic_init(void)
|
|
|
|
{
|
2021-05-17 07:55:50 -07:00
|
|
|
int i, count = cores_count();
|
2021-05-16 04:25:14 -07:00
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
for (i = 0; i < count; i++)
|
2021-05-16 04:25:14 -07:00
|
|
|
snprintf(_core_temps[i], sizeof(_core_temps[i]), "%s/temp1_input", _hwmon_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
core_id_temperature(int id)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
static int init = 0;
|
|
|
|
|
|
|
|
// This list is not exhastive by any means, if you have the
|
|
|
|
// hardware and can provide a better init, please do. WIP.
|
|
|
|
// Min max (where applicable)
|
|
|
|
thermal_drv drivers[] = {
|
|
|
|
{ "coretemp", _coretemp_init, 0, 90 }, /* Intel Coretemp */
|
|
|
|
{ "k10temp", _generic_init, 0, 90 }, /* AMD K10 */
|
|
|
|
{ "cpu_thermal", _generic_init, 0, 90 }, /* BCM2835/BCM2711 (RPI3/4) */
|
|
|
|
{ "cup", _generic_init, 0, 100 }, /* RK3399 */
|
|
|
|
{ "soc_thermal", _generic_init, 0, 100 }, /* RK3326 */
|
|
|
|
{ "cpu0_thermal", _generic_init, 0, 100 }, /* AllWinner A64 */
|
|
|
|
{ "soc_dts0", _generic_init, 0, 90 }, /* Intel Baytrail */
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!init)
|
|
|
|
{
|
|
|
|
char buf[4096];
|
|
|
|
struct dirent *dh;
|
|
|
|
DIR *dir;
|
|
|
|
|
|
|
|
memset(&_core_temps, 0, sizeof(_core_temps));
|
|
|
|
memset(&_hwmon_path, 0, sizeof(_hwmon_path));
|
|
|
|
|
|
|
|
dir = opendir("/sys/class/hwmon");
|
|
|
|
if (!dir)
|
|
|
|
{
|
|
|
|
init = 1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dh = readdir(dir)) != NULL)
|
|
|
|
{
|
|
|
|
if (dh->d_name[0] == '.') continue;
|
|
|
|
snprintf(buf, sizeof(buf), "/sys/class/hwmon/%s", dh->d_name);
|
|
|
|
char *link = realpath(buf, NULL);
|
|
|
|
if (!link) continue;
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/name", link);
|
|
|
|
char *b = file_contents(buf);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < sizeof(drivers) / sizeof(thermal_drv); i++)
|
|
|
|
{
|
|
|
|
if (!strncmp(b, drivers[i].name, strlen(drivers[i].name)))
|
|
|
|
{
|
|
|
|
snprintf(_hwmon_path, sizeof(_hwmon_path), "%s", link);
|
|
|
|
drivers[i].init();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(b);
|
|
|
|
}
|
|
|
|
free(link);
|
|
|
|
if (_hwmon_path[0]) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
init = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_hwmon_path[0]) return -1;
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
return _core_n_temperature_read(id);
|
2021-05-16 04:25:14 -07:00
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
static int init = 0;
|
|
|
|
|
|
|
|
if (!init)
|
|
|
|
{
|
|
|
|
memset(&_core_temps, 0, sizeof(_core_temps));
|
|
|
|
init = 1;
|
|
|
|
}
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
return _core_n_temperature_read(n);
|
2021-05-16 04:25:14 -07:00
|
|
|
#endif
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_temperature_min_max(int *min, int *max)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
|
|
|
|
*min = _cpu_temp_min;
|
|
|
|
*max = _cpu_temp_max;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
core_id_frequency(int id)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
int freq = -1;
|
|
|
|
FILE *f;
|
|
|
|
char buf[4096];
|
|
|
|
int tmp;
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", id);
|
2021-05-16 04:25:14 -07:00
|
|
|
f = fopen(buf, "r");
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
if (fgets(buf, sizeof(buf), f))
|
|
|
|
{
|
|
|
|
tmp = strtol(buf, NULL, 10);
|
|
|
|
if (!((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE))
|
|
|
|
freq = tmp;
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
if (freq != -1) return freq;
|
|
|
|
}
|
|
|
|
|
|
|
|
return freq;
|
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
2021-05-17 07:55:50 -07:00
|
|
|
return core_frequency();
|
2021-05-16 04:25:14 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_frequency_min_max(int *min, int *max)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
int freq_min = 0x7fffffff, freq_max = 0;
|
|
|
|
#if defined(__linux__)
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
s = file_contents("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq");
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
freq_min = atoi(s);
|
|
|
|
free(s);
|
|
|
|
s = file_contents("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
freq_max = atoi(s);
|
|
|
|
free(s);
|
|
|
|
*min = freq_min;
|
|
|
|
*max = freq_max;
|
|
|
|
if (freq_min < freq_max)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s = file_contents("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies");
|
|
|
|
if (!s) return -1;
|
|
|
|
|
|
|
|
char *t = strtok(s, " ");
|
|
|
|
while (t)
|
|
|
|
{
|
|
|
|
int freq = atoi(t);
|
|
|
|
if (freq != 0)
|
|
|
|
{
|
|
|
|
if (freq > freq_max) freq_max = freq;
|
|
|
|
if (freq < freq_min) freq_min = freq;
|
|
|
|
}
|
|
|
|
t = strtok(NULL, " ");
|
|
|
|
}
|
|
|
|
|
|
|
|
free(s);
|
|
|
|
|
|
|
|
if (freq_min == 0x7fffffff || freq_max == 0) return -1;
|
|
|
|
|
|
|
|
*min = freq_min;
|
|
|
|
*max = freq_max;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
char buf[4096];
|
|
|
|
size_t len = sizeof(buf);
|
|
|
|
char *t, *s;
|
|
|
|
|
|
|
|
if (sysctlbyname("dev.cpu.0.freq_levels", buf, &len, NULL, 0) != -1)
|
|
|
|
{
|
|
|
|
s = buf;
|
|
|
|
while (s)
|
|
|
|
{
|
|
|
|
t = strchr(s, '/');
|
|
|
|
if (!t) break;
|
|
|
|
*t = '\0';
|
|
|
|
int freq = atoi(s) * 1000;
|
|
|
|
if (freq > freq_max) freq_max = freq;
|
|
|
|
if (freq < freq_min) freq_min = freq;
|
|
|
|
|
|
|
|
s = strchr(t + 1, ' ');
|
|
|
|
}
|
|
|
|
if (freq_min == 0x7fffffff || freq_max == 0) return -1;
|
|
|
|
|
|
|
|
*min = freq_min;
|
|
|
|
*max = freq_max;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
*min = 0;
|
|
|
|
*max = 100;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
(void) freq_min; (void) freq_max;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_frequency(void)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
int freq = -1;
|
|
|
|
|
|
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
size_t len = sizeof(freq);
|
|
|
|
if (sysctlbyname("dev.cpu.0.freq", &freq, &len, NULL, 0) != -1)
|
|
|
|
freq *= 1000;
|
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
int mib[2] = { CTL_HW, HW_CPUSPEED };
|
|
|
|
size_t len = sizeof(freq);
|
|
|
|
if (sysctl(mib, 2, &freq, &len, NULL, 0) != -1)
|
|
|
|
freq *= 1000;
|
|
|
|
#elif defined(__linux__)
|
|
|
|
FILE *f;
|
|
|
|
char buf[4096];
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
if (fgets(buf, sizeof(buf), f))
|
|
|
|
{
|
|
|
|
tmp = strtol(buf, NULL, 10);
|
|
|
|
if (!((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE))
|
|
|
|
freq = tmp;
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
if (freq != -1) return freq;
|
|
|
|
}
|
|
|
|
|
|
|
|
f = fopen("/proc/cpuinfo", "r");
|
|
|
|
if (!f) return freq;
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof(buf), f))
|
|
|
|
{
|
|
|
|
if (!strncasecmp(buf, "cpu MHz", 7))
|
|
|
|
{
|
|
|
|
char *s = strchr(buf, ':') + 1;
|
|
|
|
tmp = strtol(s, NULL, 10);
|
|
|
|
if (!((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE))
|
|
|
|
freq = tmp * 1000;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
#else
|
|
|
|
|
|
|
|
#endif
|
|
|
|
return freq;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
2021-05-16 04:25:14 -07:00
|
|
|
short id;
|
|
|
|
short core_id;
|
|
|
|
} core_top_t;
|
|
|
|
|
|
|
|
static int
|
|
|
|
_cmp(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
core_top_t *aa = (core_top_t *) a;
|
|
|
|
core_top_t *bb = (core_top_t *) b;
|
|
|
|
|
|
|
|
if (aa->core_id == bb->core_id) return 0;
|
|
|
|
else if (aa->core_id < bb->core_id) return -1;
|
|
|
|
else return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_topology(Eina_List *cores)
|
2021-05-16 04:25:14 -07:00
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
char buf[4096];
|
2021-05-17 07:55:50 -07:00
|
|
|
int ncpu = eina_list_count(cores);
|
|
|
|
core_top_t *cores_top = malloc(ncpu * sizeof(core_top_t));
|
2021-05-16 04:25:14 -07:00
|
|
|
|
|
|
|
for (int i = 0; i < ncpu; i++)
|
|
|
|
{
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_top[i].id = i;
|
|
|
|
cores_top[i].core_id = i;
|
2021-05-16 04:25:14 -07:00
|
|
|
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/topology/core_id", i);
|
|
|
|
char *b = file_contents(buf);
|
|
|
|
if (b)
|
|
|
|
{
|
2021-05-17 07:55:50 -07:00
|
|
|
cores_top[i].core_id = atoi(b);
|
2021-05-16 04:25:14 -07:00
|
|
|
free(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-17 07:55:50 -07:00
|
|
|
qsort(cores_top, ncpu, sizeof(core_top_t), _cmp);
|
2021-05-16 04:25:14 -07:00
|
|
|
|
|
|
|
for (int i = 0; i < ncpu; i++)
|
|
|
|
{
|
2021-05-17 07:55:50 -07:00
|
|
|
Cpu_Core *core = eina_list_nth(cores, i);
|
|
|
|
core->top_id = cores_top[i].id;
|
2021-05-16 04:25:14 -07:00
|
|
|
}
|
2021-05-17 07:55:50 -07:00
|
|
|
free(cores_top);
|
2021-05-16 04:25:14 -07:00
|
|
|
#endif
|
|
|
|
}
|