perf tools: Add reallocarray_as_needed()
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 11 Jul 2022 09:32:06 +0000 (12:32 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 20 Jul 2022 14:08:37 +0000 (11:08 -0300)
Add helper reallocarray_as_needed() to reallocate an array to a larger
size and initialize the extra entries to an arbitrary value.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: kvm@vger.kernel.org
Link: https://lore.kernel.org/r/20220711093218.10967-24-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/util.c
tools/perf/util/util.h

index 9b02edf..391c1e9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/log2.h>
 #include <linux/time64.h>
+#include <linux/overflow.h>
 #include <unistd.h>
 #include "cap.h"
 #include "strlist.h"
@@ -500,3 +501,35 @@ char *filename_with_chroot(int pid, const char *filename)
 
        return new_name;
 }
+
+/*
+ * Reallocate an array *arr of size *arr_sz so that it is big enough to contain
+ * x elements of size msz, initializing new entries to *init_val or zero if
+ * init_val is NULL
+ */
+int do_realloc_array_as_needed(void **arr, size_t *arr_sz, size_t x, size_t msz, const void *init_val)
+{
+       size_t new_sz = *arr_sz;
+       void *new_arr;
+       size_t i;
+
+       if (!new_sz)
+               new_sz = msz >= 64 ? 1 : roundup(64, msz); /* Start with at least 64 bytes */
+       while (x >= new_sz) {
+               if (check_mul_overflow(new_sz, (size_t)2, &new_sz))
+                       return -ENOMEM;
+       }
+       if (new_sz == *arr_sz)
+               return 0;
+       new_arr = calloc(new_sz, msz);
+       if (!new_arr)
+               return -ENOMEM;
+       memcpy(new_arr, *arr, *arr_sz * msz);
+       if (init_val) {
+               for (i = *arr_sz; i < new_sz; i++)
+                       memcpy(new_arr + (i * msz), init_val, msz);
+       }
+       *arr = new_arr;
+       *arr_sz = new_sz;
+       return 0;
+}
index 0f78f1e..c1f2d42 100644 (file)
@@ -79,4 +79,19 @@ struct perf_debuginfod {
 void perf_debuginfod_setup(struct perf_debuginfod *di);
 
 char *filename_with_chroot(int pid, const char *filename);
+
+int do_realloc_array_as_needed(void **arr, size_t *arr_sz, size_t x,
+                              size_t msz, const void *init_val);
+
+#define realloc_array_as_needed(a, n, x, v) ({                 \
+       typeof(x) __x = (x);                                    \
+       __x >= (n) ?                                            \
+               do_realloc_array_as_needed((void **)&(a),       \
+                                          &(n),                \
+                                          __x,                 \
+                                          sizeof(*(a)),        \
+                                          (const void *)(v)) : \
+               0;                                              \
+       })
+
 #endif /* GIT_COMPAT_UTIL_H */