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);
 }

-- 

Reply via email to