Blender V4.3
BLI_mempool.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
17#include <stdlib.h>
18#include <string.h>
19
20#include "atomic_ops.h"
21
22#include "BLI_utildefines.h"
23
24#include "BLI_asan.h"
25#include "BLI_mempool.h" /* own include */
26#include "BLI_mempool_private.h" /* own include */
27
28#ifdef WITH_ASAN
29# include "BLI_threads.h"
30#endif
31
32#include "MEM_guardedalloc.h"
33
34#ifdef WITH_MEM_VALGRIND
35# include "valgrind/memcheck.h"
36#endif
37
38#include "BLI_strict_flags.h" /* Keep last. */
39
40#ifdef WITH_ASAN
41# define POISON_REDZONE_SIZE 32
42#else
43# define POISON_REDZONE_SIZE 0
44#endif
45
46/* NOTE: copied from BLO_blend_defs.hh, don't use here because we're in BLI. */
47#ifdef __BIG_ENDIAN__
48/* Big Endian */
49# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
50# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
51 ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \
52 (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h))
53#else
54/* Little Endian */
55# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
56# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
57 ((int64_t)(h) << 56 | (int64_t)(g) << 48 | (int64_t)(f) << 40 | (int64_t)(e) << 32 | \
58 (int64_t)(d) << 24 | (int64_t)(c) << 16 | (int64_t)(b) << 8 | (a))
59#endif
60
67#define FREEWORD \
68 ((sizeof(void *) > sizeof(int32_t)) ? MAKE_ID_8('e', 'e', 'r', 'f', 'f', 'r', 'e', 'e') : \
69 MAKE_ID('e', 'f', 'f', 'e'))
70
74#define USEDWORD MAKE_ID('u', 's', 'e', 'd')
75
76/* optimize pool size */
77#define USE_CHUNK_POW2
78
79#ifndef NDEBUG
80static bool mempool_debug_memset = false;
81#endif
82
94
102
132
133#define MEMPOOL_ELEM_SIZE_MIN (sizeof(void *) * 2)
134
135#define CHUNK_DATA(chunk) (CHECK_TYPE_INLINE(chunk, BLI_mempool_chunk *), (void *)((chunk) + 1))
136
137#define NODE_STEP_NEXT(node) ((void *)((char *)(node) + esize))
138#define NODE_STEP_PREV(node) ((void *)((char *)(node)-esize))
139
141#define CHUNK_OVERHEAD (uint)(MEM_SIZE_OVERHEAD + sizeof(BLI_mempool_chunk))
142
144{
145#ifdef WITH_ASAN
146 BLI_mutex_unlock(&pool->mutex);
147#else
148 UNUSED_VARS(pool);
149#endif
150}
151
153{
154#ifdef WITH_ASAN
155 BLI_mutex_lock(&pool->mutex);
156#else
157 UNUSED_VARS(pool);
158#endif
159}
160
161#ifdef USE_CHUNK_POW2
163{
164 x -= 1;
165 x = x | (x >> 1);
166 x = x | (x >> 2);
167 x = x | (x >> 4);
168 x = x | (x >> 8);
169 x = x | (x >> 16);
170 return x + 1;
171}
172#endif
173
175{
176 while (index-- && head) {
177 head = head->next;
178 }
179 return head;
180}
181
188BLI_INLINE uint mempool_maxchunks(const uint elem_num, const uint pchunk)
189{
190 return (elem_num <= pchunk) ? 1 : ((elem_num / pchunk) + 1);
191}
192
194{
195 return MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "mempool chunk");
196}
197
208 BLI_mempool_chunk *mpchunk,
209 BLI_freenode *last_tail)
210{
211 const uint esize = pool->esize;
212 BLI_freenode *curnode = CHUNK_DATA(mpchunk);
213 uint j;
214
215 /* append */
216 if (pool->chunk_tail) {
217 pool->chunk_tail->next = mpchunk;
218 }
219 else {
220 BLI_assert(pool->chunks == NULL);
221 pool->chunks = mpchunk;
222 }
223
224 mpchunk->next = NULL;
225 pool->chunk_tail = mpchunk;
226
227 if (UNLIKELY(pool->free == NULL)) {
228 pool->free = curnode;
229 }
230
231 /* loop through the allocated data, building the pointer structures */
232 j = pool->pchunk;
233 if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
234 while (j--) {
236
237 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
238#ifdef WITH_MEM_VALGRIND
239 VALGRIND_MAKE_MEM_DEFINED(curnode, pool->esize - POISON_REDZONE_SIZE);
240#endif
241 curnode->next = next = NODE_STEP_NEXT(curnode);
242 curnode->freeword = FREEWORD;
243
244 BLI_asan_poison(curnode, pool->esize);
245#ifdef WITH_MEM_VALGRIND
246 VALGRIND_MAKE_MEM_UNDEFINED(curnode, pool->esize);
247#endif
248 curnode = next;
249 }
250 }
251 else {
252 while (j--) {
254
255 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
256#ifdef WITH_MEM_VALGRIND
257 VALGRIND_MAKE_MEM_DEFINED(curnode, pool->esize - POISON_REDZONE_SIZE);
258#endif
259 curnode->next = next = NODE_STEP_NEXT(curnode);
260 BLI_asan_poison(curnode, pool->esize);
261#ifdef WITH_MEM_VALGRIND
262 VALGRIND_MAKE_MEM_UNDEFINED(curnode, pool->esize);
263#endif
264
265 curnode = next;
266 }
267 }
268
269 /* terminate the list (rewind one)
270 * will be overwritten if 'curnode' gets passed in again as 'last_tail' */
271
272 if (POISON_REDZONE_SIZE > 0) {
273 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
274 BLI_asan_poison(curnode, pool->esize);
275#ifdef WITH_MEM_VALGRIND
276 VALGRIND_MAKE_MEM_DEFINED(curnode, pool->esize - POISON_REDZONE_SIZE);
277 VALGRIND_MAKE_MEM_UNDEFINED(curnode, pool->esize);
278#endif
279 }
280
281 curnode = NODE_STEP_PREV(curnode);
282
283 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
284#ifdef WITH_MEM_VALGRIND
285 VALGRIND_MAKE_MEM_DEFINED(curnode, pool->esize - POISON_REDZONE_SIZE);
286#endif
287
288 curnode->next = NULL;
289 BLI_asan_poison(curnode, pool->esize);
290#ifdef WITH_MEM_VALGRIND
291 VALGRIND_MAKE_MEM_UNDEFINED(curnode, pool->esize);
292#endif
293
294 /* final pointer in the previously allocated chunk is wrong */
295 if (last_tail) {
296 BLI_asan_unpoison(last_tail, pool->esize - POISON_REDZONE_SIZE);
297#ifdef WITH_MEM_VALGRIND
298 VALGRIND_MAKE_MEM_DEFINED(last_tail, pool->esize - POISON_REDZONE_SIZE);
299#endif
300 last_tail->next = CHUNK_DATA(mpchunk);
301 BLI_asan_poison(last_tail, pool->esize);
302#ifdef WITH_MEM_VALGRIND
303 VALGRIND_MAKE_MEM_UNDEFINED(last_tail, pool->esize);
304#endif
305 }
306
307 return curnode;
308}
309
311{
312#ifdef WITH_ASAN
313 BLI_asan_unpoison(mpchunk, sizeof(BLI_mempool_chunk) + pool->esize * pool->csize);
314#else
315 UNUSED_VARS(pool);
316#endif
317#ifdef WITH_MEM_VALGRIND
318 VALGRIND_MAKE_MEM_DEFINED(mpchunk, sizeof(BLI_mempool_chunk) + pool->esize * pool->csize);
319#endif
320 MEM_freeN(mpchunk);
321}
322
324{
325 BLI_mempool_chunk *mpchunk_next;
326
327 for (; mpchunk; mpchunk = mpchunk_next) {
328 mpchunk_next = mpchunk->next;
329 mempool_chunk_free(mpchunk, pool);
330 }
331}
332
334{
335 BLI_mempool *pool;
336 BLI_freenode *last_tail = NULL;
337 uint i, maxchunks;
338
339 /* allocate the pool structure */
340 pool = MEM_mallocN(sizeof(BLI_mempool), "memory pool");
341
342#ifdef WITH_ASAN
343 BLI_mutex_init(&pool->mutex);
344#endif
345
346 /* set the elem size */
347 if (esize < (int)MEMPOOL_ELEM_SIZE_MIN) {
348 esize = (int)MEMPOOL_ELEM_SIZE_MIN;
349 }
350
352 esize = MAX2(esize, (uint)sizeof(BLI_freenode));
353 }
354
355 esize += POISON_REDZONE_SIZE;
356
357 maxchunks = mempool_maxchunks(elem_num, pchunk);
358
359 pool->chunks = NULL;
360 pool->chunk_tail = NULL;
361 pool->esize = esize;
362
363 /* Optimize chunk size to powers of 2, accounting for slop-space. */
364#ifdef USE_CHUNK_POW2
365 {
366 BLI_assert(power_of_2_max_u(pchunk * esize) > CHUNK_OVERHEAD);
367 pchunk = (power_of_2_max_u(pchunk * esize) - CHUNK_OVERHEAD) / esize;
368 }
369#endif
370
371 pool->csize = esize * pchunk;
372
373 /* Ensure this is a power of 2, minus the rounding by element size. */
374#if defined(USE_CHUNK_POW2) && !defined(NDEBUG)
375 {
376 uint final_size = (uint)MEM_SIZE_OVERHEAD + (uint)sizeof(BLI_mempool_chunk) + pool->csize;
377 BLI_assert(((uint)power_of_2_max_u(final_size) - final_size) < pool->esize);
378 }
379#endif
380
381 pool->pchunk = pchunk;
382 pool->flag = flag;
383 pool->free = NULL; /* mempool_chunk_add assigns */
384 pool->maxchunks = maxchunks;
385 pool->totused = 0;
386
387 if (elem_num) {
388 /* Allocate the actual chunks. */
389 for (i = 0; i < maxchunks; i++) {
390 BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
391 last_tail = mempool_chunk_add(pool, mpchunk, last_tail);
392 }
393 }
394
395#ifdef WITH_MEM_VALGRIND
396 VALGRIND_CREATE_MEMPOOL(pool, 0, false);
397#endif
398
399 return pool;
400}
401
403{
404 BLI_freenode *free_pop;
405
406 if (UNLIKELY(pool->free == NULL)) {
407 /* Need to allocate a new chunk. */
408 BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
409 mempool_chunk_add(pool, mpchunk, NULL);
410 }
411
412 free_pop = pool->free;
413
414 BLI_asan_unpoison(free_pop, pool->esize - POISON_REDZONE_SIZE);
415#ifdef WITH_MEM_VALGRIND
416 VALGRIND_MEMPOOL_ALLOC(pool, free_pop, pool->esize - POISON_REDZONE_SIZE);
417 /* Mark as define, then undefine immediately before returning so:
418 * - `free_pop->next` can be read without reading "undefined" memory.
419 * - `freeword` can be set without causing the memory to be considered "defined".
420 *
421 * These could be handled on a more granular level - dealing with defining & underlining these
422 * members explicitly but that requires more involved calls,
423 * adding overhead for no real benefit. */
424 VALGRIND_MAKE_MEM_DEFINED(free_pop, pool->esize - POISON_REDZONE_SIZE);
425#endif
426
427 BLI_assert(pool->chunk_tail->next == NULL);
428
429 if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
430 free_pop->freeword = USEDWORD;
431 }
432
433 pool->free = free_pop->next;
434 pool->totused++;
435
436#ifdef WITH_MEM_VALGRIND
437 VALGRIND_MAKE_MEM_UNDEFINED(free_pop, pool->esize - POISON_REDZONE_SIZE);
438#endif
439
440 return (void *)free_pop;
441}
442
444{
445 void *retval = BLI_mempool_alloc(pool);
446
447 memset(retval, 0, (size_t)pool->esize - POISON_REDZONE_SIZE);
448
449 return retval;
450}
451
457void BLI_mempool_free(BLI_mempool *pool, void *addr)
458{
459 BLI_freenode *newhead = addr;
460
461#ifndef NDEBUG
462 {
463 BLI_mempool_chunk *chunk;
464 bool found = false;
465 for (chunk = pool->chunks; chunk; chunk = chunk->next) {
466 if (ARRAY_HAS_ITEM((char *)addr, (char *)CHUNK_DATA(chunk), pool->csize)) {
467 found = true;
468 break;
469 }
470 }
471 if (!found) {
472 BLI_assert_msg(0, "Attempt to free data which is not in pool.\n");
473 }
474 }
475
476 /* Enable for debugging. */
478 memset(addr, 255, pool->esize - POISON_REDZONE_SIZE);
479 }
480#endif
481
482 if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
483#ifndef NDEBUG
484 /* This will detect double free's. */
485 BLI_assert(newhead->freeword != FREEWORD);
486#endif
487 newhead->freeword = FREEWORD;
488 }
489
490 newhead->next = pool->free;
491 pool->free = newhead;
492
493 BLI_asan_poison(newhead, pool->esize);
494
495 pool->totused--;
496
497#ifdef WITH_MEM_VALGRIND
498 VALGRIND_MEMPOOL_FREE(pool, addr);
499#endif
500
501 /* Nothing is in use; free all the chunks except the first. */
502 if (UNLIKELY(pool->totused == 0) && (pool->chunks->next)) {
503 const uint esize = pool->esize;
504 BLI_freenode *curnode;
505 uint j;
506 BLI_mempool_chunk *first;
507
508 first = pool->chunks;
509 mempool_chunk_free_all(first->next, pool);
510 first->next = NULL;
511 pool->chunk_tail = first;
512
513 /* Temporary allocation so VALGRIND doesn't complain when setting freed blocks 'next'. */
514#ifdef WITH_MEM_VALGRIND
515 VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize);
516#endif
517
518 curnode = CHUNK_DATA(first);
519 pool->free = curnode;
520
521 j = pool->pchunk;
522 while (j--) {
523 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
524 BLI_freenode *next = curnode->next = NODE_STEP_NEXT(curnode);
525 BLI_asan_poison(curnode, pool->esize);
526 curnode = next;
527 }
528
529 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
530 BLI_freenode *prev = NODE_STEP_PREV(curnode);
531 BLI_asan_poison(curnode, pool->esize);
532
533 curnode = prev;
534
535 BLI_asan_unpoison(curnode, pool->esize - POISON_REDZONE_SIZE);
536 curnode->next = NULL; /* terminate the list */
537 BLI_asan_poison(curnode, pool->esize);
538
539#ifdef WITH_MEM_VALGRIND
540 VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first));
541#endif
542 }
543}
544
546{
547 int ret = (int)pool->totused;
548
549 return ret;
550}
551
553{
554 mempool_asan_lock(pool);
555
557
558 if (index < (uint)pool->totused) {
559 /* We could have some faster mem chunk stepping code inline. */
560 BLI_mempool_iter iter;
561 void *elem;
562 BLI_mempool_iternew(pool, &iter);
563 for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) {
564 /* pass */
565 }
566
568 return elem;
569 }
570
572 return NULL;
573}
574
575void BLI_mempool_as_array(BLI_mempool *pool, void *data)
576{
577 const uint esize = pool->esize - (uint)POISON_REDZONE_SIZE;
578 BLI_mempool_iter iter;
579 const char *elem;
580 char *p = data;
581
583
584 mempool_asan_lock(pool);
585 BLI_mempool_iternew(pool, &iter);
586 while ((elem = BLI_mempool_iterstep(&iter))) {
587 memcpy(p, elem, (size_t)esize);
588 p = NODE_STEP_NEXT(p);
589 }
591}
592
593void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
594{
595 char *data = MEM_malloc_arrayN((size_t)pool->totused, pool->esize, allocstr);
596 BLI_mempool_as_array(pool, data);
597 return data;
598}
599
601{
603
604 iter->pool = pool;
605 iter->curchunk = pool->chunks;
606 iter->curindex = 0;
607}
608
610{
611 BLI_mempool_iternew(pool, &ts_iter->iter);
613}
614
616{
618
619 ParallelMempoolTaskData *iter_arr = MEM_mallocN(sizeof(*iter_arr) * iter_num, __func__);
620 BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__);
621
622 mempool_threadsafe_iternew(pool, &iter_arr->ts_iter);
623
624 *curchunk_threaded_shared = iter_arr->ts_iter.iter.curchunk;
625 iter_arr->ts_iter.curchunk_threaded_shared = curchunk_threaded_shared;
626 for (size_t i = 1; i < iter_num; i++) {
627 iter_arr[i].ts_iter = iter_arr[0].ts_iter;
628 *curchunk_threaded_shared = iter_arr[i].ts_iter.iter.curchunk =
629 ((*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL);
630 }
631
632 return iter_arr;
633}
634
642
643#if 0
644/* unoptimized, more readable */
645
646static void *bli_mempool_iternext(BLI_mempool_iter *iter)
647{
648 void *ret = NULL;
649
650 if (iter->curchunk == NULL || !iter->pool->totused) {
651 return ret;
652 }
653
654 ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex);
655
656 iter->curindex++;
657
658 if (iter->curindex == iter->pool->pchunk) {
659 iter->curindex = 0;
660 iter->curchunk = iter->curchunk->next;
661 }
662
663 return ret;
664}
665
667{
669
670 do {
671 ret = bli_mempool_iternext(iter);
672 } while (ret && ret->freeword == FREEWORD);
673
674 return ret;
675}
676
677#else /* Optimized version of code above. */
678
680{
681 if (UNLIKELY(iter->curchunk == NULL)) {
682 return NULL;
683 }
684
685 const uint esize = iter->pool->esize;
686 BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex));
688 do {
689 ret = curnode;
690
692# ifdef WITH_MEM_VALGRIND
693 VALGRIND_MAKE_MEM_DEFINED(ret, iter->pool->esize - POISON_REDZONE_SIZE);
694# endif
695
696 if (++iter->curindex != iter->pool->pchunk) {
697 curnode = POINTER_OFFSET(curnode, esize);
698 }
699 else {
700 iter->curindex = 0;
701 iter->curchunk = iter->curchunk->next;
702 if (UNLIKELY(iter->curchunk == NULL)) {
704# ifdef WITH_MEM_VALGRIND
705 VALGRIND_MAKE_MEM_DEFINED(ret, iter->pool->esize - POISON_REDZONE_SIZE);
706# endif
707 void *ret2 = (ret->freeword == FREEWORD) ? NULL : ret;
708
709 if (ret->freeword == FREEWORD) {
710 BLI_asan_poison(ret, iter->pool->esize);
711# ifdef WITH_MEM_VALGRIND
712 VALGRIND_MAKE_MEM_UNDEFINED(ret, iter->pool->esize);
713# endif
714 }
715
716 return ret2;
717 }
718 curnode = CHUNK_DATA(iter->curchunk);
719 }
720 } while (ret->freeword == FREEWORD);
721
722 return ret;
723}
724
726{
727 BLI_mempool_iter *iter = &ts_iter->iter;
728 if (UNLIKELY(iter->curchunk == NULL)) {
729 return NULL;
730 }
731
732 mempool_asan_lock(iter->pool);
733
734 const uint esize = iter->pool->esize;
735 BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex));
737 do {
738 ret = curnode;
739
741# ifdef WITH_MEM_VALGRIND
742 VALGRIND_MAKE_MEM_DEFINED(ret, iter->pool->esize);
743# endif
744
745 if (++iter->curindex != iter->pool->pchunk) {
746 curnode = POINTER_OFFSET(curnode, esize);
747 }
748 else {
749 iter->curindex = 0;
750
751 /* Begin unique to the `threadsafe` version of this function. */
752 for (iter->curchunk = *ts_iter->curchunk_threaded_shared;
753 (iter->curchunk != NULL) && (atomic_cas_ptr((void **)ts_iter->curchunk_threaded_shared,
754 iter->curchunk,
755 iter->curchunk->next) != iter->curchunk);
756 iter->curchunk = *ts_iter->curchunk_threaded_shared)
757 {
758 /* pass. */
759 }
760 if (UNLIKELY(iter->curchunk == NULL)) {
761 if (ret->freeword == FREEWORD) {
762 BLI_asan_poison(ret, esize);
763# ifdef WITH_MEM_VALGRIND
764 VALGRIND_MAKE_MEM_UNDEFINED(ret, iter->pool->esize);
765# endif
767 return NULL;
768 }
770 return ret;
771 }
772 /* End `threadsafe` exception. */
773
774 iter->curchunk = iter->curchunk->next;
775 if (UNLIKELY(iter->curchunk == NULL)) {
776 if (ret->freeword == FREEWORD) {
777 BLI_asan_poison(ret, iter->pool->esize);
778# ifdef WITH_MEM_VALGRIND
779 VALGRIND_MAKE_MEM_UNDEFINED(ret, iter->pool->esize);
780# endif
782 return NULL;
783 }
785 return ret;
786 }
787
788 curnode = CHUNK_DATA(iter->curchunk);
789 }
790
791 if (ret->freeword == FREEWORD) {
792 BLI_asan_poison(ret, iter->pool->esize);
793# ifdef WITH_MEM_VALGRIND
794 VALGRIND_MAKE_MEM_UNDEFINED(ret, iter->pool->esize);
795# endif
796 }
797 else {
798 break;
799 }
800 } while (true);
801
803 return ret;
804}
805
806#endif
807
808void BLI_mempool_clear_ex(BLI_mempool *pool, const int elem_num_reserve)
809{
810 BLI_mempool_chunk *mpchunk;
811 BLI_mempool_chunk *mpchunk_next;
812 uint maxchunks;
813
814 BLI_mempool_chunk *chunks_temp;
815 BLI_freenode *last_tail = NULL;
816
817#ifdef WITH_MEM_VALGRIND
819 VALGRIND_CREATE_MEMPOOL(pool, 0, false);
820#endif
821
822 if (elem_num_reserve == -1) {
823 maxchunks = pool->maxchunks;
824 }
825 else {
826 maxchunks = mempool_maxchunks((uint)elem_num_reserve, pool->pchunk);
827 }
828
829 /* Free all after 'pool->maxchunks'. */
830 mpchunk = mempool_chunk_find(pool->chunks, maxchunks - 1);
831 if (mpchunk && mpchunk->next) {
832 /* terminate */
833 mpchunk_next = mpchunk->next;
834 mpchunk->next = NULL;
835 mpchunk = mpchunk_next;
836
837 do {
838 mpchunk_next = mpchunk->next;
839 mempool_chunk_free(mpchunk, pool);
840 } while ((mpchunk = mpchunk_next));
841 }
842
843 /* re-initialize */
844 pool->free = NULL;
845 pool->totused = 0;
846 chunks_temp = pool->chunks;
847 pool->chunks = NULL;
848 pool->chunk_tail = NULL;
849
850 while ((mpchunk = chunks_temp)) {
851 chunks_temp = mpchunk->next;
852 last_tail = mempool_chunk_add(pool, mpchunk, last_tail);
853 }
854}
855
857{
858 BLI_mempool_clear_ex(pool, -1);
859}
860
862{
863 mempool_chunk_free_all(pool->chunks, pool);
864
865#ifdef WITH_MEM_VALGRIND
867#endif
868
869 MEM_freeN(pool);
870}
871
872#ifndef NDEBUG
874{
876}
877#endif
#define BLI_asan_unpoison(addr, size)
Definition BLI_asan.h:32
#define BLI_asan_poison(addr, size)
Definition BLI_asan.h:27
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_INLINE
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)
#define VALGRIND_DESTROY_MEMPOOL(pool)
#define MEMPOOL_ELEM_SIZE_MIN
void BLI_mempool_clear_ex(BLI_mempool *pool, const int elem_num_reserve)
#define NODE_STEP_PREV(node)
static bool mempool_debug_memset
Definition BLI_mempool.c:80
ParallelMempoolTaskData * mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t iter_num)
#define USEDWORD
Definition BLI_mempool.c:74
void * BLI_mempool_findelem(BLI_mempool *pool, uint index)
#define CHUNK_DATA(chunk)
void BLI_mempool_as_array(BLI_mempool *pool, void *data)
static void mempool_asan_lock(BLI_mempool *pool)
void mempool_iter_threadsafe_destroy(ParallelMempoolTaskData *iter_arr)
void * BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
void * BLI_mempool_alloc(BLI_mempool *pool)
int BLI_mempool_len(const BLI_mempool *pool)
void BLI_mempool_free(BLI_mempool *pool, void *addr)
void BLI_mempool_clear(BLI_mempool *pool)
static BLI_mempool_chunk * mempool_chunk_alloc(const BLI_mempool *pool)
static void mempool_threadsafe_iternew(BLI_mempool *pool, BLI_mempool_threadsafe_iter *ts_iter)
void BLI_mempool_set_memory_debug(void)
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
#define FREEWORD
Definition BLI_mempool.c:67
static void mempool_asan_unlock(BLI_mempool *pool)
static void mempool_chunk_free(BLI_mempool_chunk *mpchunk, BLI_mempool *pool)
void * mempool_iter_threadsafe_step(BLI_mempool_threadsafe_iter *ts_iter)
struct BLI_freenode BLI_freenode
void * BLI_mempool_calloc(BLI_mempool *pool)
void BLI_mempool_destroy(BLI_mempool *pool)
struct BLI_mempool_chunk BLI_mempool_chunk
void * BLI_mempool_iterstep(BLI_mempool_iter *iter)
#define POISON_REDZONE_SIZE
Definition BLI_mempool.c:43
static BLI_freenode * mempool_chunk_add(BLI_mempool *pool, BLI_mempool_chunk *mpchunk, BLI_freenode *last_tail)
BLI_mempool * BLI_mempool_create(uint esize, uint elem_num, uint pchunk, uint flag)
static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk, BLI_mempool *pool)
#define CHUNK_OVERHEAD
#define NODE_STEP_NEXT(node)
BLI_INLINE BLI_mempool_chunk * mempool_chunk_find(BLI_mempool_chunk *head, uint index)
BLI_INLINE uint mempool_maxchunks(const uint elem_num, const uint pchunk)
static uint power_of_2_max_u(uint x)
@ BLI_MEMPOOL_ALLOW_ITER
Definition BLI_mempool.h:95
unsigned int uint
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#define UNUSED_VARS(...)
#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len)
#define MAX2(a, b)
#define UNLIKELY(x)
#define POINTER_OFFSET(v, ofs)
ThreadMutex mutex
Read Guarded memory(de)allocation.
#define MEM_SIZE_OVERHEAD
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
#define NULL
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong * next
return ret
_W64 int intptr_t
Definition stdint.h:118
struct BLI_freenode * next
Definition BLI_mempool.c:90
intptr_t freeword
Definition BLI_mempool.c:92
struct BLI_mempool_chunk * next
struct BLI_mempool_chunk * curchunk
Definition BLI_mempool.h:80
BLI_mempool * pool
Definition BLI_mempool.h:79
unsigned int curindex
Definition BLI_mempool.h:81
struct BLI_mempool_chunk ** curchunk_threaded_shared
BLI_mempool_chunk * chunks
BLI_mempool_chunk * chunk_tail
BLI_freenode * free
BLI_mempool_threadsafe_iter ts_iter
uint8_t flag
Definition wm_window.cc:138