Blender  V2.93
BLI_memarena.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "MEM_guardedalloc.h"
36 
37 #include "BLI_asan.h"
38 #include "BLI_memarena.h"
39 #include "BLI_strict_flags.h"
40 #include "BLI_utildefines.h"
41 
42 #ifdef WITH_MEM_VALGRIND
43 # include "valgrind/memcheck.h"
44 #else
45 # define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) UNUSED_VARS(pool, rzB, is_zeroed)
46 # define VALGRIND_DESTROY_MEMPOOL(pool) UNUSED_VARS(pool)
47 # define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) UNUSED_VARS(pool, addr, size)
48 #endif
49 
50 struct MemBuf {
51  struct MemBuf *next;
52  uchar data[0];
53 };
54 
55 struct MemArena {
56  unsigned char *curbuf;
57  const char *name;
58  struct MemBuf *bufs;
59 
60  size_t bufsize, cursize;
61  size_t align;
62 
63  bool use_calloc;
64 };
65 
66 static void memarena_buf_free_all(struct MemBuf *mb)
67 {
68  while (mb != NULL) {
69  struct MemBuf *mb_next = mb->next;
70 
71  /* Unpoison memory because MEM_freeN might overwrite it. */
73 
74  MEM_freeN(mb);
75  mb = mb_next;
76  }
77 }
78 
79 MemArena *BLI_memarena_new(const size_t bufsize, const char *name)
80 {
81  MemArena *ma = MEM_callocN(sizeof(*ma), "memarena");
82  ma->bufsize = bufsize;
83  ma->align = 8;
84  ma->name = name;
85 
86  VALGRIND_CREATE_MEMPOOL(ma, 0, false);
87 
88  return ma;
89 }
90 
92 {
93  ma->use_calloc = 1;
94 }
95 
97 {
98  ma->use_calloc = 0;
99 }
100 
101 void BLI_memarena_use_align(struct MemArena *ma, const size_t align)
102 {
103  /* Align must be a power of two. */
104  BLI_assert((align & (align - 1)) == 0);
105 
106  ma->align = align;
107 }
108 
110 {
112 
114 
115  MEM_freeN(ma);
116 }
117 
119 #define PADUP(num, amt) (((num) + ((amt)-1)) & ~((amt)-1))
120 
123 {
124  unsigned char *tmp;
125 
126  tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align);
127  ma->cursize -= (size_t)(tmp - ma->curbuf);
128  ma->curbuf = tmp;
129 }
130 
131 void *BLI_memarena_alloc(MemArena *ma, size_t size)
132 {
133  void *ptr;
134 
135  /* Ensure proper alignment by rounding size up to multiple of 8. */
136  size = PADUP(size, ma->align);
137 
138  if (UNLIKELY(size > ma->cursize)) {
139  if (size > ma->bufsize - (ma->align - 1)) {
140  ma->cursize = PADUP(size + 1, ma->align);
141  }
142  else {
143  ma->cursize = ma->bufsize;
144  }
145 
146  struct MemBuf *mb = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(sizeof(*mb) + ma->cursize,
147  ma->name);
148  ma->curbuf = mb->data;
149  mb->next = ma->bufs;
150  ma->bufs = mb;
151 
152  BLI_asan_poison(ma->curbuf, ma->cursize);
153 
155  }
156 
157  ptr = ma->curbuf;
158  ma->curbuf += size;
159  ma->cursize -= size;
160 
162 
164 
165  return ptr;
166 }
167 
169 {
170  void *ptr;
171 
172  /* No need to use this function call if we're calloc'ing by default. */
173  BLI_assert(ma->use_calloc == false);
174 
175  ptr = BLI_memarena_alloc(ma, size);
176  memset(ptr, 0, size);
177 
178  return ptr;
179 }
180 
186 {
187  if (ma->bufs) {
188  unsigned char *curbuf_prev;
189  size_t curbuf_used;
190 
191  if (ma->bufs->next) {
193  ma->bufs->next = NULL;
194  }
195 
196  curbuf_prev = ma->curbuf;
197  ma->curbuf = ma->bufs->data;
199 
200  /* restore to original size */
201  curbuf_used = (size_t)(curbuf_prev - ma->curbuf);
202  ma->cursize += curbuf_used;
203 
204  if (ma->use_calloc) {
205  memset(ma->curbuf, 0, curbuf_used);
206  }
207  BLI_asan_poison(ma->curbuf, ma->cursize);
208  }
209 
211  VALGRIND_CREATE_MEMPOOL(ma, 0, false);
212 }
#define BLI_asan_unpoison(addr, size)
Definition: BLI_asan.h:42
#define BLI_asan_poison(addr, size)
Definition: BLI_asan.h:37
#define BLI_assert(a)
Definition: BLI_assert.h:58
static void memarena_curbuf_align(MemArena *ma)
Definition: BLI_memarena.c:122
void * BLI_memarena_calloc(MemArena *ma, size_t size)
Definition: BLI_memarena.c:168
#define PADUP(num, amt)
Definition: BLI_memarena.c:119
void BLI_memarena_use_calloc(MemArena *ma)
Definition: BLI_memarena.c:91
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)
Definition: BLI_memarena.c:47
MemArena * BLI_memarena_new(const size_t bufsize, const char *name)
Definition: BLI_memarena.c:79
void * BLI_memarena_alloc(MemArena *ma, size_t size)
Definition: BLI_memarena.c:131
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)
Definition: BLI_memarena.c:45
void BLI_memarena_use_malloc(MemArena *ma)
Definition: BLI_memarena.c:96
static void memarena_buf_free_all(struct MemBuf *mb)
Definition: BLI_memarena.c:66
#define VALGRIND_DESTROY_MEMPOOL(pool)
Definition: BLI_memarena.c:46
void BLI_memarena_free(MemArena *ma)
Definition: BLI_memarena.c:109
void BLI_memarena_use_align(struct MemArena *ma, const size_t align)
Definition: BLI_memarena.c:101
void BLI_memarena_clear(MemArena *ma)
Definition: BLI_memarena.c:185
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNLIKELY(x)
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:40
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
_W64 int intptr_t
Definition: stdint.h:121
unsigned char * curbuf
Definition: BLI_memarena.c:56
struct MemBuf * bufs
Definition: BLI_memarena.c:58
const char * name
Definition: BLI_memarena.c:57
size_t align
Definition: BLI_memarena.c:61
bool use_calloc
Definition: BLI_memarena.c:63
size_t cursize
Definition: BLI_memarena.c:60
size_t bufsize
Definition: BLI_memarena.c:60
uchar data[0]
Definition: BLI_memarena.c:52
struct MemBuf * next
Definition: BLI_memarena.c:51
PointerRNA * ptr
Definition: wm_files.c:3157