2021-02-18 22:25:36 +01:00
#include "fastfetch.h"
2021-04-09 14:07:05 +02:00
#include <string.h>
2021-04-15 18:59:26 +02:00
#define FF_CPU_MODULE_NAME "CPU"
2021-06-16 11:28:33 +02:00
#define FF_CPU_NUM_FORMAT_ARGS 14
2021-04-15 18:59:26 +02:00
2021-06-16 11:47:32 +02:00
static double parseHz ( FFstrbuf * content )
2021-03-28 13:02:40 +02:00
{
2021-06-16 11:28:33 +02:00
if ( content -> length == 0 )
2021-03-28 13:02:40 +02:00
return 0 ;
2021-06-16 11:47:32 +02:00
double herz ;
if ( sscanf ( content -> chars , "%lf" , & herz ) != 1 )
2021-03-28 13:02:40 +02:00
return 0 ;
2021-06-16 11:47:32 +02:00
return herz ;
2021-03-28 13:02:40 +02:00
}
2021-06-16 11:47:32 +02:00
static double getGhz ( const char * policyFile , const char * cpuFile )
2021-06-16 11:28:33 +02:00
{
FFstrbuf content ;
ffStrbufInit ( & content );
2021-06-16 11:47:32 +02:00
ffGetFileContent ( policyFile , & content );
if ( content . length == 0 )
ffGetFileContent ( cpuFile , & content );
double herz = parseHz ( & content );
2021-06-16 11:28:33 +02:00
ffStrbufDestroy ( & content );
2021-06-16 11:47:32 +02:00
herz /= 1000.0 ; //to MHz
return herz / 1000.0 ; //to GHz
2021-06-16 11:28:33 +02:00
}
2021-02-27 18:30:05 +01:00
void ffPrintCPU ( FFinstance * instance )
2021-02-18 22:25:36 +01:00
{
2021-04-15 18:59:26 +02:00
if ( ffPrintFromCache ( instance , FF_CPU_MODULE_NAME , & instance -> config . cpuKey , & instance -> config . cpuFormat , FF_CPU_NUM_FORMAT_ARGS ))
2021-02-22 16:52:51 +01:00
return ;
2021-04-03 21:51:50 +02:00
FILE * cpuinfo = fopen ( "/proc/cpuinfo" , "r" );
if ( cpuinfo == NULL )
{
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_CPU_MODULE_NAME , 0 , & instance -> config . cpuKey , & instance -> config . cpuFormat , FF_CPU_NUM_FORMAT_ARGS , "fopen( \" /proc/cpuinfo \" , \" r \" ) == NULL" );
2021-04-03 21:51:50 +02:00
return ;
}
2021-06-16 11:28:33 +02:00
FFstrbuf name ;
2021-11-17 10:59:31 +01:00
ffStrbufInitA ( & name , 64 );
2021-06-16 11:28:33 +02:00
FFstrbuf vendor ;
2021-11-17 10:59:31 +01:00
ffStrbufInitA ( & vendor , 64 );
2021-06-16 11:28:33 +02:00
FFstrbuf physicalCoresString ;
ffStrbufInit ( & physicalCoresString );
FFstrbuf procGhzString ;
ffStrbufInit ( & procGhzString );
2021-03-27 18:14:19 +01:00
2021-03-28 13:02:40 +02:00
char * line = NULL ;
size_t len = 0 ;
while ( getline ( & line , & len , cpuinfo ) != - 1 )
2021-02-19 16:23:41 +01:00
{
2021-03-28 13:02:40 +02:00
//Stop after the first CPU
2021-10-20 06:04:55 +00:00
if ( name . length > 0 && ( * line == '\0' || * line == '\n' ))
2021-03-28 13:02:40 +02:00
break ;
2021-10-20 06:04:55 +00:00
( void )(
ffGetPropValue ( line , "model name :" , & name ) ||
ffGetPropValue ( line , "vendor_id :" , & vendor ) ||
ffGetPropValue ( line , "cpu cores :" , & physicalCoresString ) ||
ffGetPropValue ( line , "cpu MHz :" , & procGhzString ) ||
( name . length == 0 && ffGetPropValue ( line , "Hardware :" , & name )) //For Android devices
);
2021-02-19 16:23:41 +01:00
}
2021-02-18 22:25:36 +01:00
2021-03-28 13:02:40 +02:00
if ( line != NULL )
free ( line );
fclose ( cpuinfo );
2021-06-16 11:47:32 +02:00
double procGhz = parseHz ( & procGhzString ) / 1000.0 ; //to GHz
2021-06-16 11:28:33 +02:00
ffStrbufDestroy ( & procGhzString );
2021-06-16 11:47:32 +02:00
double biosLimit = getGhz ( "/sys/devices/system/cpu/cpufreq/policy0/bios_limit" , "/sys/devices/system/cpu/cpu0/cpufreq/bios_limit" );
double scalingMaxFreq = getGhz ( "/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq" , "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" );
double scalingMinFreq = getGhz ( "/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq" , "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq" );
double infoMaxFreq = getGhz ( "/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq" , "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" );
double infoMinFreq = getGhz ( "/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq" , "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq" );
2021-02-18 22:25:36 +01:00
2021-03-28 13:02:40 +02:00
int numProcsOnline = get_nprocs ();
int numProcsAvailable = get_nprocs_conf ();
2021-03-19 20:57:07 +01:00
2021-06-16 11:28:33 +02:00
int physicalCores = 1 ;
sscanf ( physicalCoresString . chars , "%i" , & physicalCores );
ffStrbufDestroy ( & physicalCoresString );
2021-04-03 21:51:50 +02:00
//The current get_nprocs* returns 1 on failure. It also makes no sense to have a (1) as count
int numProcs = numProcsOnline ;
if ( numProcs <= 1 )
numProcs = numProcsAvailable ;
if ( numProcs <= 1 )
numProcs = physicalCores ;
double ghz = biosLimit ;
if ( ghz == 0 )
ghz = scalingMaxFreq ;
if ( ghz == 0 )
ghz = infoMaxFreq ;
2021-06-16 11:28:33 +02:00
if ( ghz == 0 )
ghz = procGhz ;
2021-04-03 21:51:50 +02:00
if ( ghz == 0 )
ghz = scalingMinFreq ;
if ( ghz == 0 )
ghz = infoMinFreq ;
if (
2021-06-16 11:28:33 +02:00
name . length == 0 &&
vendor . length == 0 &&
2021-04-03 21:51:50 +02:00
numProcs <= 1 &&
ghz <= 0
) {
2021-06-16 11:28:33 +02:00
ffStrbufDestroy ( & name );
ffStrbufDestroy ( & vendor );
2021-04-15 18:59:26 +02:00
ffPrintError ( instance , FF_CPU_MODULE_NAME , 0 , & instance -> config . cpuKey , & instance -> config . cpuFormat , FF_CPU_NUM_FORMAT_ARGS , "No CPU info found in /proc/cpuinfo" );
2021-04-03 21:51:50 +02:00
return ;
}
FFstrbuf namePretty ;
ffStrbufInitA ( & namePretty , 64 );
2021-06-16 11:28:33 +02:00
ffStrbufAppend ( & namePretty , & name );
2021-04-17 14:37:32 +02:00
const char * removeStrings [] = {
"(R)" , "(r)" , "(TM)" , "(tm)" ,
2021-05-02 21:45:47 +02:00
" CPU" , " FPU" , " APU" , " Processor" ,
2021-04-17 14:37:32 +02:00
" Dual-Core" , " Quad-Core" , " Six-Core" , " Eight-Core" , " Ten-Core" ,
" 2-Core" , " 4-Core" , " 6-Core" , " 8-Core" , " 10-Core" , " 12-Core" , " 14-Core" , " 16-Core"
};
ffStrbufRemoveStringsA ( & namePretty , sizeof ( removeStrings ) / sizeof ( removeStrings [ 0 ]), removeStrings );
2021-04-03 21:51:50 +02:00
ffStrbufSubstrBeforeFirstC ( & namePretty , '@' ); //Cut the speed output in the name as we append our own
ffStrbufTrimRight ( & namePretty , ' ' ); //If we removed the @ in previous step there was most likely a space before it
2021-04-03 12:14:25 +02:00
FFstrbuf cpu ;
ffStrbufInitA ( & cpu , 128 );
2021-03-19 20:57:07 +01:00
2021-04-15 18:59:26 +02:00
if ( namePretty . length > 0 )
ffStrbufAppend ( & cpu , & namePretty );
2021-06-16 11:28:33 +02:00
else if ( name . length > 0 )
ffStrbufAppend ( & cpu , & name );
else if ( vendor . length > 0 )
2021-03-19 20:57:07 +01:00
{
2021-06-16 11:28:33 +02:00
ffStrbufAppend ( & cpu , & vendor );
2022-01-09 16:51:57 +01:00
ffStrbufAppendS ( & cpu , " CPU" );
2021-03-19 20:57:07 +01:00
}
else
2022-01-09 16:51:57 +01:00
ffStrbufAppendS ( & cpu , "CPU" );
2021-04-15 18:59:26 +02:00
if ( numProcs > 1 )
ffStrbufAppendF ( & cpu , " (%i)" , numProcs );
if ( ghz > 0 )
ffStrbufAppendF ( & cpu , " @ %.9gGHz" , ghz );
ffPrintAndSaveToCache ( instance , FF_CPU_MODULE_NAME , & instance -> config . cpuKey , & cpu , & instance -> config . cpuFormat , FF_CPU_NUM_FORMAT_ARGS , ( FFformatarg []){
2021-06-16 11:28:33 +02:00
{ FF_FORMAT_ARG_TYPE_STRBUF , & name },
2021-04-15 18:59:26 +02:00
{ FF_FORMAT_ARG_TYPE_STRBUF , & namePretty },
2021-06-16 11:28:33 +02:00
{ FF_FORMAT_ARG_TYPE_STRBUF , & vendor },
2021-04-15 18:59:26 +02:00
{ FF_FORMAT_ARG_TYPE_INT , & numProcsOnline },
{ FF_FORMAT_ARG_TYPE_INT , & numProcsAvailable },
{ FF_FORMAT_ARG_TYPE_INT , & physicalCores },
{ FF_FORMAT_ARG_TYPE_INT , & numProcs },
2021-06-16 11:28:33 +02:00
{ FF_FORMAT_ARG_TYPE_DOUBLE , & biosLimit },
2021-04-15 18:59:26 +02:00
{ FF_FORMAT_ARG_TYPE_DOUBLE , & scalingMaxFreq },
{ FF_FORMAT_ARG_TYPE_DOUBLE , & scalingMinFreq },
{ FF_FORMAT_ARG_TYPE_DOUBLE , & infoMaxFreq },
{ FF_FORMAT_ARG_TYPE_DOUBLE , & infoMinFreq },
2021-06-16 11:28:33 +02:00
{ FF_FORMAT_ARG_TYPE_DOUBLE , & procGhz },
2021-04-15 18:59:26 +02:00
{ FF_FORMAT_ARG_TYPE_DOUBLE , & ghz }
});
2021-03-27 18:14:19 +01:00
2021-04-03 21:51:50 +02:00
ffStrbufDestroy ( & cpu );
2021-06-16 11:28:33 +02:00
ffStrbufDestroy ( & namePretty );
ffStrbufDestroy ( & name );
ffStrbufDestroy ( & vendor );
2021-03-27 18:14:19 +01:00
}