Change printing of maps to use qsort to order the output using a pointer
authorclaudio <claudio@openbsd.org>
Mon, 15 Nov 2021 14:57:57 +0000 (14:57 +0000)
committerclaudio <claudio@openbsd.org>
Mon, 15 Nov 2021 14:57:57 +0000 (14:57 +0000)
array. This replaces the current solution that only prints one element for
a certain value and not all elements with tha same value.
This can be further optimized but printing is not really a hot path in btrace.
OK mpi@

usr.sbin/btrace/map.c

index d2afab1..aff9b3a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: map.c,v 1.18 2021/11/12 16:57:24 claudio Exp $ */
+/*     $OpenBSD: map.c,v 1.19 2021/11/15 14:57:57 claudio Exp $ */
 
 /*
  * Copyright (c) 2020 Martin Pieuchot <mpi@openbsd.org>
@@ -49,13 +49,13 @@ struct mentry {
        struct bt_arg           *mval;
 };
 
-int             mcmp(struct mentry *, struct mentry *);
+int             mcmp(const struct mentry *, const struct mentry *);
 struct mentry  *mget(struct map *, const char *);
 
 RB_GENERATE(map, mentry, mlink, mcmp);
 
 int
-mcmp(struct mentry *me0, struct mentry *me1)
+mcmp(const struct mentry *me0, const struct mentry *me1)
 {
        return strncmp(me0->mkey, me1->mkey, KLEN - 1);
 }
@@ -183,35 +183,49 @@ map_insert(struct map *map, const char *key, struct bt_arg *bval,
        return map;
 }
 
+static int
+map_cmp(const void *a, const void *b)
+{
+       const struct mentry *ma = *(const struct mentry **)a;
+       const struct mentry *mb = *(const struct mentry **)b;
+       long rv;
+
+       rv = bacmp(ma->mval, mb->mval);
+       if (rv != 0)
+               return (rv > 0 ? -1 : 1);
+       return mcmp(ma, mb);
+}
+
 /* Print at most `top' entries of the map ordered by value. */
 void
 map_print(struct map *map, size_t top, const char *name)
 {
-       struct mentry *mep, *mcur;
-       struct bt_arg *bhigh, *bprev;
-       size_t i;
+       struct mentry **elms, *mep;
+       size_t i, count = 0;
 
        if (map == NULL)
                return;
 
-       bprev = &g_maxba;
-       for (i = 0; i < top; i++) {
-               mcur = NULL;
-               bhigh = &g_nullba;
-               RB_FOREACH(mep, map, map) {
-                       if (bacmp(mep->mval, bhigh) >= 0 &&
-                           bacmp(mep->mval, bprev) < 0 &&
-                           mep->mval != bprev) {
-                               mcur = mep;
-                               bhigh = mcur->mval;
-                       }
-               }
-               if (mcur == NULL)
-                       break;
-               printf("@%s[%s]: %s\n", name, mcur->mkey,
-                   ba2str(mcur->mval, NULL));
-               bprev = mcur->mval;
+       RB_FOREACH(mep, map, map)
+               count++;
+
+       elms = calloc(count, sizeof(*elms));
+       if (elms == NULL)
+               err(1, NULL);
+
+       count = 0;
+       RB_FOREACH(mep, map, map)
+               elms[count++] = mep;
+
+       qsort(elms, count, sizeof(*elms), map_cmp);
+
+       for (i = 0; i < top && i < count; i++) {
+               mep = elms[i];
+               printf("@%s[%s]: %s\n", name, mep->mkey,
+                   ba2str(mep->mval, NULL));
        }
+
+       free(elms);
 }
 
 void