]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
many: use POINTER_MAY_BE_NULL in inner sort _cmp funcs
authorMichael Vogt <michael@amutable.com>
Sun, 29 Mar 2026 10:46:28 +0000 (12:46 +0200)
committerMichael Vogt <michael@amutable.com>
Tue, 31 Mar 2026 16:30:40 +0000 (18:30 +0200)
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.

src/basic/sort-util.c
src/basic/strv.c
src/core/job.c
src/shared/format-table.c

index 2859f14376ef0416e294c3845f3914f566599fa1..a76a6c85a8219bbffff834b0051b7a17282a1fd8 100644 (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);
 }
index 5e4d46bde4df201afb86f8dd5ea507821af0d383..4044a129c60e766e036fd91eb16f8a43a1741e5a 100644 (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);
 }
index 638e6e759e5b24a308e3c2407ba69b37f527e9be..7dd8a4617db263032f26ac9b4f52ad72f2008655 100644 (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);
 }
index eb1866e8d4a5d06a1e2c44809b966c01b2b1e47c..55e19ebd70f10f8271d3a027ecf4745e0eb9ee7b 100644 (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);