]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
macro: introduce several helper functions for alignment
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 18 Oct 2023 03:59:31 +0000 (12:59 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 19 Oct 2023 09:31:44 +0000 (18:31 +0900)
Some of them are not used in this commit, but will be used later.

src/basic/memory-util.h
src/fundamental/macro-fundamental.h
src/test/test-macro.c
src/test/test-memory-util.c

index b5e3984a09ae241656fea32c5c0f9865c3e8f33e..11795135f9d6f89091895b7de92e4b0be4df0113 100644 (file)
 #include "memory-util-fundamental.h"
 
 size_t page_size(void) _pure_;
-#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-#define PAGE_ALIGN_DOWN(l) ((l) & ~(page_size() - 1))
-#define PAGE_OFFSET(l) ((l) & (page_size() - 1))
+#define PAGE_ALIGN(l)          ALIGN_TO(l, page_size())
+#define PAGE_ALIGN_U64(l)      ALIGN_TO_U64(l, page_size())
+#define PAGE_ALIGN_DOWN(l)     ALIGN_DOWN(l, page_size())
+#define PAGE_ALIGN_DOWN_U64(l) ALIGN_DOWN_U64(l, page_size())
+#define PAGE_OFFSET(l)         ALIGN_OFFSET(l, page_size())
+#define PAGE_OFFSET_U64(l)     ALIGN_OFFSET_U64(l, page_size())
 
 /* Normal memcpy() requires src to be nonnull. We do nothing if n is 0. */
 static inline void *memcpy_safe(void *dst, const void *src, size_t n) {
index a311b01e30c4248e7f2d868dd43b5dfac880ce54..797330dd97d6cabb2da7fc30fcb9999afc3b804f 100644 (file)
@@ -379,6 +379,39 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
         return ((l + (ali - 1)) & ~(ali - 1));
 }
 
+static inline uint64_t ALIGN_TO_U64(uint64_t l, uint64_t ali) {
+        assert(ISPOWEROF2(ali));
+
+        if (l > UINT64_MAX - (ali - 1))
+                return UINT64_MAX; /* indicate overflow */
+
+        return ((l + (ali - 1)) & ~(ali - 1));
+}
+
+static inline size_t ALIGN_DOWN(size_t l, size_t ali) {
+        assert(ISPOWEROF2(ali));
+
+        return l & ~(ali - 1);
+}
+
+static inline uint64_t ALIGN_DOWN_U64(uint64_t l, uint64_t ali) {
+        assert(ISPOWEROF2(ali));
+
+        return l & ~(ali - 1);
+}
+
+static inline size_t ALIGN_OFFSET(size_t l, size_t ali) {
+        assert(ISPOWEROF2(ali));
+
+        return l & (ali - 1);
+}
+
+static inline uint64_t ALIGN_OFFSET_U64(uint64_t l, uint64_t ali) {
+        assert(ISPOWEROF2(ali));
+
+        return l & (ali - 1);
+}
+
 #define ALIGN2(l) ALIGN_TO(l, 2)
 #define ALIGN4(l) ALIGN_TO(l, 4)
 #define ALIGN8(l) ALIGN_TO(l, 8)
index 810ebc580e7acb0d97b43b78ffa2fd6cf652d96e..1b5ef9718e089ec047a1040f483e7fecd2f3dbef 100644 (file)
@@ -513,6 +513,34 @@ TEST(align_to) {
         assert_se(ALIGN_TO(SIZE_MAX-1, 4) == SIZE_MAX); /* overflow */
         assert_se(ALIGN_TO(SIZE_MAX, 4) == SIZE_MAX);   /* overflow */
 
+        assert_se(ALIGN_TO_U64(0, 1) == 0);
+        assert_se(ALIGN_TO_U64(1, 1) == 1);
+        assert_se(ALIGN_TO_U64(2, 1) == 2);
+        assert_se(ALIGN_TO_U64(3, 1) == 3);
+        assert_se(ALIGN_TO_U64(4, 1) == 4);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-1, 1) == UINT64_MAX-1);
+        assert_se(ALIGN_TO_U64(UINT64_MAX, 1) == UINT64_MAX);
+
+        assert_se(ALIGN_TO_U64(0, 2) == 0);
+        assert_se(ALIGN_TO_U64(1, 2) == 2);
+        assert_se(ALIGN_TO_U64(2, 2) == 2);
+        assert_se(ALIGN_TO_U64(3, 2) == 4);
+        assert_se(ALIGN_TO_U64(4, 2) == 4);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-3, 2) == UINT64_MAX-3);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-2, 2) == UINT64_MAX-1);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-1, 2) == UINT64_MAX-1);
+        assert_se(ALIGN_TO_U64(UINT64_MAX, 2) == UINT64_MAX); /* overflow */
+
+        assert_se(ALIGN_TO_U64(0, 4) == 0);
+        assert_se(ALIGN_TO_U64(1, 4) == 4);
+        assert_se(ALIGN_TO_U64(2, 4) == 4);
+        assert_se(ALIGN_TO_U64(3, 4) == 4);
+        assert_se(ALIGN_TO_U64(4, 4) == 4);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-3, 4) == UINT64_MAX-3);
+        assert_se(ALIGN_TO_U64(UINT64_MAX-2, 4) == UINT64_MAX); /* overflow */
+        assert_se(ALIGN_TO_U64(UINT64_MAX-1, 4) == UINT64_MAX); /* overflow */
+        assert_se(ALIGN_TO_U64(UINT64_MAX, 4) == UINT64_MAX);   /* overflow */
+
         assert_cc(CONST_ALIGN_TO(96, 512) == 512);
         assert_cc(CONST_ALIGN_TO(511, 512) == 512);
         assert_cc(CONST_ALIGN_TO(512, 512) == 512);
