Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
mem_alloc.h
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18#ifndef DT_SYSTEM_MEM_ALLOC_H
19#define DT_SYSTEM_MEM_ALLOC_H
20
21/* Cacheline-aligned memory: alignment constants/attributes and the dt_alloc/dt_free
22 * family. Self-contained on purpose: low-level compute units include this instead of
23 * darktable.h. The pixelpipe-cache-tracked allocators
24 * (dt_pixelpipe_cache_alloc_*) are NOT here — they reference the darktable global and
25 * stay with the orchestrator. */
26
27#include "system/macros.h"
28
29#include <glib.h>
30#include <stdint.h>
31#include <stdlib.h>
32#include <string.h>
33
34#ifdef _WIN32
35#include <malloc.h> // _aligned_malloc / _aligned_free
36#endif
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42/* Helper to force stack vectors to be aligned on DT_CACHELINE_BYTES blocks to enable AVX2 */
43#define DT_IS_ALIGNED(x) __builtin_assume_aligned(x, DT_CACHELINE_BYTES)
44
45// Configure the size of a CPU cacheline in bytes, floats, and pixels. On most current architectures,
46// a cacheline contains 64 bytes, but Apple Silicon (M-series processors) uses 128-byte cache lines.
47#if defined(__APPLE__) && defined(__aarch64__)
48 #define DT_CACHELINE_BYTES 128
49 #define DT_CACHELINE_FLOATS 32
50 #define DT_CACHELINE_PIXELS 8
51#else
52 #define DT_CACHELINE_BYTES 64
53 #define DT_CACHELINE_FLOATS 16
54 #define DT_CACHELINE_PIXELS 4
55#endif /* __APPLE__ && __aarch64__ */
56
57// Helper to force heap vectors to be aligned on 64 byte blocks to enable AVX2
58// If this is applied to a struct member and the struct is allocated on the heap, then it must be allocated
59// on a 64 byte boundary to avoid crashes or undefined behavior because of unaligned memory access.
60#define DT_ALIGNED_ARRAY __attribute__((aligned(DT_CACHELINE_BYTES)))
61#define DT_ALIGNED_PIXEL __attribute__((aligned(16)))
62
63static inline gboolean dt_is_aligned(const void *pointer, size_t byte_count)
64{
65 return (uintptr_t)pointer % byte_count == 0;
66}
67
68static inline size_t dt_round_size(const size_t size, const size_t alignment)
69{
70 // Round the size of a buffer to the closest higher multiple
71 return ((size % alignment) == 0) ? size : ((size - 1) / alignment + 1) * alignment;
72}
73
74static inline size_t dt_round_size_sse(const size_t size)
75{
76 // Round the size of a buffer to the closest 64 higher multiple
77 return dt_round_size(size, 64);
78}
79
80static inline void *dt_alloc_align_internal(size_t size)
81{
82 const size_t alignment = DT_CACHELINE_BYTES;
83 const size_t aligned_size = dt_round_size(size, alignment);
84#if defined(__FreeBSD_version) && __FreeBSD_version < 700013
85 return malloc(aligned_size);
86#elif defined(_WIN32)
87 return _aligned_malloc(aligned_size, alignment);
88#else
89 void *ptr = NULL;
90 if(posix_memalign(&ptr, alignment, aligned_size)) return NULL;
91 return ptr;
92#endif
93}
94
95void *dt_alloc_align(size_t size);
96
97#define dt_free(ptr) \
98 if(!IS_NULL_PTR(ptr)) \
99 { \
100 g_free((void *)(ptr)); \
101 *(void **)(&(ptr)) = NULL; \
102 }
103
104static inline void dt_free_gpointer(gpointer ptr)
105{
106 g_free(ptr);
107 ptr = NULL;
108}
109
110#ifdef _WIN32
111 static inline void dt_free_align_ptr(void *mem)
112 {
113 _aligned_free(mem);
114 }
115#else
116 static inline void dt_free_align_ptr(void *mem)
117 {
118 dt_free(mem);
119 }
120#endif
121
122#define dt_free_align(ptr) \
123 if(!IS_NULL_PTR(ptr)) \
124 { \
125 dt_free_align_ptr((void *)(ptr)); \
126 *(void **)(&(ptr)) = NULL; \
127 }
128
129static inline void* dt_calloc_align(size_t size)
130{
131 void *buf = dt_alloc_align(size);
132 if(buf) memset(buf, 0, size);
133 return buf;
134}
135static inline float *dt_alloc_align_float(size_t pixels)
136{
137 return (float*)__builtin_assume_aligned(dt_alloc_align(pixels * sizeof(float)), DT_CACHELINE_BYTES);
138}
139static inline float *dt_calloc_align_float(size_t pixels)
140{
141 float *const buf = (float*)dt_alloc_align(pixels * sizeof(float));
142 if(buf) memset(buf, 0, pixels * sizeof(float));
143 return (float*)__builtin_assume_aligned(buf, DT_CACHELINE_BYTES);
144}
145static inline void * dt_check_sse_aligned(void * pointer)
146{
149 else
150 return NULL;
151}
152
159static inline void memset_zero(void *const buffer, size_t size)
160{
161 // Same as memset_s in C11. memset might be optimized away by compilers, this will not.
162 // Not parallelized or vectorized since it's applied only on "small" tiles.
163 for(size_t k = 0; k < size / sizeof(unsigned char); k++) {
164 unsigned char *const item = (unsigned char *const)buffer + k;
165 *item = 0;
166 }
167}
168
169#ifdef __cplusplus
170}
171#endif
172
173#endif // DT_SYSTEM_MEM_ALLOC_H
174
175// clang-format off
176// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
177// vim: shiftwidth=2 expandtab tabstop=2 cindent
178// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
179// clang-format on
float *const restrict const size_t k
static void memset_zero(void *const buffer, size_t size)
Set the memory buffer to zero as a pack of unsigned char.
Definition mem_alloc.h:159
static float * dt_calloc_align_float(size_t pixels)
Definition mem_alloc.h:139
static void * dt_calloc_align(size_t size)
Definition mem_alloc.h:129
static void dt_free_align_ptr(void *mem)
Definition mem_alloc.h:111
static float * dt_alloc_align_float(size_t pixels)
Definition mem_alloc.h:135
static size_t dt_round_size_sse(const size_t size)
Definition mem_alloc.h:74
static void * dt_check_sse_aligned(void *pointer)
Definition mem_alloc.h:145
static void * dt_alloc_align_internal(size_t size)
Definition mem_alloc.h:80
static void dt_free_gpointer(gpointer ptr)
Definition mem_alloc.h:104
void * dt_alloc_align(size_t size)
Definition darktable.c:508
#define dt_free(ptr)
Definition mem_alloc.h:97
static size_t dt_round_size(const size_t size, const size_t alignment)
Definition mem_alloc.h:68
static gboolean dt_is_aligned(const void *pointer, size_t byte_count)
Definition mem_alloc.h:63
#define DT_CACHELINE_BYTES
Definition mem_alloc.h:52
size_t size
Definition mipmap_cache.c:3