Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | // // aligned_alloc_test.c // libmalloc // // test allocating and freeing all sizes and alignments // #include <darwintest.h> #include <errno.h> #include <malloc/malloc.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true), T_META_TAG_XZONE); static inline void* t_aligned_alloc(size_t alignment, size_t size) { void *ptr = aligned_alloc(alignment, size); size_t allocated_size = malloc_size(ptr); T_QUIET; T_ASSERT_NOTNULL(ptr, "allocation"); T_QUIET; T_ASSERT_EQ((intptr_t)ptr % alignment, 0ul, "pointer should be properly aligned"); T_QUIET; T_EXPECT_LE(size, allocated_size, "allocation size"); // Scribble memory pointed to by `ptr` to make sure we're not using that // memory for control structures. This also makes sure the memory can be // written to. const uint64_t pat = 0xdeadbeefcafebabeull; memset_pattern8(ptr, &pat, size); return ptr; } T_DECL(aligned_alloc_free, "aligned_alloc all power of two alignments <= 64kb", T_META_TAG_VM_NOT_PREFERRED) { #if TARGET_OS_WATCH const size_t max_alignment = 4096; #else const size_t max_alignment = 64 * 1024; #endif // TARGET_OS_WATCH for (size_t alignment = sizeof(void*); alignment < max_alignment; alignment *= 2) { // test several sizes that are multiples of the alignment for (size_t size = alignment; size <= 256*alignment; size += alignment) { const int num_ptrs = 10; void *ptrs[num_ptrs]; for (int i = 0; i < num_ptrs; i++) { ptrs[i] = t_aligned_alloc(alignment, size); } for (int i = 0; i < num_ptrs; i++) { free(ptrs[i]); } } } } T_DECL(aligned_alloc_alignment_not_multiple_of_size, "aligned_alloc should set errno to EINVAL if size is not a multiple of alignment", T_META_TAG_VM_PREFERRED) { { void *ptr = aligned_alloc(8, 12); T_QUIET; T_ASSERT_NULL(ptr, "ptr should be null"); T_QUIET; T_ASSERT_EQ(errno, EINVAL, "errno should be EINVAL"); } { void *ptr = aligned_alloc(32, 16); T_QUIET; T_ASSERT_NULL(ptr, "ptr should be null"); T_QUIET; T_ASSERT_EQ(errno, EINVAL, "errno should be EINVAL"); } } T_DECL(aligned_alloc_alignment_not_power_of_two, "aligned_alloc should set errno to EINVAL if alignment is not a power of two (implementation constraint)", T_META_TAG_VM_PREFERRED) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-power-of-two-alignment" { void *ptr = aligned_alloc(24, 48); // alignment is even, but not a power of two T_QUIET; T_ASSERT_NULL(ptr, "ptr should be null"); T_QUIET; T_ASSERT_EQ(errno, EINVAL, "errno should be EINVAL"); } { void *ptr = aligned_alloc(23, 46); // alignment is odd, and not a power of two T_QUIET; T_ASSERT_NULL(ptr, "ptr should be null"); T_QUIET; T_ASSERT_EQ(errno, EINVAL, "errno should be EINVAL"); } #pragma GCC diagnostic pop } T_DECL(aligned_alloc_alignment_not_a_multiple_of_voidstar, "aligned_alloc should set errno to EINVAL if alignment is not a multiple of sizeof(void*) (implementation constraint)", T_META_TAG_VM_PREFERRED) { const size_t alignment = sizeof(void*)+1; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-power-of-two-alignment" void *ptr = aligned_alloc(alignment, alignment * 2); #pragma GCC diagnostic pop T_QUIET; T_ASSERT_NULL(ptr, "ptr should be null"); T_QUIET; T_ASSERT_EQ(errno, EINVAL, "aligned_alloc should set errno to EINVAL"); } |