Fetch freq from cpuid, instead of asking Linux (using /proc). This finally removes udev dependency. However, the support of cpuid 0x16 is limited, so this may break cpufetch on some systems

This commit is contained in:
Dr-Noob
2020-06-20 13:24:50 +02:00
parent 04a2fef2a2
commit b81d611282
9 changed files with 111 additions and 156 deletions

View File

@@ -5,7 +5,17 @@
#define RED "\x1b[31;1m"
#define RESET "\x1b[0m"
void printError(const char *fmt, ...) {
void printErr(const char *fmt, ...) {
int buffer_size = 4096;
char buffer[buffer_size];
va_list args;
va_start(args, fmt);
vsnprintf(buffer,buffer_size, fmt, args);
va_end(args);
fprintf(stderr,RED "ERROR: "RESET "%s\n",buffer);
}
void printBug(const char *fmt, ...) {
int buffer_size = 4096;
char buffer[buffer_size];
va_list args;

View File

@@ -1,6 +1,7 @@
#ifndef __GLOBAL__
#define __GLOBAL__
void printError(const char *fmt, ...);
void printErr(const char *fmt, ...);
void printBug(const char *fmt, ...);
#endif

View File

@@ -3,7 +3,6 @@
#include "args.h"
#include "printer.h"
#include "standart.h"
#include "udev.h"
#include "extended.h"
#include "global.h"
@@ -25,7 +24,7 @@ Peak FLOPS: 512 GFLOP/s(in simple precision)
***/
static const char* VERSION = "0.4";
static const char* VERSION = "0.41";
void print_help(int argc, char *argv[]) {
printf("Usage: %s [--version] [--help] [--style STYLE]\n\
@@ -60,11 +59,11 @@ int main(int argc, char* argv[]) {
if(cpu == NULL)
return EXIT_FAILURE;
struct cache* cach = get_cache_info();
struct cache* cach = get_cache_info(cpu);
if(cach == NULL)
return EXIT_FAILURE;
struct frequency* freq = get_frequency_info();
struct frequency* freq = get_frequency_info(cpu);
if(freq == NULL)
return EXIT_FAILURE;

View File

@@ -67,7 +67,7 @@ struct ascii* set_ascii(VENDOR cpuVendor, STYLE style) {
/*** Check that number of lines of ascii art matches the number
of spaces plus the number of lines filled with text ***/
if(LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT != NUMBER_OF_LINES) {
printError("Number of lines do not match (%d vs %d)",LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT,NUMBER_OF_LINES);
printBug("Number of lines do not match (%d vs %d)",LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT,NUMBER_OF_LINES);
return NULL;
}
@@ -86,7 +86,7 @@ struct ascii* set_ascii(VENDOR cpuVendor, STYLE style) {
strcpy(art->color2,COL_INTEL_DARK_2);
break;
default:
printError("Found invalid style (%d)",style);
printBug("Found invalid style (%d)",style);
return NULL;
}
@@ -125,7 +125,7 @@ struct ascii* set_ascii(VENDOR cpuVendor, STYLE style) {
strcpy(art->color2,COL_AMD_DARK_2);
break;
default:
printError("Found invalid style (%d)",style);
printBug("Found invalid style (%d)",style);
return NULL;
}

View File

@@ -7,15 +7,21 @@
#include "standart.h"
#include "cpuid.h"
#include "udev.h"
#include "global.h"
#define STRING_YES "Yes"
#define STRING_NO "No"
#define VENDOR_INTEL_STRING "GenuineIntel"
#define VENDOR_AMD_STRING "AuthenticAMD"
#define STRING_YES "Yes"
#define STRING_NO "No"
#define STRING_UNKNOWN "Unknown"
#define STRING_NONE "None"
#define STRING_MEGAHERZ "MHz"
#define STRING_GIGAHERZ "GHz"
#define STRING_KILOBYTES "KB"
#define UNKNOWN -1
/*
* cpuid reference: http://www.sandpile.org/x86/cpuid.htm
*/
@@ -54,6 +60,11 @@ struct cache {
int L3;
};
struct frequency {
long base;
long max;
};
void init_cpu_info(struct cpuInfo* cpu) {
cpu->AVX = false;
cpu->AVX2 = false;
@@ -103,10 +114,10 @@ struct cpuInfo* get_cpu_info() {
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
init_cpu_info(cpu);
unsigned eax = 0;
unsigned ebx = 0;
unsigned ecx = 0;
unsigned edx = 0;
unsigned int eax = 0;
unsigned int ebx = 0;
unsigned int ecx = 0;
unsigned int edx = 0;
//Get max cpuid level
eax = 0x0000000;
@@ -187,7 +198,7 @@ struct cpuInfo* get_cpu_info() {
}
// see https://stackoverflow.com/questions/12594208/c-program-to-determine-levels-size-of-cache
struct cache* get_cache_info() {
struct cache* get_cache_info(struct cpuInfo* cpu) {
struct cache* cach = malloc(sizeof(struct cache));
unsigned int eax, ebx, ecx, edx;
@@ -217,7 +228,7 @@ struct cache* get_cache_info() {
switch (cache_type) {
case 1: // Data Cache (We assume this is L1d)
if(cache_level != 1) {
printError("Found data cache at level %d (expected 1)", cache_level);
printBug("Found data cache at level %d (expected 1)", cache_level);
return NULL;
}
cach->L1d = cache_total_size;
@@ -225,7 +236,7 @@ struct cache* get_cache_info() {
case 2: // Instruction Cache (We assume this is L1i)
if(cache_level != 1) {
printError("Found instruction cache at level %d (expected 1)", cache_level);
printBug("Found instruction cache at level %d (expected 1)", cache_level);
return NULL;
}
cach->L1i = cache_total_size;
@@ -235,13 +246,13 @@ struct cache* get_cache_info() {
if(cache_level == 2) cach->L2 = cache_total_size;
else if(cache_level == 3) cach->L3 = cache_total_size;
else {
printError("Found unified cache at level %d (expected == 2 or 3)", cache_level);
printBug("Found unified cache at level %d (expected == 2 or 3)", cache_level);
return NULL;
}
break;
default: // Unknown Type Cache
printError("Unknown Type Cache found at ID %d", i);
printBug("Unknown Type Cache found at ID %d", i);
return NULL;
}
}
@@ -250,6 +261,33 @@ struct cache* get_cache_info() {
return cach;
}
struct frequency* get_frequency_info(struct cpuInfo* cpu) {
struct frequency* freq = malloc(sizeof(struct frequency));
if(cpu->maxLevels < 0x16) {
printErr("Can't read frequency information from cpuid (needed level is %d, max is %d)", 0x16, cpu->maxLevels);
freq->base = UNKNOWN;
freq->max = UNKNOWN;
}
else {
unsigned int eax = 0x16;
unsigned int ebx = 0;
unsigned int ecx = 0;
unsigned int edx = 0;
cpuid(&eax, &ebx, &ecx, &edx);
freq->base = eax;
freq->max = ebx;
}
return freq;
}
long get_freq(struct frequency* freq) {
return freq->max;
}
VENDOR get_cpu_vendor(struct cpuInfo* cpu) {
return cpu->cpu_vendor;
}
@@ -274,13 +312,18 @@ void debug_cpu_info(struct cpuInfo* cpu) {
printf("SHA=%s\n", cpu->SHA ? "true" : "false");
}
void debugCache(struct cache* cach) {
void debug_cache(struct cache* cach) {
printf("L1i=%dB\n",cach->L1i);
printf("L1d=%dB\n",cach->L1d);
printf("L2=%dB\n",cach->L2);
printf("L3=%dB\n",cach->L3);
}
void debug_frequency(struct frequency* freq) {
printf("max f=%ldMhz\n",freq->max);
printf("base f=%ldMhz\n",freq->base);
}
/*** STRING FUNCTIONS ***/
char* get_str_peak_performance(struct cpuInfo* cpu, long freq) {
@@ -308,7 +351,7 @@ char* get_str_peak_performance(struct cpuInfo* cpu, long freq) {
return string;
}
float flops = (cpu->nThreads/cpu->HT)*freq*2;
float flops = (cpu->nThreads/cpu->HT)*(freq*1000000)*2;
if(cpu->FMA3 || cpu->FMA4)
flops = flops*2;
@@ -474,6 +517,24 @@ char* get_str_l3(struct cache* cach) {
}
}
char* get_str_freq(struct frequency* freq) {
//Max 3 digits and 3 for '(M/G)Hz' plus 1 for '\0'
unsigned int size = (4+3+1);
assert(strlen(STRING_UNKNOWN)+1 <= size);
char* string = malloc(sizeof(char)*size);
if(freq->max == UNKNOWN)
snprintf(string,strlen(STRING_UNKNOWN)+1,STRING_UNKNOWN);
else if(freq->max >= 1000)
snprintf(string,size,"%.2f"STRING_GIGAHERZ,(float)(freq->max)/1000);
else
snprintf(string,size,"%.2f"STRING_MEGAHERZ,(float)(freq->max));
return string;
}
void free_cache_struct(struct cache* cach) {
free(cach);
}
void free_freq_struct(struct frequency* freq) {
free(freq);
}

View File

@@ -6,13 +6,17 @@
#define VENDOR_AMD 2
#define VENDOR_INVALID 3
struct cpuInfo;
struct frequency;
struct cache;
typedef int VENDOR;
struct cache* get_cache_info();
struct cpuInfo* get_cpu_info();
VENDOR get_cpu_vendor(struct cpuInfo* cpu);
char* get_str_peak_performance(struct cpuInfo* cpu, long freq);
long get_freq(struct frequency* freq);
struct cache* get_cache_info(struct cpuInfo* cpu);
struct frequency* get_frequency_info(struct cpuInfo* cpu);
char* get_str_ncores(struct cpuInfo* cpu);
char* get_str_avx(struct cpuInfo* cpu);
@@ -25,10 +29,16 @@ char* get_str_l1(struct cache* cach);
char* get_str_l2(struct cache* cach);
char* get_str_l3(struct cache* cach);
char* get_str_freq(struct frequency* freq);
char* get_str_peak_performance(struct cpuInfo* cpu, long freq);
void free_cpuinfo_struct(struct cpuInfo* cpu);
void free_cache_struct(struct cache* cach);
void free_freq_struct(struct frequency* freq);
void debug_cpu_info(struct cpuInfo* cpu);
void debugCache(struct cache* cach);
void debug_cache(struct cache* cach);
void debug_frequency(struct frequency* freq);
#endif

View File

@@ -1,104 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "udev.h"
#define _PATH_SYS_SYSTEM "/sys/devices/system"
#define _PATH_SYS_CPU _PATH_SYS_SYSTEM"/cpu"
#define _PATH_ONE_CPU _PATH_SYS_CPU"/cpu0"
#define _PATH_FREQUENCY _PATH_ONE_CPU"/cpufreq"
#define _PATH_FREQUENCY_MAX _PATH_FREQUENCY"/cpuinfo_max_freq"
#define _PATH_FREQUENCY_MIN _PATH_FREQUENCY"/cpuinfo_min_freq"
struct frequency {
long max;
long min;
};
// Parses buf which should be expressed in the way: xxxxK where 'x' are numbers and 'K' refers to kilobytes.
// Returns the size as a int in bytes
int getSize(char* buf, int size) {
char* end = strstr (buf,"K");
if(end == NULL) {
printf("ERROR in getSize(strstr)\n");
return UNKNOWN;
}
*end = 0;
int cachsize = atoi(buf);
if(cachsize == 0) {
printf("ERROR in getSize(atoi)\n");
return UNKNOWN;
}
return cachsize;
}
// Returns CPU frequency in Hz
long get_freq_from_file(char* path) {
FILE *file = fopen(path, "r");
if(file == NULL) {
//Doest not exist
return UNKNOWN;
}
//File exists, read it
int fd = fileno(file);
int bytes_read = 0;
int offset = 0;
int block = 1;
char* buf = malloc(sizeof(char)*DEFAULT_FILE_SIZE);
memset(buf, 0, sizeof(char)*DEFAULT_FILE_SIZE);
while ( (bytes_read = read(fd, buf+offset, block)) > 0 ) {
offset += bytes_read;
}
int ret = atoi(buf);
free(buf);
if(ret == 0) {
printf("error in get_freq_from_file\n");
return UNKNOWN;
}
fclose(file);
return (long)ret*1000;
}
long get_freq(struct frequency* freq) {
return freq->max;
}
char* get_str_freq(struct frequency* freq) {
//Max 3 digits and 3 for '(M/G)Hz' plus 1 for '\0'
unsigned int size = (4+3+1);
assert(strlen(STRING_UNKNOWN)+1 <= size);
char* string = malloc(sizeof(char)*size);
if(freq->max == UNKNOWN)
snprintf(string,strlen(STRING_UNKNOWN)+1,STRING_UNKNOWN);
else if(freq->max >= 1000000000)
snprintf(string,size,"%.2f"STRING_GIGAHERZ,(float)(freq->max)/1000000000);
else
snprintf(string,size,"%.2f"STRING_MEGAHERZ,(float)(freq->max)/1000000);
return string;
}
struct frequency* get_frequency_info() {
struct frequency* freq = malloc(sizeof(struct frequency));
freq->max = get_freq_from_file(_PATH_FREQUENCY_MAX);
freq->min = get_freq_from_file(_PATH_FREQUENCY_MIN);
return freq;
}
void free_freq_struct(struct frequency* freq) {
free(freq);
}
void debugFrequency(struct frequency* freq) {
printf("max f=%ldMhz\n",freq->max);
printf("min f=%ldMhz\n",freq->min);
}

View File

@@ -1,22 +0,0 @@
#ifndef __UDEV__
#define __UDEV__
#define UNKNOWN -1
#define DEFAULT_FILE_SIZE 4096
#define DEFAULT_BLOCK_SIZE 128
#define STRING_UNKNOWN "Unknown"
#define STRING_NONE "None"
#define STRING_MEGAHERZ "MHz"
#define STRING_GIGAHERZ "GHz"
#define STRING_KILOBYTES "KB"
struct frequency* get_frequency_info();
void free_freq_struct(struct frequency* freq);
char* get_str_freq(struct frequency* freq);
long get_freq(struct frequency* freq);
void debugFrequency(struct frequency* freq);
#endif