@@ -523,6 +551,106 @@ TEST(align_to) {
         assert_cc(__builtin_types_compatible_p(typeof(CONST_ALIGN_TO(SIZE_MAX, 512)), void));
 }
 
+TEST(align_down) {
+        assert_se(ALIGN_DOWN(0, 1) == 0);
+        assert_se(ALIGN_DOWN(1, 1) == 1);
+        assert_se(ALIGN_DOWN(2, 1) == 2);
+        assert_se(ALIGN_DOWN(3, 1) == 3);
+        assert_se(ALIGN_DOWN(4, 1) == 4);
+        assert_se(ALIGN_DOWN(SIZE_MAX-1, 1) == SIZE_MAX-1);
+        assert_se(ALIGN_DOWN(SIZE_MAX, 1) == SIZE_MAX);
+
+        assert_se(ALIGN_DOWN(0, 2) == 0);
+        assert_se(ALIGN_DOWN(1, 2) == 0);
+        assert_se(ALIGN_DOWN(2, 2) == 2);
+        assert_se(ALIGN_DOWN(3, 2) == 2);
+        assert_se(ALIGN_DOWN(4, 2) == 4);
+        assert_se(ALIGN_DOWN(SIZE_MAX-1, 2) == SIZE_MAX-1);
+        assert_se(ALIGN_DOWN(SIZE_MAX, 2) == SIZE_MAX-1);
+
+        assert_se(ALIGN_DOWN(0, 4) == 0);
+        assert_se(ALIGN_DOWN(1, 4) == 0);
+        assert_se(ALIGN_DOWN(2, 4) == 0);
+        assert_se(ALIGN_DOWN(3, 4) == 0);
+        assert_se(ALIGN_DOWN(4, 4) == 4);
+        assert_se(ALIGN_DOWN(SIZE_MAX-1, 4) == SIZE_MAX-3);
+        assert_se(ALIGN_DOWN(SIZE_MAX, 4) == SIZE_MAX-3);
+
+        assert_se(ALIGN_DOWN_U64(0, 1) == 0);
+        assert_se(ALIGN_DOWN_U64(1, 1) == 1);
+        assert_se(ALIGN_DOWN_U64(2, 1) == 2);
+        assert_se(ALIGN_DOWN_U64(3, 1) == 3);
+        assert_se(ALIGN_DOWN_U64(4, 1) == 4);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 1) == UINT64_MAX-1);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX, 1) == UINT64_MAX);
+
+        assert_se(ALIGN_DOWN_U64(0, 2) == 0);
+        assert_se(ALIGN_DOWN_U64(1, 2) == 0);
+        assert_se(ALIGN_DOWN_U64(2, 2) == 2);
+        assert_se(ALIGN_DOWN_U64(3, 2) == 2);
+        assert_se(ALIGN_DOWN_U64(4, 2) == 4);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 2) == UINT64_MAX-1);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX, 2) == UINT64_MAX-1);
+
+        assert_se(ALIGN_DOWN_U64(0, 4) == 0);
+        assert_se(ALIGN_DOWN_U64(1, 4) == 0);
+        assert_se(ALIGN_DOWN_U64(2, 4) == 0);
+        assert_se(ALIGN_DOWN_U64(3, 4) == 0);
+        assert_se(ALIGN_DOWN_U64(4, 4) == 4);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 4) == UINT64_MAX-3);
+        assert_se(ALIGN_DOWN_U64(UINT64_MAX, 4) == UINT64_MAX-3);
+}
+
+TEST(align_offset) {
+        assert_se(ALIGN_OFFSET(0, 1) == 0);
+        assert_se(ALIGN_OFFSET(1, 1) == 0);
+        assert_se(ALIGN_OFFSET(2, 1) == 0);
+        assert_se(ALIGN_OFFSET(3, 1) == 0);
+        assert_se(ALIGN_OFFSET(4, 1) == 0);
+        assert_se(ALIGN_OFFSET(SIZE_MAX-1, 1) == 0);
+        assert_se(ALIGN_OFFSET(SIZE_MAX, 1) == 0);
+
+        assert_se(ALIGN_OFFSET(0, 2) == 0);
+        assert_se(ALIGN_OFFSET(1, 2) == 1);
+        assert_se(ALIGN_OFFSET(2, 2) == 0);
+        assert_se(ALIGN_OFFSET(3, 2) == 1);
+        assert_se(ALIGN_OFFSET(4, 2) == 0);
+        assert_se(ALIGN_OFFSET(SIZE_MAX-1, 2) == 0);
+        assert_se(ALIGN_OFFSET(SIZE_MAX, 2) == 1);
+
+        assert_se(ALIGN_OFFSET(0, 4) == 0);
+        assert_se(ALIGN_OFFSET(1, 4) == 1);
+        assert_se(ALIGN_OFFSET(2, 4) == 2);
+        assert_se(ALIGN_OFFSET(3, 4) == 3);
+        assert_se(ALIGN_OFFSET(4, 4) == 0);
+        assert_se(ALIGN_OFFSET(SIZE_MAX-1, 4) == 2);
+        assert_se(ALIGN_OFFSET(SIZE_MAX, 4) == 3);
+
+        assert_se(ALIGN_OFFSET_U64(0, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(1, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(2, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(3, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(4, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 1) == 0);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 1) == 0);
+
+        assert_se(ALIGN_OFFSET_U64(0, 2) == 0);
+        assert_se(ALIGN_OFFSET_U64(1, 2) == 1);
+        assert_se(ALIGN_OFFSET_U64(2, 2) == 0);
+        assert_se(ALIGN_OFFSET_U64(3, 2) == 1);
+        assert_se(ALIGN_OFFSET_U64(4, 2) == 0);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 2) == 0);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 2) == 1);
+
+        assert_se(ALIGN_OFFSET_U64(0, 4) == 0);
+        assert_se(ALIGN_OFFSET_U64(1, 4) == 1);
+        assert_se(ALIGN_OFFSET_U64(2, 4) == 2);
+        assert_se(ALIGN_OFFSET_U64(3, 4) == 3);
+        assert_se(ALIGN_OFFSET_U64(4, 4) == 0);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 4) == 2);
+        assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 4) == 3);
+}
+
 TEST(flags) {
         enum {
                 F1 = 1 << 0,
index 2f8384ac09b26844d2e9a2c7957baa1eae0dcfb8..cd4b64ac164b4e6e8668640266705cfc1ced9285 100644 (file)
@@ -52,4 +52,74 @@ TEST(cleanup_array) {
         free(saved_iov);
 }
 
+TEST(page_align) {
+        assert_se(PAGE_ALIGN(page_size() - 1) == page_size());
+        assert_se(PAGE_ALIGN(page_size()    ) == page_size());
+        assert_se(PAGE_ALIGN(page_size() + 1) == page_size() * 2);
+        assert_se(PAGE_ALIGN(page_size() * 123 - 1) == page_size() * 123);
+        assert_se(PAGE_ALIGN(page_size() * 123    ) == page_size() * 123);
+        assert_se(PAGE_ALIGN(page_size() * 123 + 1) == page_size() * 124);
+        assert_se(PAGE_ALIGN(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN(SIZE_MAX - page_size()    ) == SIZE_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN(SIZE_MAX - page_size() + 2) == SIZE_MAX); /* overflow */
+        assert_se(PAGE_ALIGN(SIZE_MAX) == SIZE_MAX); /* overflow */
+
+        assert_se(PAGE_ALIGN_U64(page_size() - 1) == page_size());
+        assert_se(PAGE_ALIGN_U64(page_size()    ) == page_size());
+        assert_se(PAGE_ALIGN_U64(page_size() + 1) == page_size() * 2);
+        assert_se(PAGE_ALIGN_U64(page_size() * 123 - 1) == page_size() * 123);
+        assert_se(PAGE_ALIGN_U64(page_size() * 123    ) == page_size() * 123);
+        assert_se(PAGE_ALIGN_U64(page_size() * 123 + 1) == page_size() * 124);
+        assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() - 1) == UINT64_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size()    ) == UINT64_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() + 1) == UINT64_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() + 2) == UINT64_MAX); /* overflow */
+        assert_se(PAGE_ALIGN_U64(UINT64_MAX) == UINT64_MAX); /* overflow */
+
+        assert_se(PAGE_ALIGN_DOWN(page_size() - 1) == 0);
+        assert_se(PAGE_ALIGN_DOWN(page_size()    ) == page_size());
+        assert_se(PAGE_ALIGN_DOWN(page_size() + 1) == page_size());
+        assert_se(PAGE_ALIGN_DOWN(page_size() * 123 - 1) == page_size() * 122);
+        assert_se(PAGE_ALIGN_DOWN(page_size() * 123    ) == page_size() * 123);
+        assert_se(PAGE_ALIGN_DOWN(page_size() * 123 + 1) == page_size() * 123);
+        assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() * 2 + 1);
+        assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size()    ) == SIZE_MAX - page_size() * 2 + 1);
+        assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() + 2) == SIZE_MAX - page_size() + 1);
+
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size() - 1) == 0);
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size()    ) == page_size());
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size() + 1) == page_size());
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123 - 1) == page_size() * 122);
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123    ) == page_size() * 123);
+        assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123 + 1) == page_size() * 123);
+        assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() * 2 + 1);
+        assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size()    ) == SIZE_MAX - page_size() * 2 + 1);
+        assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+        assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() + 2) == SIZE_MAX - page_size() + 1);
+
+        assert_se(PAGE_OFFSET(page_size() - 1) == page_size() - 1);
+        assert_se(PAGE_OFFSET(page_size()    ) == 0);
+        assert_se(PAGE_OFFSET(page_size() + 1) == 1);
+        assert_se(PAGE_OFFSET(page_size() * 123 - 1) == page_size() - 1);
+        assert_se(PAGE_OFFSET(page_size() * 123    ) == 0);
+        assert_se(PAGE_OFFSET(page_size() * 123 + 1) == 1);
+        assert_se(PAGE_OFFSET(SIZE_MAX - page_size() - 1) == page_size() - 2);
+        assert_se(PAGE_OFFSET(SIZE_MAX - page_size()    ) == page_size() - 1);
+        assert_se(PAGE_OFFSET(SIZE_MAX - page_size() + 1) == 0);
+        assert_se(PAGE_OFFSET(SIZE_MAX - page_size() + 2) == 1);
+
+        assert_se(PAGE_OFFSET_U64(page_size() - 1) == page_size() - 1);
+        assert_se(PAGE_OFFSET_U64(page_size()    ) == 0);
+        assert_se(PAGE_OFFSET_U64(page_size() + 1) == 1);
+        assert_se(PAGE_OFFSET_U64(page_size() * 123 - 1) == page_size() - 1);
+        assert_se(PAGE_OFFSET_U64(page_size() * 123    ) == 0);
+        assert_se(PAGE_OFFSET_U64(page_size() * 123 + 1) == 1);
+        assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() - 1) == page_size() - 2);
+        assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size()    ) == page_size() - 1);
+        assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() + 1) == 0);
+        assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() + 2) == 1);
+}
+
 DEFINE_TEST_MAIN(LOG_INFO);