]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
macro: add generic IS_ALIGNED32() anf friends
authorLennart Poettering <lennart@poettering.net>
Wed, 7 Dec 2022 17:31:27 +0000 (18:31 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 8 Dec 2022 14:30:31 +0000 (15:30 +0100)
Let's generalize (and invert) the UNALIGNED32_P() macro from the sha256
code, and let's add a test for it.

src/fundamental/macro-fundamental.h
src/test/test-macro.c

index c11a5b15f46b790095ea7306e13dbfb022888c4f..65c9e042cd43a1c86098e87da7b743239be1d122 100644 (file)
@@ -327,14 +327,23 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
         return ((l + ali - 1) & ~(ali - 1));
 }
 
+#define ALIGN2(l) ALIGN_TO(l, 2)
 #define ALIGN4(l) ALIGN_TO(l, 4)
 #define ALIGN8(l) ALIGN_TO(l, 8)
+#define ALIGN2_PTR(p) ((void*) ALIGN2((uintptr_t) p))
+#define ALIGN4_PTR(p) ((void*) ALIGN4((uintptr_t) p))
+#define ALIGN8_PTR(p) ((void*) ALIGN8((uintptr_t) p))
 #ifndef SD_BOOT
 /* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
 #define ALIGN(l)  ALIGN_TO(l, sizeof(void*))
 #define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
 #endif
 
+/* Checks if the specified pointer is aligned as appropriate for the specific type */
+#define IS_ALIGNED16(p) (((uintptr_t) p) % __alignof__(uint16_t) == 0)
+#define IS_ALIGNED32(p) (((uintptr_t) p) % __alignof__(uint32_t) == 0)
+#define IS_ALIGNED64(p) (((uintptr_t) p) % __alignof__(uint64_t) == 0)
+
 /* Same as ALIGN_TO but callable in constant contexts. */
 #define CONST_ALIGN_TO(l, ali)                                         \
         __builtin_choose_expr(                                         \
index 001166d0dcce4c9d5fcf6e703ed0e6ba49034d65..d4f32496b7e71ddecae4b9958a379461a50f16e3 100644 (file)
@@ -531,4 +531,57 @@ TEST(ISPOWEROF2) {
         assert_se(!ISPOWEROF2(u));
 }
 
+TEST(ALIGNED) {
+        assert_se(IS_ALIGNED16(NULL));
+        assert_se(IS_ALIGNED32(NULL));
+        assert_se(IS_ALIGNED64(NULL));
+
+        uint64_t u64;
+        uint32_t u32;
+        uint16_t u16;
+
+        assert_se(IS_ALIGNED16(&u16));
+        assert_se(IS_ALIGNED16(&u32));
+        assert_se(IS_ALIGNED16(&u64));
+        assert_se(IS_ALIGNED32(&u32));
+        assert_se(IS_ALIGNED32(&u64));
+        assert_se(IS_ALIGNED64(&u64));
+
+        _align_(32) uint8_t ua256;
+        _align_(8) uint8_t ua64;
+        _align_(4) uint8_t ua32;
+        _align_(2) uint8_t ua16;
+
+        assert_se(IS_ALIGNED16(&ua256));
+        assert_se(IS_ALIGNED32(&ua256));
+        assert_se(IS_ALIGNED64(&ua256));
+
+        assert_se(IS_ALIGNED16(&ua64));
+        assert_se(IS_ALIGNED32(&ua64));
+        assert_se(IS_ALIGNED64(&ua64));
+
+        assert_se(IS_ALIGNED16(&ua32));
+        assert_se(IS_ALIGNED32(&ua32));
+
+        assert_se(IS_ALIGNED16(&ua16));
+
+#ifdef __x86_64__
+        /* Conditionalized on x86-64, since there we know for sure that all three types are aligned to
+         * their size. Too lazy to figure it out for other archs */
+        void *p = UINT_TO_PTR(1); /* definitely not aligned */
+        assert_se(!IS_ALIGNED16(p));
+        assert_se(!IS_ALIGNED32(p));
+        assert_se(!IS_ALIGNED64(p));
+
+        assert_se(IS_ALIGNED16(ALIGN2_PTR(p)));
+        assert_se(IS_ALIGNED32(ALIGN4_PTR(p)));
+        assert_se(IS_ALIGNED64(ALIGN8_PTR(p)));
+
+        p = UINT_TO_PTR(-1); /* also definitely not aligned */
+        assert_se(!IS_ALIGNED16(p));
+        assert_se(!IS_ALIGNED32(p));
+        assert_se(!IS_ALIGNED64(p));
+#endif
+}
+
 DEFINE_TEST_MAIN(LOG_INFO);