On Wed, 16 Aug 2023 16:57:16 -0600 Ross Zwisler <zwisler@xxxxxxxxxx> wrote: > > +static int iter_custom_cmp(const void *A, const void *B, void *data) > > +{ > > + struct iter_custom_data *cust_data = data; > > + struct traceeval_iterator *iter = cust_data->iter; > > + struct traceeval *teval = iter->teval; > > + const struct entry *a = *((const struct entry **)A); > > + const struct entry *b = *((const struct entry **)B); > > + > > + return cust_data->sort_fn(teval, a->keys, a->vals, b->keys, b->vals, > > + cust_data->data); > > +} > > + > > +int traceeval_iterator_sort_custom(struct traceeval_iterator *iter, > > + traceeval_cmp_fn sort_fn, void *data) > > +{ > > + struct iter_custom_data cust_data = { > > + .iter = iter, > > + .sort_fn = sort_fn, > > + .data = data > > + }; > > + > > + qsort_r(iter->entries, iter->nr_entries, sizeof(*iter->entries), > > + iter_custom_cmp, &cust_data); > > I guess I don't yet see what this gives us over the existing sorting and > iterators? Does this do the same thing, we just pass in the sort function > instead of calling traceeval_iterator_sort() one or more times? This should be used in replace of the other sorting. It allows the user to make a complex sort. If you look at the last patch, the sample uses this: +/* + * Sort all the processes by the RUNNING state. + * If A and B have the same COMM, then sort by state. + * else + * Find the RUNNNIG state for A and B + * If the RUNNING state does not exist, it's considered -1 + * If RUNNING is equal, then sort by COMM. + */ +static int compare_pdata(struct traceeval *teval_data, + const union traceeval_data *Akeys, + const union traceeval_data *Avals, + const union traceeval_data *Bkeys, + const union traceeval_data *Bvals, + void *data) +{ + struct traceeval *teval = data; /* The deltas are here */ + union traceeval_data keysA[] = { + { .cstring = Akeys[0].cstring }, { .number = RUNNING } }; + union traceeval_data keysB[] = { + { .cstring = Bkeys[0].cstring }, { .number = RUNNING } }; + struct traceeval_stat *statA; + struct traceeval_stat *statB; + unsigned long long totalA = -1; + unsigned long long totalB = -1; + + /* First check if we are on the same task */ + if (strcmp(Akeys[0].cstring, Bkeys[0].cstring) == 0) { + /* Sort decending */ + if (Bkeys[1].number > Akeys[1].number) + return -1; + return Bkeys[1].number != Akeys[1].number; + } + + /* Get the RUNNING values for both processes */ + statA = traceeval_stat(teval, keysA, &delta_vals[0]); + if (statA) + totalA = traceeval_stat_total(statA); + + statB = traceeval_stat(teval, keysB, &delta_vals[0]); + if (statB) + totalB = traceeval_stat_total(statB); + + if (totalB < totalA) + return -1; + if (totalB > totalA) + return 1; + + return strcmp(Bkeys[0].cstring, Akeys[0].cstring); +} > > > + > > + iter->needs_sort = false; > > Also probably need to set > iter->next = 0; So much for redundancy! Thanks, -- Steve > > > + return 0; > > +} > > +