diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2020-09-23 11:58:11 +0200 |
---|---|---|
committer | cgzones <cgzones@googlemail.com> | 2020-10-12 13:15:23 +0200 |
commit | 9f5b50edd78111a42b5824f3725794f8762326d2 (patch) | |
tree | b207995e874d37832ce5ebca271606c8fe93e633 /CPUMeter.c | |
parent | 0b9a0014989b8557eb16697984d9fd02b59bf47a (diff) |
CPUMeter: avoid crashes and leaks in case the CPU count changes
E.g. if the HT/SMT mode changes
Use separate data for sub-meters
Do not reuse drawData for maintainability
Diffstat (limited to 'CPUMeter.c')
-rw-r--r-- | CPUMeter.c | 57 |
1 files changed, 38 insertions, 19 deletions
@@ -27,6 +27,11 @@ static const int CPUMeter_attributes[] = { CPU_IOWAIT }; +typedef struct CPUMeterData_ { + int cpus; + Meter** meters; +} CPUMeterData; + static void CPUMeter_init(Meter* this) { int cpu = this->param; if (this->pl->cpuCount > 1) { @@ -42,6 +47,9 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, int size) { int cpu = this->param; if (cpu > this->pl->cpuCount) { xSnprintf(buffer, size, "absent"); + int items = this->curItems; + for (int i = 0; i < items; i++) + this->values[i] = 0; return; } memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT); @@ -119,7 +127,8 @@ static void CPUMeter_display(const Object* cast, RichString* out) { } static void AllCPUsMeter_getRange(Meter* this, int* start, int* count) { - int cpus = this->pl->cpuCount; + CPUMeterData* data = this->meterData; + int cpus = data->cpus; switch(Meter_name(this)[0]) { default: case 'A': // All @@ -139,9 +148,13 @@ static void AllCPUsMeter_getRange(Meter* this, int* start, int* count) { static void CPUMeterCommonInit(Meter *this, int ncol) { int cpus = this->pl->cpuCount; - if (!this->drawData) - this->drawData = xCalloc(cpus, sizeof(Meter*)); - Meter** meters = (Meter**) this->drawData; + CPUMeterData* data = this->meterData; + if (!data) { + data = this->meterData = xMalloc(sizeof(CPUMeterData)); + data->cpus = cpus; + data->meters = xCalloc(cpus, sizeof(Meter*)); + } + Meter** meters = data->meters; int start, count; AllCPUsMeter_getRange(this, &start, &count); for (int i = 0; i < count; i++) { @@ -156,7 +169,8 @@ static void CPUMeterCommonInit(Meter *this, int ncol) { } static void CPUMeterCommonUpdateMode(Meter* this, int mode, int ncol) { - Meter** meters = (Meter**) this->drawData; + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; this->mode = mode; int h = Meter_modes[mode]->h; int start, count; @@ -168,11 +182,14 @@ static void CPUMeterCommonUpdateMode(Meter* this, int mode, int ncol) { } static void AllCPUsMeter_done(Meter* this) { - Meter** meters = (Meter**) this->drawData; + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; int start, count; AllCPUsMeter_getRange(this, &start, &count); for (int i = 0; i < count; i++) Meter_delete((Object*)meters[i]); + free(data->meters); + free(data); } static void SingleColCPUsMeter_init(Meter* this) { @@ -208,18 +225,19 @@ static void OctoColCPUsMeter_updateMode(Meter* this, int mode) { } static void CPUMeterCommonDraw(Meter* this, int x, int y, int w, int ncol) { - Meter** meters = (Meter**) this->drawData; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - int colwidth = (w-ncol)/ncol + 1; - int diff = (w - (colwidth * ncol)); - int nrows = (count + ncol - 1) / ncol; - for (int i = 0; i < count; i++){ - int d = (i/nrows) > diff ? diff : (i / nrows) ; // dynamic spacer - int xpos = x + ((i / nrows) * colwidth) + d; - int ypos = y + ((i % nrows) * meters[0]->h); - meters[i]->draw(meters[i], xpos, ypos, colwidth); - } + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + int colwidth = (w-ncol)/ncol + 1; + int diff = (w - (colwidth * ncol)); + int nrows = (count + ncol - 1) / ncol; + for (int i = 0; i < count; i++){ + int d = (i/nrows) > diff ? diff : (i / nrows) ; // dynamic spacer + int xpos = x + ((i / nrows) * colwidth) + d; + int ypos = y + ((i % nrows) * meters[0]->h); + meters[i]->draw(meters[i], xpos, ypos, colwidth); + } } static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) { @@ -236,7 +254,8 @@ static void OctoColCPUsMeter_draw(Meter* this, int x, int y, int w) { static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) { - Meter** meters = (Meter**) this->drawData; + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; int start, count; AllCPUsMeter_getRange(this, &start, &count); for (int i = 0; i < count; i++) { |