TBCI Numerical high perf. C++ Library 2.8.0
malloc_cache.h
Go to the documentation of this file.
10
11#ifndef TBCI_MALLOC_CACHE_H
12#define TBCI_MALLOC_CACHE_H
13
14#define MALLOC_CACHE 1
15
16#ifndef HAVE_NO_NEW_HEADERS_BUG
17# include <cstdio>
18#else
19# include <stdio.h>
20#endif
21
22#ifdef TBCI_MALLOC_STATS
23# include <typeinfo>
24#endif
25
26#ifdef HAVE_MALLOC_ATTR
27# define MALLOC __attribute__((malloc))
28#else
29# define MALLOC
30#endif
31
32#ifdef HAVE_MALLOC_H // memalign
33# include <malloc.h>
34#endif
35
36#if defined(SMP) && !defined(TBCI_MALLOC_NOLOCK)
37# define TBCI_MALLOC_LOCK 1
38# include "tbci/smp.h"
39#endif
40
41#if defined(__GNUC__) && defined(SMP) && defined(TBCI_MALLOC_NOLOCK)
42# warning "SMP support but no locking in memalloc_cache. Don't do memory\
43 de/allocations from threads; otherwise you face corruption!"
44#endif
45
46//#pragma interface "malloc_cache.h"
47
48#ifdef DEBUG_MALLOC /* Ugly, but portable */
49# define DEBUG_PRINTF1(arg1) CSTD__ fprintf(stderr, arg1)
50# define DEBUG_PRINTF2(a1,a2) CSTD__ fprintf(stderr, a1, a2)
51# define DEBUG_PRINTF3(a1,a2,a3) CSTD__ fprintf(stderr, a1, a2, a3)
52# define DEBUG_PRINTF4(a1,a2,a3,a4) CSTD__ fprintf(stderr, a1, a2, a3, a4)
53#else
54# define DEBUG_PRINTF1(arg1) do {} while (0)
55# define DEBUG_PRINTF2(a1,a2) do {} while (0)
56# define DEBUG_PRINTF3(a1,a2,a3) do {} while (0)
57# define DEBUG_PRINTF4(a1,a2,a3,a4) do {} while (0)
58#endif
59
61#ifndef TBCI_MALLOC_POOLSZ
62# define TBCI_MALLOC_POOLSZ 8
63#endif
64#ifndef TBCI_MALLOC_LIMIT
65# define TBCI_MALLOC_LIMIT 8192
66#endif
67
68#if !defined(__GNUC__) && !defined(__BORLANDC__) /* __EDG__ */
69# define DUMMY1 const T* const dummy
70# define DUMMY2(TYPE) const TYPE * const dummy
71# define DUMMY3(t) (t*)0
72# define FGD2
73#else // GCC || Borland
74# define DUMMY1
75# define DUMMY2(TYPE)
76# define DUMMY3(t)
77# define FGD2 FGDT
78#endif
79#ifndef MINLINE
80# define MINLINE inline
81#endif
82
83// Some compilers don't understand the typical singleton construction :(
84#if defined(__INTEL_COMPILER) || defined(_MSC_VER) || defined(__BORLANDC__) || (defined(_SGI_SOURCE) && defined(_COMPILER_VERSION) && !defined(__GNUC__))
85# define NO_SINGLETON
86# define NO_SINGLETON_PUBLIC public:
87//#warning Intel C++ 6 does not understand the typical singleton construction. Sigh.
88#else
89# define NO_SINGLETON_PUBLIC /**/
90#endif
91
92template <typename T> class tbci_memalloc;
93template <typename T> inline tbci_memalloc<T>& tbci_s_allocator (DUMMY1);
94//template <> tbci_memalloc_base<double>& tbci_s_allocator<double> ();
95
100template <typename T>
102 protected:
103 // singleton construction ...
107 public:
109 static T* alloc(const unsigned long sz)
110 { return new T[sz]; }
111 static void dealloc(const T* const ptr, const unsigned long sz)
112 { delete [] (T*)ptr; }
113};
114
115
116#ifndef TBCI_SIMD_ALIGN
117# ifdef AVX512
118# define TBCI_SIMD_ALIGN 64
119# elif defined(__AVX__)
120# define TBCI_SIMD_ALIGN 32
121# else
122# define TBCI_SIMD_ALIGN 16
123# endif
124#endif
125#ifndef TBCI_MALLOC_ALIGN_FACT
126# define TBCI_MALLOC_ALIGN_FACT 1
127#endif
128
129#if !defined(__SSE2__) || defined(__x86_64__) || !defined(HAVE_MALLOC_H)
130# define _MC_NEW(T,SZ) new T[SZ]
131# define _MC_DELETE(T,PTR) delete[] (T*)PTR
132# ifndef __x86_64__
133# define SSE_VARS_MAY_BE_UNALIGNED
134# endif
135#else
136# define _MC_NEW(T,SZ) (T*)memalign(TBCI_SIMD_ALIGN*TBCI_MALLOC_ALIGN_FACT, SZ*sizeof(T))
137# define _MC_DELETE(T,PTR) free((T*)PTR)
138#endif
139
140#if defined(__x86_64__) || defined(__i386__)
141# define INC(x) asm volatile ("lock incl %0" : "=m" (x): "m" (x));
142#else
143# define INC(x) ++x;
144#endif
145
173
174#if defined(HAVE_TLS) && !defined(TBCI_MALLOC_FORCESPINLOCK)
175# define TBCI_MALLOC_NOSPINLOCK
176#endif
177
178#if !defined(TBCI_MALLOC_NOSPINLOCK) && defined(HAVE_PTHREAD_SPINLOCK) && defined(TBCI_MALLOC_LOCK)
179
180#define TBCI_MALLOC_SPINLOCK
181#include <errno.h>
182
183#if defined(__i386__) || defined(__x86_64__)
184# define _cpu_relax() asm ("rep; nop")
185#else
186# define _cpu_relax()
187#endif
188
189#ifndef TBCI_MAXLOCKTRIES
190# define TBCI_MAXLOCKTRIES 4
191#endif
192
193#ifdef TBCI_MALLOC_STATS
194static volatile unsigned long locks_taken = 0;
195static volatile unsigned long locks_tried = 0;
196static volatile unsigned long locks_direct = 0;
197static volatile unsigned long locks_yield = 0;
198#endif
199
200/* TODO: Can we find a more efficient way to do spinlocks than
201 * pthread_spin_lock() ? These seem to be rather heavyweight
202 * and seem to involve the kernel (even in the fast path).
203 * Can we do something with futexes?
204 */
205
206static inline void _spin_lock(pthread_spinlock_t* lock)
207{
208 unsigned int tries = 0;
209 int err;
210 while (0 != (err = pthread_spin_trylock(lock))) {
211#ifdef PARANOIA
212 if (UNLIKELY(err != EBUSY)) {
213 fprintf(stderr, "LOCKING ERROR: %s\n", strerror(err));
214 abort();
215 }
216#endif
217 if (0 == ++tries % TBCI_MAXLOCKTRIES) {
218#ifdef TBCI_MALLOC_STATS
219 INC(locks_yield);
220#endif
221 sched_yield();
222 }
223 _cpu_relax();
224 }
225#ifdef TBCI_MALLOC_STATS
226 INC(locks_taken);
227 locks_tried += tries;
228 if (!tries)
229 INC(locks_direct);
230#endif
231}
232
233static inline void _spin_unlock(pthread_spinlock_t* lock)
234{
235 pthread_spin_unlock(lock);
236}
237
238# define SMP_LOCK _spin_lock(&this->lock)
239# define SMP_UNLOCK _spin_unlock(&this->lock)
240
241#else /* TBCI_MALLOC_SPINLOCK */
242# define SMP_LOCK
243# define SMP_UNLOCK
244#endif
245
246#if __WORDSIZE == 64
247template <typename T>
249{
250 const T *free_pt[TBCI_MALLOC_POOLSZ]; /* pointers to slots */
251 unsigned int free_sz[TBCI_MALLOC_POOLSZ]; /* sizes of free slots (0 => in use) */
252 unsigned int free_idx; /* next free (RR): guess */
253 //unsigned int pad[3]; /* padding */
254 volatile unsigned int hit, srch, all, miss;
255} ALIGN(64);
256#else
257template <typename T>
259{
260 const T *free_pt[TBCI_MALLOC_POOLSZ]; /* pointers to slots */
261 unsigned short free_sz[TBCI_MALLOC_POOLSZ]; /* sizes of free slots (0 => in use) */
262 unsigned char free_idx; /* next free (RR): guess */
263 volatile unsigned int miss:24;
264 volatile unsigned int hit, srch, all;
265} ALIGN(64);
266#endif
267
278template <typename T>
280{
282#ifdef TBCI_MALLOC_SPINLOCK
283 pthread_spinlock_t lock;
284#endif
285#ifdef SMP
286 int nthr;
287#endif
288
289 int find_by_sz(const unsigned ln) const;
290 void enter(const T* const ptr, const unsigned ln);
291 void free_and_enter(const T* const ptr, const unsigned ln);
292 void rmv(const unsigned idx);
293 const T * find_and_rmv(const unsigned sz);
294 T * alloc(const unsigned long) MALLOC;
295 void dealloc(const T* const, const unsigned long);
296#ifdef SMP
297 static void _init(tbci_memalloc_cache<T>* th, const int thr)
298 {
299 if (th->nthr >= thr)
300 return;
301 tbci_memalloc_cache_tls<T> *new_malloc_tls;
302 new_malloc_tls = (tbci_memalloc_cache_tls<T>*)
303 memalign(128, sizeof(tbci_memalloc_cache_tls<T>) *(thr+1));
304 memcpy(new_malloc_tls, th->malloc_tls,
305 sizeof(tbci_memalloc_cache_tls<T>) *(th->nthr+1));
306 SWAP(new_malloc_tls, th->malloc_tls);
307 th->nthr = thr;
308 free(new_malloc_tls);
309 th->smp_init();
310 }
311 static void _deinit(tbci_memalloc_cache<T>* th, const int thr)
312 { th->smp_deinit(); }
313#endif
314 void deinit(const int thr);
315 void init(const int thr)
316 {
317#ifdef SMP
318 BCHK(thr > nthr, NumErr, thread malloc not allocated, thr, );
319#endif
320 tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thr;
321 CSTD__ memset(pool, 0, sizeof(struct tbci_memalloc_cache_tls<T>));
323#ifdef TBCI_MALLOC_SPINLOCK
324 pthread_spin_init(&lock, 0);
325#endif
326 //fprintf(stderr, "Init pool %i @ %p\n", thr, pool);
327 }
328#ifdef SMP
329 void smp_init()
330 {
331 //CSTD__ fprintf(stderr, "malloc_cache<%s>: smp_init(%i)\n",
332 // typeid(T).name(), nthr);
333 for (int t = 1; t <= nthr; ++t)
334 init(t);
335 }
336#endif
338 {
339#ifdef TBCI_MALLOC_STATS
340 unsigned int hit, srch, all, miss;
341 hit = srch = all = miss = 0;
342#endif
343#ifdef SMP
344 if (nthr) {
345 //CSTD__ fprintf(stderr, "malloc_cache<%s>: smp_deinit(%i)\n",
346 // typeid(T).name(), nthr);
347 for (int t = nthr; t > 0; --t) {
348#ifdef TBCI_MALLOC_STATS
349 hit += malloc_tls[t].hit; srch += malloc_tls[t].srch;
350 all += malloc_tls[t].all; miss += malloc_tls[t].miss;
351#endif
352 deinit(t);
353 }
354 nthr = 0; thrno = 0;
355 }
356#endif
357#ifdef TBCI_MALLOC_STATS
358 hit += malloc_tls[0].hit; srch += malloc_tls[0].srch;
359 all += malloc_tls[0].all; miss += malloc_tls[0].miss;
360 CSTD__ fprintf(stderr, "malloc_cache<%s>: %i hits, %i misses, %i searches, %i allocs\n",
361 typeid(T).name(), hit, miss, srch, all);
362#ifdef TBCI_MALLOC_SPINLOCK
363 CSTD__ fprintf(stderr, "malloc_cache<%s>: %lu locks, %lu tries, %lu direct, %lu yields\n",
364 typeid(T).name(), locks_taken, locks_tried, locks_direct, locks_yield);
365#endif
366#endif
367 }
369#ifdef SMP
371#endif
372 {
373 //malloc_tls = new tbci_memalloc_cache_tls<T>[num_threads+1];
375 memalign(128, sizeof(tbci_memalloc_cache_tls<T>) *(num_threads+1));
376 init(0);
377#ifdef SMP
378 if (nthr) {
379 smp_init();
380 //fprintf(stderr, "Directly init per-thread vars %p: %zi\n",
381 // malloc_tls, sizeof(*malloc_tls));
382 }
383 thread_reg_callback((cbackfn*) &_init,
384 (cbackfn*) &_deinit, (void*)this);
385#endif
386 }
388 {
389#ifdef SMP
390 thread_dereg_callback((cbackfn*) &_init,
391 (cbackfn*) &_deinit, (void*)this);
392#endif
393 smp_deinit();
394 deinit(0);
395 //delete[] malloc_tls;
396 free(malloc_tls);
397 }
399
401template <typename T>
402inline int tbci_memalloc_cache<T>::find_by_sz(const unsigned sz) const
403{
404 DEBUG_PRINTF2("Search for free chunk of sz %i: ", sz);
406#ifdef SMP
407 BCHK(thrno > nthr, NumErr, thread malloc_cache too small, thrno, -1);
408#endif
409 for (unsigned int _i = 1; _i <= TBCI_MALLOC_POOLSZ; ++_i) {
410 const unsigned fidx = pool->free_idx;
411 const unsigned int i = (fidx + _i) % TBCI_MALLOC_POOLSZ;
412 DEBUG_PRINTF2("%i ", i);
413 if (sz == pool->free_sz[i]) {
414 DEBUG_PRINTF1("(found)\n");
415#ifdef TBCI_MALLOC_STATS
416 ++pool->hit;
417#endif
418 return i;
419 }
420#ifdef TBCI_MALLOC_STATS
421 ++pool->srch;
422#endif
423 }
424 DEBUG_PRINTF1("not found!\n");
425#ifdef TBCI_MALLOC_STATS
426 ++pool->miss;
427#endif
428 return -1;
429}
430
432template <typename T>
433inline void tbci_memalloc_cache<T>::enter(const T* const ptr, const unsigned ln)
434{
436 const unsigned fidx = pool->free_idx;
437 pool->free_pt[fidx] = ptr;
438 pool->free_sz[fidx] = ln;
439 pool->free_idx = (TBCI_MALLOC_POOLSZ + fidx - 1) % TBCI_MALLOC_POOLSZ;
440}
441
443template <typename T>
444inline void tbci_memalloc_cache<T>::rmv(const unsigned idx)
445{
447 pool->free_sz[idx] = 0;
448 pool->free_idx = idx;
449}
450
451template <typename T>
452inline const T* tbci_memalloc_cache<T>::find_and_rmv(const unsigned sz)
453{
454 SMP_LOCK;
455 const T* ptr = 0;
456 const int idx = find_by_sz(sz);
457 if (LIKELY(idx >= 0)) {
458 rmv(idx);
459 ptr = malloc_tls[thrno].free_pt[idx];
460 }
462 return ptr;
463}
464
465
466template <typename T>
467inline T* tbci_memalloc_cache<T>::alloc(const unsigned long sz)
468{
469 BCHK(!sz, NumErr, alloc 0 bytes, sz, (T*)0);
470#ifdef TBCI_MALLOC_STATS
471 ++malloc_tls[thrno].all;
472#endif
473#if defined(TBCI_MALLOC_LOCK) && !defined(TBCI_MALLOC_SPINLOCK)
475 if (0 && !ismainthread)
476 return _MC_NEW(T, sz);
477#endif
478 if (UNLIKELY (sz > TBCI_MALLOC_LIMIT/sizeof(T)))
479 return _MC_NEW(T, sz);
480
481 const T* ptr = find_and_rmv(sz);
482 if (!ptr)
483 ptr = _MC_NEW(T, sz);
484
485 DEBUG_PRINTF3("Allocated %p (%li)\n", ptr, sz);
486 return (T*) ptr;
487}
488
489template <typename T>
490inline void tbci_memalloc_cache<T>::free_and_enter(const T* const ptr, const unsigned sz)
491{
492 const T* tofree = 0;
493 SMP_LOCK;
494 /* replace free slot? */
496 const unsigned fidx = pool->free_idx;
497 if (UNLIKELY(pool->free_sz[fidx] != 0))
498 tofree = pool->free_pt[fidx];
499 DEBUG_PRINTF4("\"Freed\" %p (%li) -> %i\n", ptr, sz, fidx);
500 enter(ptr, sz);
502 if (LIKELY(!tofree))
503 return;
504 _MC_DELETE(T, tofree);
505}
506
507template <typename T>
508inline void tbci_memalloc_cache<T>::dealloc(const T* const ptr, const unsigned long sz)
509{
510 BCHK (!ptr||!sz, NumErr, dealloc null ptr or 0 bytes, (long)ptr, );
511
512#ifdef MALLOC_POISON
513 CSTD__ memset((void*)ptr, 0xa5, sz*sizeof(T));
514#endif
515#if defined(TBCI_MALLOC_LOCK) && !defined(TBCI_MALLOC_SPINLOCK)
516 if (0 && !ismainthread) {
517 _MC_DELETE(T, ptr); return;
518 }
519#endif
520
521 if (UNLIKELY (sz > TBCI_MALLOC_LIMIT/sizeof(T)))
522 _MC_DELETE(T, ptr);
523 else
524 free_and_enter(ptr, sz);
525}
526
527template <typename T>
528inline void tbci_memalloc_cache<T>::deinit(const int thr)
529{
530 DEBUG_PRINTF1("Freeing memory pool ...\n");
531 //int * ptr = 0; *ptr = 0;
532 tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thr;
533
534 for (int _i = 0; _i < TBCI_MALLOC_POOLSZ; ++_i) {
535 if (pool->free_sz[_i]) {
536 DEBUG_PRINTF3("Freeing mem %p (size %i)\n",
537 pool->free_pt[_i], pool->free_sz[_i]);
538 pool->free_sz[_i] = 0;
539 _MC_DELETE(T, pool->free_pt[_i]);
540 }
541 }
542#ifdef TBCI_MALLOC_SPINLOCK
543 pthread_spin_destroy(&lock);
544#endif
545}
546
549#define SPECIALIZE_MEMALLOC_CLASS(TYPE) \
550template <> \
551class tbci_memalloc<TYPE > { \
552 typedef TYPE T; \
553 protected: \
554 tbci_memalloc_cache<T > m_cache; \
555 NO_SINGLETON_PUBLIC \
556 tbci_memalloc() {} \
557 ~tbci_memalloc() {} \
558 public: \
559 friend tbci_memalloc<T >& tbci_s_allocator FGD2 (DUMMY1); \
560 T* alloc(const unsigned long sz) { return m_cache.alloc(sz); } \
561 void dealloc(const T* const ptr, const unsigned long sz) \
562 { m_cache.dealloc(ptr,sz); } \
563};
564
565/* Default allocator, just a wrapper to new[] and delete[] */
566template <typename T> \
568{
569 static tbci_memalloc<T> _tbci_s_alloc_ANON; /* the one and only */
570 return _tbci_s_alloc_ANON;
571}
572
573#if defined(__MINGW32__)
574#define SPECIALIZE_MEMALLOC(TYPE) /* nothing */
575#define SPECIALIZE_MEMALLOC2(TYPE,SHTP) /* even less */
576#else
577/* Specializations */
578#define SPECIALIZE_MEMALLOC(TYPE) \
579SPECIALIZE_MEMALLOC_CLASS(TYPE) \
580template <> \
581MINLINE tbci_memalloc<TYPE >& tbci_s_allocator<TYPE > (DUMMY2(TYPE)) \
582{ /* the one and only */ \
583 static tbci_memalloc<TYPE > _tbci_s_alloc_##TYPE; \
584 return _tbci_s_alloc_##TYPE; \
585}
586/* Specializations */
587#define SPECIALIZE_MEMALLOC2(TYPE,SHTP) \
588SPECIALIZE_MEMALLOC_CLASS(TYPE) \
589template <> \
590MINLINE tbci_memalloc<TYPE >& tbci_s_allocator<TYPE > (DUMMY2(TYPE)) \
591{ /* the one and only */ \
592 static tbci_memalloc<TYPE > _tbci_s_alloc_##SHTP; \
593 return _tbci_s_alloc_##SHTP; \
594}
595#endif /* ! __MINGW32__ */
596
597/* TODO: Add define, controlling instantiation */
598
599#if 0 // defined(TBCI_SELECTIVE_INST) && !defined(TBCI_INSTANTIATE) && !defined(AUTO_DECL)
600# include "malloc_cache_gd.h"
601#else
602
604typedef double* doubleptr;
607typedef float* floatptr;
613typedef int* intptr;
615SPECIALIZE_MEMALLOC2(unsigned char, uchar)
616SPECIALIZE_MEMALLOC2(signed char, schar)
617typedef char* charptr;
622typedef long* longptr;
624SPECIALIZE_MEMALLOC2(unsigned long, ulong)
627SPECIALIZE_MEMALLOC2(unsigned short, ushort)
630
631#endif // TBCI_SELECTIVE_INST
632
633#define NEW(t, s) tbci_s_allocator<t>(DUMMY3(t)).alloc(s)
634#define TBCIDELETE(t, v, sz) tbci_s_allocator<t>(DUMMY3(t)).dealloc(v, sz)
635#define TBCIDELETE_RO(t, v, sz) tbci_s_allocator<t>(DUMMY3(t)).dealloc(v, sz)
636#define REALLOC(v, os, t, s) do { \
637 t *ptr = NEW(t, s); \
638 if (LIKELY(v)) { \
639 TBCICOPY(ptr, v, t, MIN(os, s));\
640 TBCIDELETE(t, v, os); \
641 } \
642 v = ptr; \
643} while (0)
644
646#endif /* TBCI_MALLOC_CACHE_H */
const Vector< T > const Vector< T > const Vector< T > int T T & err
Definition LM_fit.h:102
int i
Definition LM_fit.h:71
#define num_threads
Definition basics.h:782
#define CSTD__
Definition basics.h:340
#define BCHK(cond, exc, txt, ind, rtval)
Definition basics.h:575
#define LIKELY(expr)
branch prediction note that we sometimes on purpose mark the unlikely possibility likely and vice ver...
Definition basics.h:100
#define ismainthread
Definition basics.h:784
#define NAMESPACE_END
Definition basics.h:323
#define thrno
Definition basics.h:783
#define NAMESPACE_TBCI
Definition basics.h:317
#define UNLIKELY(expr)
Definition basics.h:101
#define T
Definition bdmatlib.cc:20
exception base class for the TBCI NumLib
Definition except.h:59
static T * alloc(const unsigned long sz)
static void dealloc(const T *const ptr, const unsigned long sz)
#define _MC_NEW(T, SZ)
#define _MC_DELETE(T, PTR)
#define SMP_UNLOCK
#define DEBUG_PRINTF2(a1, a2)
volatile unsigned int hit
Definition malloc_cache.h:4
long * longptr
#define INC(x)
unsigned short free_sz[8]
Definition malloc_cache.h:1
#define MALLOC
#define SPECIALIZE_MEMALLOC2(TYPE, SHTP)
#define SPECIALIZE_MEMALLOC(TYPE)
unsigned int * uintptr
volatile unsigned int miss
Definition malloc_cache.h:3
#define DEBUG_PRINTF1(arg1)
unsigned long * ulongptr
#define DEBUG_PRINTF3(a1, a2, a3)
const T * free_pt[8]
Definition malloc_cache.h:0
unsigned char * ucharptr
#define DEBUG_PRINTF4(a1, a2, a3, a4)
#define SMP_LOCK
SMP locking: The TBCI worker threads don't do memory allocations so the memalloc_cache code does not ...
struct tbci_memalloc_cache ALIGN
unsigned char free_idx
Definition malloc_cache.h:2
volatile unsigned int all
Definition malloc_cache.h:4
volatile unsigned int srch
Definition malloc_cache.h:4
#define MINLINE
char * charptr
#define DUMMY1
float * floatptr
#define TBCI_MALLOC_LIMIT
void * voidptr
double * doubleptr
int * intptr
#define NO_SINGLETON_PUBLIC
#define TBCI_MALLOC_POOLSZ
#define FGD2
tbci_memalloc< T > & tbci_s_allocator()
void thread_dereg_callback(cbackfn ctor, cbackfn dtor, void *parm)
Definition smp.cc:340
#define _cpu_relax()
Definition smp.cc:510
void thread_reg_callback(cbackfn ctor, cbackfn dtor, void *parm)
Definition smp.cc:333
volatile unsigned int hit
volatile unsigned int all
volatile unsigned int miss
volatile unsigned int srch
unsigned short free_sz[8]
int find_by_sz(const unsigned ln) const
Find free slot with right len, starting point for search is free_idx.
static void _init(tbci_memalloc_cache< T > *th, const int thr)
void rmv(const unsigned idx)
Remove from list of FREE slots.
static void _deinit(tbci_memalloc_cache< T > *th, const int thr)
const T * find_and_rmv(const unsigned sz)
void free_and_enter(const T *const ptr, const unsigned ln)
void init(const int thr)
T * alloc(const unsigned long)
void enter(const T *const ptr, const unsigned ln)
Enter into list of FREE slots.
tbci_memalloc_cache_tls< T > * malloc_tls
void deinit(const int thr)
void dealloc(const T *const, const unsigned long)
#define small