many: use POINTER_MAY_BE_NULL in inner sort _cmp funcs

Some functions are in the hot path of a sort. While it is more
correct to also use assert() here for the passed pointers it is
also a runtime cost that should never be needed when e.g. qsort()
is used as it will always pass non-NULL pointers.

So for these critical functions use POINTER_MAY_BE_NULL() which
is compiled out and add a comment to them. Not all _compare()
functions are changed, it was a bit of a judgement call because
some (like ether_addr_compare) are not called with that much data.

But happy to get advise here and tweak accordingly.
This commit is contained in:
Michael Vogt
2026-03-31 18:30:40 +02:00
parent 18e70eec2f
commit bb94af45c1
4 changed files with 20 additions and 12 deletions
+8 -4
View File
@@ -65,15 +65,19 @@ void qsort_r_safe(void *base, size_t nmemb, size_t size, comparison_userdata_fn_
}
int cmp_int(const int *a, const int *b) {
assert(a);
assert(b);
/* This is called from qsort()s inner loops. Correctly implemented qsort will never pass NULL so we
just suppress the check via POINTER_MAY_BE_NULL instead of assert() to avoid the runtime cost. */
POINTER_MAY_BE_NULL(a);
POINTER_MAY_BE_NULL(b);
return CMP(*a, *b);
}
int cmp_uint16(const uint16_t *a, const uint16_t *b) {
assert(a);
assert(b);
/* This is called from qsort()s inner loops. Correctly implemented qsort will never pass NULL so we
just suppress the check via POINTER_MAY_BE_NULL instead of assert() to avoid the runtime cost. */
POINTER_MAY_BE_NULL(a);
POINTER_MAY_BE_NULL(b);
return CMP(*a, *b);
}
+4 -2
View File
@@ -844,8 +844,10 @@ bool strv_overlap(char * const *a, char * const *b) {
}
static int str_compare(char * const *a, char * const *b) {
assert(a);
assert(b);
/* This is called from qsort()s inner loops. Correctly implemented qsort will never pass NULL so we
just suppress the check via POINTER_MAY_BE_NULL instead of assert() to avoid the runtime cost. */
POINTER_MAY_BE_NULL(a);
POINTER_MAY_BE_NULL(b);
return strcmp(*a, *b);
}
+4 -4
View File
@@ -1525,10 +1525,10 @@ void job_add_to_gc_queue(Job *j) {
}
static int job_compare_id(Job * const *a, Job * const *b) {
assert(a);
assert(b);
assert(*a);
assert(*b);
/* This is called from qsort()s inner loops. Correctly implemented qsort will never pass NULL so we
just suppress the check via POINTER_MAY_BE_NULL instead of assert() to avoid the runtime cost. */
POINTER_MAY_BE_NULL(a);
POINTER_MAY_BE_NULL(b);
return CMP((*a)->id, (*b)->id);
}
+4 -2
View File
@@ -1543,8 +1543,10 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
static int table_data_compare(const size_t *a, const size_t *b, Table *t) {
int r;
assert(a);
assert(b);
/* This is called from qsort()s inner loops. Correctly implemented qsort will never pass NULL so we
just suppress the check via POINTER_MAY_BE_NULL instead of assert() to avoid the runtime cost. */
POINTER_MAY_BE_NULL(a);
POINTER_MAY_BE_NULL(b);
assert(t);
assert(t->sort_map);