mem.h (4749B)
1 /* 2 * Copyright © 2018, VideoLAN and dav1d authors 3 * Copyright © 2018, Two Orioles, LLC 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef DAV1D_SRC_MEM_H 29 #define DAV1D_SRC_MEM_H 30 31 #define TRACK_HEAP_ALLOCATIONS 0 32 33 #include <stdlib.h> 34 35 #if defined(_WIN32) || HAVE_MEMALIGN 36 #include <malloc.h> 37 #endif 38 39 #include "dav1d/dav1d.h" 40 41 #include "common/attributes.h" 42 43 #include "src/thread.h" 44 45 enum AllocationType { 46 ALLOC_BLOCK, 47 ALLOC_CDEF, 48 ALLOC_CDF, 49 ALLOC_COEF, 50 ALLOC_COMMON_CTX, 51 ALLOC_DAV1DDATA, 52 ALLOC_IPRED, 53 ALLOC_LF, 54 ALLOC_LR, 55 ALLOC_OBU_HDR, 56 ALLOC_OBU_META, 57 ALLOC_PAL, 58 ALLOC_PIC, 59 ALLOC_PIC_CTX, 60 ALLOC_REFMVS, 61 ALLOC_SEGMAP, 62 ALLOC_THREAD_CTX, 63 ALLOC_TILE, 64 N_ALLOC_TYPES, 65 }; 66 67 typedef struct Dav1dMemPoolBuffer { 68 void *data; 69 struct Dav1dMemPoolBuffer *next; 70 } Dav1dMemPoolBuffer; 71 72 typedef struct Dav1dMemPool { 73 pthread_mutex_t lock; 74 Dav1dMemPoolBuffer *buf; 75 int ref_cnt; 76 int end; 77 #if TRACK_HEAP_ALLOCATIONS 78 enum AllocationType type; 79 #endif 80 } Dav1dMemPool; 81 82 // TODO: Move this to a common location? 83 #define ROUND_UP(x,a) (((x)+((a)-1)) & ~((a)-1)) 84 85 /* 86 * Allocate align-byte aligned memory. The return value can be released 87 * by calling the dav1d_free_aligned() function. 88 */ 89 static inline void *dav1d_alloc_aligned_internal(const size_t sz, const size_t align) { 90 assert(!(align & (align - 1))); 91 #ifdef _WIN32 92 return _aligned_malloc(sz, align); 93 #elif HAVE_POSIX_MEMALIGN 94 void *ptr; 95 if (posix_memalign(&ptr, align, sz)) return NULL; 96 return ptr; 97 #elif HAVE_MEMALIGN 98 return memalign(align, sz); 99 #elif HAVE_ALIGNED_ALLOC 100 // The C11 standard specifies that the size parameter 101 // must be an integral multiple of alignment. 102 return aligned_alloc(align, ROUND_UP(sz, align)); 103 #else 104 void *const buf = malloc(sz + align + sizeof(void *)); 105 if (!buf) return NULL; 106 107 void *const ptr = (void *)(((uintptr_t)buf + sizeof(void *) + align - 1) & ~(align - 1)); 108 ((void **)ptr)[-1] = buf; 109 return ptr; 110 #endif 111 } 112 113 static inline void dav1d_free_aligned_internal(void *ptr) { 114 #ifdef _WIN32 115 _aligned_free(ptr); 116 #elif HAVE_POSIX_MEMALIGN || HAVE_MEMALIGN || HAVE_ALIGNED_ALLOC 117 free(ptr); 118 #else 119 if (ptr) free(((void **)ptr)[-1]); 120 #endif 121 } 122 123 #if TRACK_HEAP_ALLOCATIONS 124 void *dav1d_malloc(enum AllocationType type, size_t sz); 125 void *dav1d_realloc(enum AllocationType type, void *ptr, size_t sz); 126 void *dav1d_alloc_aligned(enum AllocationType type, size_t sz, size_t align); 127 void dav1d_free(void *ptr); 128 void dav1d_free_aligned(void *ptr); 129 void dav1d_log_alloc_stats(Dav1dContext *c); 130 #else 131 #define dav1d_mem_pool_init(type, pool) dav1d_mem_pool_init(pool) 132 #define dav1d_malloc(type, sz) malloc(sz) 133 #define dav1d_realloc(type, ptr, sz) realloc(ptr, sz) 134 #define dav1d_alloc_aligned(type, sz, align) dav1d_alloc_aligned_internal(sz, align) 135 #define dav1d_free(ptr) free(ptr) 136 #define dav1d_free_aligned(ptr) dav1d_free_aligned_internal(ptr) 137 #endif /* TRACK_HEAP_ALLOCATIONS */ 138 139 void dav1d_mem_pool_push(Dav1dMemPool *pool, Dav1dMemPoolBuffer *buf); 140 Dav1dMemPoolBuffer *dav1d_mem_pool_pop(Dav1dMemPool *pool, size_t size); 141 int dav1d_mem_pool_init(enum AllocationType type, Dav1dMemPool **pool); 142 void dav1d_mem_pool_end(Dav1dMemPool *pool); 143 144 static inline void dav1d_freep_aligned(void *ptr) { 145 void **mem = (void **) ptr; 146 if (*mem) { 147 dav1d_free_aligned(*mem); 148 *mem = NULL; 149 } 150 } 151 152 #endif /* DAV1D_SRC_MEM_H */