| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* -*- c -*- */ | ||
| 2 | /* | ||
| 3 | * Copyright 2014 Free Software Foundation, Inc. | ||
| 4 | * | ||
| 5 | * This file is part of VOLK | ||
| 6 | * | ||
| 7 | * SPDX-License-Identifier: LGPL-3.0-or-later | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <stdio.h> | ||
| 11 | #include <stdlib.h> | ||
| 12 | #include <string.h> | ||
| 13 | |||
| 14 | #include <volk/volk_malloc.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * C11 features: | ||
| 18 | * see: https://en.cppreference.com/w/c/memory/aligned_alloc | ||
| 19 | * | ||
| 20 | * MSVC is broken | ||
| 21 | * see: | ||
| 22 | * https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=vs-2019 | ||
| 23 | * This section: | ||
| 24 | * C11 The Universal CRT implemented the parts of the | ||
| 25 | * C11 Standard Library that are required by C++17, | ||
| 26 | * with the exception of C99 strftime() E/O alternative | ||
| 27 | * conversion specifiers, C11 fopen() exclusive mode, | ||
| 28 | * and C11 aligned_alloc(). The latter is unlikely to | ||
| 29 | * be implemented, because C11 specified aligned_alloc() | ||
| 30 | * in a way that's incompatible with the Microsoft | ||
| 31 | * implementation of free(): | ||
| 32 | * namely, that free() must be able to handle highly aligned allocations. | ||
| 33 | * | ||
| 34 | * We must work around this problem because MSVC is non-compliant! | ||
| 35 | */ | ||
| 36 | |||
| 37 | |||
| 38 | 3536 | void* volk_malloc(size_t size, size_t alignment) | |
| 39 | { | ||
| 40 |
2/4✓ Branch 0 taken 3536 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3536 times.
|
3536 | if ((size == 0) || (alignment == 0)) { |
| 41 | ✗ | fprintf(stderr, "VOLK: Error allocating memory: either size or alignment is 0"); | |
| 42 | ✗ | return NULL; | |
| 43 | } | ||
| 44 | // Tweak size to satisfy ASAN (the GCC address sanitizer). | ||
| 45 | // Calling 'volk_malloc' might therefor result in the allocation of more memory than | ||
| 46 | // requested for correct alignment. Any allocation size change here will in general | ||
| 47 | // not impact the end result since initial size alignment is required either way. | ||
| 48 |
2/2✓ Branch 0 taken 2446 times.
✓ Branch 1 taken 1090 times.
|
3536 | if (size % alignment) { |
| 49 | 2446 | size += alignment - (size % alignment); | |
| 50 | } | ||
| 51 | #if HAVE_POSIX_MEMALIGN | ||
| 52 | // quoting posix_memalign() man page: | ||
| 53 | // "alignment must be a power of two and a multiple of sizeof(void *)" | ||
| 54 | // volk_get_alignment() could return 1 for some machines (e.g. generic_orc) | ||
| 55 | if (alignment == 1) { | ||
| 56 | return malloc(size); | ||
| 57 | } | ||
| 58 | void* ptr; | ||
| 59 | int err = posix_memalign(&ptr, alignment, size); | ||
| 60 | if (err != 0) { | ||
| 61 | ptr = NULL; | ||
| 62 | fprintf(stderr, | ||
| 63 | "VOLK: Error allocating memory " | ||
| 64 | "(posix_memalign: error %d: %s)\n", | ||
| 65 | err, | ||
| 66 | strerror(err)); | ||
| 67 | } | ||
| 68 | #elif defined(_MSC_VER) || defined(__MINGW32__) | ||
| 69 | void* ptr = _aligned_malloc(size, alignment); | ||
| 70 | #else | ||
| 71 | 3536 | void* ptr = aligned_alloc(alignment, size); | |
| 72 | #endif | ||
| 73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3536 times.
|
3536 | if (ptr == NULL) { |
| 74 | ✗ | fprintf(stderr, | |
| 75 | "VOLK: Error allocating memory (aligned_alloc/_aligned_malloc)\n"); | ||
| 76 | } | ||
| 77 | 3536 | return ptr; | |
| 78 | } | ||
| 79 | |||
| 80 | 3524 | void volk_free(void* ptr) | |
| 81 | { | ||
| 82 | #if defined(_MSC_VER) || defined(__MINGW32__) | ||
| 83 | _aligned_free(ptr); | ||
| 84 | #else | ||
| 85 | 3524 | free(ptr); | |
| 86 | #endif | ||
| 87 | 3524 | } | |
| 88 |