This is an automated email from Gerrit. "Richard Allen <rsa...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8605
-- gerrit commit 82ed9a0779f4e9bc874ec4626aa1c0af5ccaab8b Author: Richard Allen <rsa...@gmail.com> Date: Fri Nov 29 12:27:48 2024 -0600 target: malloc-free histogram Leverage presorted samples to generate gmon histogram without buffering entire histogram in memory. Change-Id: I38276dd1be011ce5781b0264b7cbb09a3aa1a2a2 Signed-off-by: Richard Allen <rsa...@gmail.com> diff --git a/src/target/target.c b/src/target/target.c index 894e8e8f85..59d7205e08 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4210,6 +4210,22 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms) { uint32_t i; + + /* trim out of address range samples */ + if (with_range) { + while (sample_num && samples[0] < start_address) { + sample_num--; + samples++; + } + while (sample_num && samples[sample_num - 1] > end_address) + sample_num--; + } + + if (!sample_num) { + LOG_WARNING("no samples to write"); + return; + } + FILE *f = fopen(filename, "wb"); if (!f) return; @@ -4223,33 +4239,19 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char write_data(f, &zero, 1); /* figure out bucket size */ - uint32_t min; - uint32_t max; - if (with_range) { - min = start_address; - max = end_address; - } else { - min = samples[0]; - max = samples[0]; - for (i = 0; i < sample_num; i++) { - if (min > samples[i]) - min = samples[i]; - if (max < samples[i]) - max = samples[i]; - } - - /* max should be (largest sample + 1) - * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + /* max should be (largest sample + 1) + * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + uint32_t min = samples[0]; + uint32_t max = samples[sample_num - 1]; + if (max < UINT32_MAX) + max++; + + /* gprof requires (max - min) >= 2 */ + while ((max - min) < 2) { if (max < UINT32_MAX) max++; - - /* gprof requires (max - min) >= 2 */ - while ((max - min) < 2) { - if (max < UINT32_MAX) - max++; - else - min--; - } + else + min--; } uint32_t address_space = max - min; @@ -4260,24 +4262,6 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char uint32_t num_buckets = address_space / sizeof(UNIT); if (num_buckets > max_buckets) num_buckets = max_buckets; - int *buckets = malloc(sizeof(int) * num_buckets); - if (!buckets) { - fclose(f); - return; - } - memset(buckets, 0, sizeof(int) * num_buckets); - for (i = 0; i < sample_num; i++) { - uint32_t address = samples[i]; - - if ((address < min) || (max <= address)) - continue; - - long long a = address - min; - long long b = num_buckets; - long long c = address_space; - int index_t = (a * b) / c; /* danger!!!! int32 overflows */ - buckets[index_t]++; - } /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ write_long(f, min, target); /* low_pc */ @@ -4291,22 +4275,19 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char write_string(f, "s"); /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ - - char *data = malloc(2 * num_buckets); - if (data) { - for (i = 0; i < num_buckets; i++) { - int val; - val = buckets[i]; - if (val > 65535) - val = 65535; - data[i * 2] = val&0xff; - data[i * 2 + 1] = (val >> 8) & 0xff; - } - free(buckets); - write_data(f, data, num_buckets * 2); - free(data); - } else - free(buckets); + uint32_t bidx; + for (i = 0, bidx = 0; bidx < num_buckets; ++bidx) { + int val = 0; + long long bmax = min + (long long)address_space * (bidx + 1) / num_buckets; + for ( ; i < sample_num && samples[i] < bmax; ++i) + if (val < 65535) + val++; + + uint8_t data[2]; + data[0] = val & 0xff; + data[1] = (val >> 8) & 0xff; + write_data(f, data, 2); + } fclose(f); } --