Commit 7a103a45 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Arjen Hiemstra

Linux/cpuinfo.c: grow buffer size as needed for 12+ core CPUs

Summary:
Getting CPU information starts with reading /proc/cpuinfo into a buffer; if that buffer is too small, then no information will be returned at all (updateCpuInfo() will return -1, so initCpuInfo() will return early); the consequence is that ksysguardd/ksysguard/plasmaengineexplorer won't know about "system/cores" or "cpu/system/AverageClock"; that in turn will make the "System Load Viewer" plasmoid completely dysfunctional (it won't show *any* data) because it relies on "system/cores" being available.

The buffer is currently 32KiB large, which is not enough on modern hardware (e.g. 12-core/24-thread systems exceed it). This patch lowers the initial size to 8KiB to be as memory-efficient as possible on low-end systems (dual/quadcore systems shouldn't ever need to grow it), and grows the buffer size as needed to accommodate arbitrarily many CPUs (tested on a 72-thread system, where the buffer grows four times, reaching 128KiB final size).

When the buffer needs to grow, its size is doubled, so the overall cost of the growth scales linearly with the file size (on average, each byte is copied to a larger buffer at most once). Also, the buffer size is remembered as long as the process runs, so the cost of the growth is only incurred once on startup (or if additional CPUs come online, which is probably rare).

I've verified locally that this patch fixes the issue: the System Log Viewer plasmoid shows data as expected afterwards.

BUG: 384515

Reviewers: davidedmundson, ahiemstra

Reviewed By: ahiemstra

Subscribers: ngraham, ahiemstra, cfeck, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D27362
parent 7d2382a9
......@@ -40,8 +40,9 @@ static int numCores = 0; /* Total # of cores */
static int HighNumCores = 0; /* Highest # of cores ever seen */
static float* Clocks = 0; /* Array with one entry per core */
#define CPUINFOBUFSIZE (32 * 1024)
static char CpuInfoBuf[ CPUINFOBUFSIZE ];
/* Enough for 4-6 virtual cores. Larger values will be tried as needed. */
static size_t CpuInfoBufSize = 8 * 1024;
static char* CpuInfoBuf = NULL;
static int Dirty = 0;
static struct SensorModul *CpuInfoSM;
......@@ -191,9 +192,12 @@ int updateCpuInfo( void )
return -1;
}
if ( CpuInfoBuf == NULL ) {
CpuInfoBuf = malloc( CpuInfoBufSize );
}
n = 0;
for(;;) {
ssize_t len = read( fd, CpuInfoBuf + n, CPUINFOBUFSIZE - 1 - n );
ssize_t len = read( fd, CpuInfoBuf + n, CpuInfoBufSize - 1 - n );
if( len < 0 ) {
print_error( "Failed to read file \'/proc/cpuinfo\'!\n" );
CpuInfoOK = -1;
......@@ -203,11 +207,14 @@ int updateCpuInfo( void )
n += len;
if( len == 0 ) /* reading finished */
break;
if( n == CPUINFOBUFSIZE - 1 ) {
log_error( "Internal buffer too small to read \'/proc/cpuinfo\'" );
CpuInfoOK = 0;
close( fd );
return -1;
if( n == CpuInfoBufSize - 1 ) {
/* The buffer was too small. Double its size and keep going. */
size_t new_size = CpuInfoBufSize * 2;
char* new_buffer = malloc( new_size );
memcpy( new_buffer, CpuInfoBuf, n ); /* copy read data */
free( CpuInfoBuf ); /* free old buffer */
CpuInfoBuf = new_buffer; /* remember new buffer and size */
CpuInfoBufSize = new_size;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment