From 925a5adafed2d17c4f2c50460d4e571ca509f54e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Dec 2022 18:31:27 +0100 Subject: [PATCH] macro: add generic IS_ALIGNED32() anf friends Let's generalize (and invert) the UNALIGNED32_P() macro from the sha256 code, and let's add a test for it. (cherry picked from commit 4f07388360a3513b9fc8d2773568b8def941f4a4) Related: RHEL-16952 --- src/fundamental/macro-fundamental.h | 9 +++++ src/test/test-macro.c | 53 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index e0665d9dcb..dd0de328cb 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -334,14 +334,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( \ diff --git a/src/test/test-macro.c b/src/test/test-macro.c index bb79ea0dbe..a1618c3105 100644 --- a/src/test/test-macro.c +++ b/src/test/test-macro.c @@ -755,4 +755,57 @@ TEST(FOREACH_ARRAY) { assert_se(n == 0); } +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);