TBCI Numerical high perf. C++ Library  2.8.0
malloc_cache.h
Go to the documentation of this file.
1 
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 
92 template <typename T> class tbci_memalloc;
93 template <typename T> inline tbci_memalloc<T>& tbci_s_allocator (DUMMY1);
94 //template <> tbci_memalloc_base<double>& tbci_s_allocator<double> ();
95 
100 template <typename T>
101 class tbci_memalloc {
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 
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
194 static volatile unsigned long locks_taken = 0;
195 static volatile unsigned long locks_tried = 0;
196 static volatile unsigned long locks_direct = 0;
197 static 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 
206 static 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 
233 static 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
247 template <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
257 template <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 
278 template <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>));
322  pool->free_idx = TBCI_MALLOC_POOLSZ-1;
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
337  void smp_deinit()
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
370  : nthr(num_threads)
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  }
398 };
399 
401 template <typename T>
402 inline int tbci_memalloc_cache<T>::find_by_sz(const unsigned sz) const
403 {
404  DEBUG_PRINTF2("Search for free chunk of sz %i: ", sz);
405  tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thrno;
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 
432 template <typename T>
433 inline void tbci_memalloc_cache<T>::enter(const T* const ptr, const unsigned ln)
434 {
435  tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thrno;
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 
443 template <typename T>
444 inline void tbci_memalloc_cache<T>::rmv(const unsigned idx)
445 {
446  tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thrno;
447  pool->free_sz[idx] = 0;
448  pool->free_idx = idx;
449 }
450 
451 template <typename T>
452 inline 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  }
461  SMP_UNLOCK;
462  return ptr;
463 }
464 
465 
466 template <typename T>
467 inline 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)
474 
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 
489 template <typename T>
490 inline 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? */
495  tbci_memalloc_cache_tls<T> * const pool = malloc_tls+thrno;
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);
501  SMP_UNLOCK;
502  if (LIKELY(!tofree))
503  return;
504  _MC_DELETE(T, tofree);
505 }
506 
507 template <typename T>
508 inline 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 
527 template <typename T>
528 inline 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) \
550 template <> \
551 class 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[] */
566 template <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) \
579 SPECIALIZE_MEMALLOC_CLASS(TYPE) \
580 template <> \
581 MINLINE 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) \
588 SPECIALIZE_MEMALLOC_CLASS(TYPE) \
589 template <> \
590 MINLINE 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 
604 typedef double* doubleptr;
607 typedef float* floatptr;
610 typedef unsigned int* uintptr;
613 typedef int* intptr;
615 SPECIALIZE_MEMALLOC2(unsigned char, uchar)
616 SPECIALIZE_MEMALLOC2(signed char, schar)
617 typedef char* charptr;
619 typedef unsigned char* ucharptr;
622 typedef long* longptr;
624 SPECIALIZE_MEMALLOC2(unsigned long, ulong)
625 typedef unsigned long* ulongptr;
627 SPECIALIZE_MEMALLOC2(unsigned short, ushort)
628 typedef void* voidptr;
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 */
#define DEBUG_PRINTF3(a1, a2, a3)
Definition: malloc_cache.h:56
volatile unsigned int srch
Definition: malloc_cache.h:264
#define SPECIALIZE_MEMALLOC(TYPE)
Definition: malloc_cache.h:578
double * doubleptr
Definition: malloc_cache.h:604
void thread_dereg_callback(cbackfn ctor, cbackfn dtor, void *parm)
Definition: smp.cc:340
volatile unsigned int hit
Definition: malloc_cache.h:98
void enter(const T *const ptr, const unsigned ln)
Enter into list of FREE slots.
Definition: malloc_cache.h:433
volatile unsigned int miss
Definition: malloc_cache.h:97
#define ALIGN(x)
Definition: basics.h:444
int find_by_sz(const unsigned ln) const
Find free slot with right len, starting point for search is free_idx.
Definition: malloc_cache.h:402
#define DUMMY1
Definition: malloc_cache.h:74
void rmv(const unsigned idx)
Remove from list of FREE slots.
Definition: malloc_cache.h:444
static void _init(tbci_memalloc_cache< T > *th, const int thr)
Definition: malloc_cache.h:297
#define SMP_UNLOCK
Definition: malloc_cache.h:243
static void _deinit(tbci_memalloc_cache< T > *th, const int thr)
Definition: malloc_cache.h:311
#define _MC_NEW(T, SZ)
Definition: malloc_cache.h:130
long * longptr
Definition: malloc_cache.h:622
#define NAMESPACE_TBCI
Definition: basics.h:317
volatile unsigned int srch
Definition: malloc_cache.h:98
void free_and_enter(const T *const ptr, const unsigned ln)
Definition: malloc_cache.h:490
exception base class for the TBCI NumLib
Definition: except.h:58
tbci_memalloc< T > & tbci_s_allocator()
Definition: malloc_cache.h:567
volatile unsigned int all
Definition: malloc_cache.h:264
#define DEBUG_PRINTF4(a1, a2, a3, a4)
Definition: malloc_cache.h:57
thread_reg_callback((cbackfn *)&_init,(cbackfn *)&_deinit,(void *) this)
void deinit(const int thr)
Definition: malloc_cache.h:528
#define BCHK(cond, exc, txt, ind, rtval)
Definition: basics.h:575
unsigned long * ulongptr
Definition: malloc_cache.h:625
#define UNLIKELY(expr)
Definition: basics.h:101
#define TBCI_MALLOC_LIMIT
Definition: malloc_cache.h:65
NAMESPACE_TBCI int num_threads
Definition: smp.cc:103
unsigned char free_idx
Definition: malloc_cache.h:262
volatile unsigned int miss
Definition: malloc_cache.h:263
#define SPECIALIZE_MEMALLOC2(TYPE, SHTP)
Definition: malloc_cache.h:587
For specializations of the memory allocator:
Definition: malloc_cache.h:279
#define DEBUG_PRINTF1(arg1)
Definition: malloc_cache.h:54
#define CSTD__
Definition: basics.h:340
int * intptr
Definition: malloc_cache.h:613
unsigned short free_sz[8]
Definition: malloc_cache.h:261
#define _MC_DELETE(T, PTR)
Definition: malloc_cache.h:131
const T * find_and_rmv(const unsigned sz)
Definition: malloc_cache.h:452
#define SMP_LOCK
SMP locking: The TBCI worker threads don&#39;t do memory allocations so the memalloc_cache code does not ...
Definition: malloc_cache.h:242
#define FGD2
Definition: malloc_cache.h:77
unsigned int * uintptr
Definition: malloc_cache.h:610
#define _cpu_relax()
Definition: smp.cc:510
float * floatptr
Definition: malloc_cache.h:607
THREAD__ int thrno
Definition: smp.cc:112
tbci_memalloc_cache_tls< T > * malloc_tls
Definition: malloc_cache.h:281
#define TBCI_MALLOC_POOLSZ
Definition: malloc_cache.h:62
void init(const int thr)
Definition: malloc_cache.h:315
#define MALLOC
Definition: malloc_cache.h:29
void SWAP(T &a, T &b)
SWAP function Note: We could implement a swap function without temporaries: a -= b b += a a -= b a = ...
Definition: basics.h:813
#define MINLINE
Definition: malloc_cache.h:80
const Vector< T > const Vector< T > const Vector< T > int T T & err
Definition: LM_fit.h:102
static void dealloc(const T *const ptr, const unsigned long sz)
Definition: malloc_cache.h:111
char * charptr
Definition: malloc_cache.h:617
void dealloc(const T *const, const unsigned long)
Definition: malloc_cache.h:508
int i
Definition: LM_fit.h:71
void * voidptr
Definition: malloc_cache.h:628
#define INC(x)
Definition: malloc_cache.h:143
#define DEBUG_PRINTF2(a1, a2)
Definition: malloc_cache.h:55
#define NAMESPACE_END
Definition: basics.h:323
#define small
THREAD__ int ismainthread
Definition: smp.cc:111
volatile unsigned int hit
Definition: malloc_cache.h:264
#define NO_SINGLETON_PUBLIC
Definition: malloc_cache.h:89
#define T
Definition: bdmatlib.cc:20
static T * alloc(const unsigned long sz)
Definition: malloc_cache.h:109
unsigned char * ucharptr
Definition: malloc_cache.h:619
volatile unsigned int all
Definition: malloc_cache.h:98
T * alloc(const unsigned long)
Definition: malloc_cache.h:467
#define LIKELY(expr)
branch prediction note that we sometimes on purpose mark the unlikely possibility likely and vice ver...
Definition: basics.h:100