38 #include "kmp_wrapper_malloc.h"
46 typedef int (*bget_compact_t)(size_t, int);
47 typedef void *(*bget_acquire_t)(size_t);
48 typedef void (*bget_release_t)(
void *);
54 typedef kmp_int32 bufsize;
56 typedef kmp_int64 bufsize;
59 typedef ssize_t bufsize;
64 typedef enum bget_mode {
71 static void bpool( kmp_info_t *th,
void *buffer, bufsize len);
72 static void *bget( kmp_info_t *th, bufsize size);
73 static void *bgetz( kmp_info_t *th, bufsize size);
74 static void *bgetr( kmp_info_t *th,
void *buffer, bufsize newsize);
75 static void brel( kmp_info_t *th,
void *buf);
76 static void bectl( kmp_info_t *th, bget_compact_t compact, bget_acquire_t acquire, bget_release_t release, bufsize pool_incr );
79 static void bstats( kmp_info_t *th, bufsize *curalloc, bufsize *totfree, bufsize *maxfree,
long *nget,
long *nrel);
80 static void bstatse( kmp_info_t *th, bufsize *pool_incr,
long *npool,
long *npget,
long *nprel,
long *ndget,
long *ndrel);
81 static void bufdump( kmp_info_t *th,
void *buf);
82 static void bpoold( kmp_info_t *th,
void *pool,
int dumpalloc,
int dumpfree);
83 static int bpoolv( kmp_info_t *th,
void *pool);
99 #define AlignType double
104 #define AlignType _Quad
145 static bufsize bget_bin_size[ ] = {
169 #define MAX_BGET_BINS (sizeof(bget_bin_size) / sizeof(bufsize))
178 typedef struct qlinks {
179 struct bfhead *flink;
180 struct bfhead *blink;
185 typedef struct bhead2 {
196 typedef union bhead {
197 KMP_ALIGN( SizeQuant )
199 char b_pad[ sizeof(bhead2_t) + (SizeQuant - (sizeof(bhead2_t) % SizeQuant)) ];
202 #define BH(p) ((bhead_t *) (p))
206 typedef struct bdhead
211 #define BDH(p) ((bdhead_t *) (p))
215 typedef struct bfhead {
219 #define BFH(p) ((bfhead_t *) (p))
221 typedef struct thr_data {
222 bfhead_t freelist[ MAX_BGET_BINS ];
227 long numpget, numprel;
228 long numdget, numdrel;
232 bget_compact_t compfcn;
233 bget_acquire_t acqfcn;
234 bget_release_t relfcn;
245 bfhead_t * last_pool;
250 #define QLSize (sizeof(qlinks_t))
251 #define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize)
252 #define MaxSize (bufsize)( ~ ( ( (bufsize)( 1 ) << ( sizeof( bufsize ) * CHAR_BIT - 1 ) ) | ( SizeQuant - 1 ) ) )
259 #define ESent ((bufsize) (-(((((bufsize)1)<<((int)sizeof(bufsize)*8-2))-1)*2)-2))
266 bget_get_bin( bufsize size )
269 int lo = 0, hi = MAX_BGET_BINS - 1;
271 KMP_DEBUG_ASSERT( size > 0 );
273 while ( (hi - lo) > 1 ) {
274 int mid = (lo + hi) >> 1;
275 if (size < bget_bin_size[ mid ])
281 KMP_DEBUG_ASSERT( (lo >= 0) && (lo < MAX_BGET_BINS) );
287 set_thr_data( kmp_info_t *th )
294 ( ! th->th.th_local.bget_data ) ? __kmp_allocate(
sizeof( *data ) ) : th->th.th_local.bget_data
297 memset( data,
'\0',
sizeof( *data ) );
299 for (i = 0; i < MAX_BGET_BINS; ++i) {
300 data->freelist[ i ].ql.flink = & data->freelist[ i ];
301 data->freelist[ i ].ql.blink = & data->freelist[ i ];
304 th->th.th_local.bget_data = data;
305 th->th.th_local.bget_list = 0;
306 #if ! USE_CMP_XCHG_FOR_BGET
307 #ifdef USE_QUEUING_LOCK_FOR_BGET
308 __kmp_init_lock( & th->th.th_local.bget_lock );
310 __kmp_init_bootstrap_lock( & th->th.th_local.bget_lock );
316 get_thr_data( kmp_info_t *th )
320 data = (thr_data_t *) th->th.th_local.bget_data;
322 KMP_DEBUG_ASSERT( data != 0 );
331 __kmp_bget_validate_queue( kmp_info_t *th )
335 void *p = (
void *) th->th.th_local.bget_list;
338 bfhead_t *b = BFH(((
char *) p) -
sizeof(bhead_t));
340 KMP_DEBUG_ASSERT(b->bh.bb.bsize != 0);
341 p = (
void *) b->ql.flink;
350 __kmp_bget_dequeue( kmp_info_t *th )
352 void *p = TCR_SYNC_PTR(th->th.th_local.bget_list);
355 #if USE_CMP_XCHG_FOR_BGET
357 volatile void *old_value = TCR_SYNC_PTR(th->th.th_local.bget_list);
358 while ( ! KMP_COMPARE_AND_STORE_PTR(
359 & th->th.th_local.bget_list, old_value, NULL ) )
362 old_value = TCR_SYNC_PTR(th->th.th_local.bget_list);
364 p = (
void *) old_value;
367 #ifdef USE_QUEUING_LOCK_FOR_BGET
368 __kmp_acquire_lock( & th->th.th_local.bget_lock,
369 __kmp_gtid_from_thread(th) );
371 __kmp_acquire_bootstrap_lock( & th->th.th_local.bget_lock );
374 p = (
void *) th->th.th_local.bget_list;
375 th->th.th_local.bget_list = 0;
377 #ifdef USE_QUEUING_LOCK_FOR_BGET
378 __kmp_release_lock( & th->th.th_local.bget_lock,
379 __kmp_gtid_from_thread(th) );
381 __kmp_release_bootstrap_lock( & th->th.th_local.bget_lock );
389 bfhead_t *b = BFH(((
char *) p) -
sizeof(bhead_t));
391 KMP_DEBUG_ASSERT( b->bh.bb.bsize != 0 );
392 KMP_DEBUG_ASSERT( ( (kmp_uintptr_t)TCR_PTR(b->bh.bb.bthr) & ~1 ) ==
394 KMP_DEBUG_ASSERT( b->ql.blink == 0 );
396 p = (
void *) b->ql.flink;
406 __kmp_bget_enqueue( kmp_info_t *th,
void *buf
407 #ifdef USE_QUEUING_LOCK_FOR_BGET
412 bfhead_t *b = BFH(((
char *) buf) -
sizeof(bhead_t));
414 KMP_DEBUG_ASSERT( b->bh.bb.bsize != 0 );
415 KMP_DEBUG_ASSERT( ( (kmp_uintptr_t)TCR_PTR(b->bh.bb.bthr) & ~1 ) ==
420 KC_TRACE( 10, (
"__kmp_bget_enqueue: moving buffer to T#%d list\n",
421 __kmp_gtid_from_thread( th ) ) );
423 #if USE_CMP_XCHG_FOR_BGET
425 volatile void *old_value = TCR_PTR(th->th.th_local.bget_list);
428 b->ql.flink = BFH( old_value );
431 KMP_FSYNC_RELEASING(&th->th.th_local.bget_list);
434 while ( ! KMP_COMPARE_AND_STORE_PTR(
435 & th->th.th_local.bget_list, old_value, buf ) )
438 old_value = TCR_PTR(th->th.th_local.bget_list);
441 b->ql.flink = BFH( old_value );
443 KMP_FSYNC_RELEASING(&th->th.th_local.bget_list);
448 # ifdef USE_QUEUING_LOCK_FOR_BGET
449 __kmp_acquire_lock( & th->th.th_local.bget_lock, rel_gtid );
451 __kmp_acquire_bootstrap_lock( & th->th.th_local.bget_lock );
454 b->ql.flink = BFH( th->th.th_local.bget_list );
455 th->th.th_local.bget_list = (
void *) buf;
457 # ifdef USE_QUEUING_LOCK_FOR_BGET
458 __kmp_release_lock( & th->th.th_local.bget_lock, rel_gtid );
460 __kmp_release_bootstrap_lock( & th->th.th_local.bget_lock );
468 __kmp_bget_insert_into_freelist( thr_data_t *thr, bfhead_t *b )
472 KMP_DEBUG_ASSERT( ((
size_t)b ) % SizeQuant == 0 );
473 KMP_DEBUG_ASSERT( b->bh.bb.bsize % SizeQuant == 0 );
475 bin = bget_get_bin( b->bh.bb.bsize );
477 KMP_DEBUG_ASSERT(thr->freelist[ bin ].ql.blink->ql.flink == &thr->freelist[ bin ]);
478 KMP_DEBUG_ASSERT(thr->freelist[ bin ].ql.flink->ql.blink == &thr->freelist[ bin ]);
480 b->ql.flink = &thr->freelist[ bin ];
481 b->ql.blink = thr->freelist[ bin ].ql.blink;
483 thr->freelist[ bin ].ql.blink = b;
484 b->ql.blink->ql.flink = b;
490 __kmp_bget_remove_from_freelist( bfhead_t *b )
492 KMP_DEBUG_ASSERT(b->ql.blink->ql.flink == b);
493 KMP_DEBUG_ASSERT(b->ql.flink->ql.blink == b);
495 b->ql.blink->ql.flink = b->ql.flink;
496 b->ql.flink->ql.blink = b->ql.blink;
504 bcheck( kmp_info_t *th, bufsize *max_free, bufsize *total_free )
506 thr_data_t *thr = get_thr_data( th );
509 *total_free = *max_free = 0;
511 for (bin = 0; bin < MAX_BGET_BINS; ++bin) {
514 best = &thr->freelist[ bin ];
517 while (b != &thr->freelist[ bin ]) {
518 *total_free += (b->bh.bb.bsize -
sizeof( bhead_t ));
519 if ((best == &thr->freelist[ bin ]) || (b->bh.bb.bsize < best->bh.bb.bsize))
526 if (*max_free < best->bh.bb.bsize)
527 *max_free = best->bh.bb.bsize;
530 if (*max_free >
sizeof( bhead_t ))
531 *max_free -=
sizeof( bhead_t );
539 bget( kmp_info_t *th, bufsize requested_size )
541 thr_data_t *thr = get_thr_data( th );
542 bufsize size = requested_size;
550 if ( size < 0 || size +
sizeof( bhead_t ) > MaxSize ) {
554 __kmp_bget_dequeue( th );
559 #if defined( SizeQuant ) && ( SizeQuant > 1 )
560 size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1));
563 size +=
sizeof(bhead_t);
565 KMP_DEBUG_ASSERT( size >= 0 );
566 KMP_DEBUG_ASSERT( size % SizeQuant == 0 );
568 use_blink = ( thr->mode == bget_mode_lifo );
577 for (bin = bget_get_bin( size ); bin < MAX_BGET_BINS; ++bin) {
579 b = ( use_blink ? thr->freelist[ bin ].ql.blink : thr->freelist[ bin ].ql.flink );
581 if (thr->mode == bget_mode_best) {
582 best = &thr->freelist[ bin ];
587 while (b != &thr->freelist[ bin ]) {
588 if (b->bh.bb.bsize >= (bufsize) size) {
589 if ((best == &thr->freelist[ bin ]) || (b->bh.bb.bsize < best->bh.bb.bsize)) {
595 b = ( use_blink ? b->ql.blink : b->ql.flink );
600 while (b != &thr->freelist[ bin ]) {
601 if ((bufsize) b->bh.bb.bsize >= (bufsize) size) {
612 if ((b->bh.bb.bsize - (bufsize) size) > (SizeQ + (
sizeof(bhead_t)))) {
615 ba = BH(((
char *) b) + (b->bh.bb.bsize - (bufsize) size));
616 bn = BH(((
char *) ba) + size);
618 KMP_DEBUG_ASSERT(bn->bb.prevfree == b->bh.bb.bsize);
621 b->bh.bb.bsize -= (bufsize) size;
624 ba->bb.prevfree = b->bh.bb.bsize;
627 ba->bb.bsize = -size;
630 TCW_PTR(ba->bb.bthr, th);
635 __kmp_bget_remove_from_freelist( b );
636 __kmp_bget_insert_into_freelist( thr, b );
638 thr->totalloc += (size_t) size;
641 buf = (
void *) ((((
char *) ba) +
sizeof(bhead_t)));
642 KMP_DEBUG_ASSERT( ((
size_t)buf) % SizeQuant == 0 );
647 ba = BH(((
char *) b) + b->bh.bb.bsize);
649 KMP_DEBUG_ASSERT(ba->bb.prevfree == b->bh.bb.bsize);
654 __kmp_bget_remove_from_freelist( b );
656 thr->totalloc += (size_t) b->bh.bb.bsize;
660 b->bh.bb.bsize = -(b->bh.bb.bsize);
663 TCW_PTR(ba->bb.bthr, th);
669 buf = (
void *) &(b->ql);
670 KMP_DEBUG_ASSERT( ((
size_t)buf) % SizeQuant == 0 );
676 b = ( use_blink ? b->ql.blink : b->ql.flink );
684 if ((thr->compfcn == 0) || (!(*thr->compfcn)(size, ++compactseq))) {
693 if (thr->acqfcn != 0) {
694 if (size > (bufsize) (thr->exp_incr -
sizeof(bhead_t))) {
701 size +=
sizeof(bdhead_t) -
sizeof(bhead_t);
703 KE_TRACE( 10, (
"%%%%%% MALLOC( %d )\n", (
int) size ) );
706 bdh = BDH((*thr->acqfcn)((bufsize) size));
711 bdh->bh.bb.bsize = 0;
714 TCW_PTR(bdh->bh.bb.bthr, th);
716 bdh->bh.bb.prevfree = 0;
719 thr->totalloc += (size_t) size;
723 buf = (
void *) (bdh + 1);
724 KMP_DEBUG_ASSERT( ((
size_t)buf) % SizeQuant == 0 );
734 KE_TRACE( 10, (
"%%%%%% MALLOCB( %d )\n", (
int) thr->exp_incr ) );
737 newpool = (*thr->acqfcn)((bufsize) thr->exp_incr);
738 KMP_DEBUG_ASSERT( ((
size_t)newpool) % SizeQuant == 0 );
739 if (newpool != NULL) {
740 bpool( th, newpool, thr->exp_incr);
741 buf = bget( th, requested_size);
757 bgetz( kmp_info_t *th, bufsize size )
759 char *buf = (
char *) bget( th, size);
765 b = BH(buf -
sizeof(bhead_t));
766 rsize = -(b->bb.bsize);
770 bd = BDH(buf -
sizeof(bdhead_t));
771 rsize = bd->tsize - (bufsize)
sizeof(bdhead_t);
773 rsize -=
sizeof(bhead_t);
776 KMP_DEBUG_ASSERT(rsize >= size);
778 (void) memset(buf, 0, (bufsize) rsize);
780 return ((
void *) buf);
789 bgetr( kmp_info_t *th,
void *buf, bufsize size)
795 nbuf = bget( th, size );
796 if ( nbuf == NULL ) {
802 b = BH(((
char *) buf) -
sizeof(bhead_t));
803 osize = -b->bb.bsize;
808 bd = BDH(((
char *) buf) -
sizeof(bdhead_t));
809 osize = bd->tsize - (bufsize)
sizeof(bdhead_t);
811 osize -=
sizeof(bhead_t);
814 KMP_DEBUG_ASSERT(osize > 0);
816 (void) memcpy((
char *) nbuf, (
char *) buf,
817 (
size_t) ((size < osize) ? size : osize));
826 brel( kmp_info_t *th,
void *buf )
828 thr_data_t *thr = get_thr_data( th );
832 KMP_DEBUG_ASSERT(buf != NULL);
833 KMP_DEBUG_ASSERT( ((
size_t)buf) % SizeQuant == 0 );
835 b = BFH(((
char *) buf) -
sizeof(bhead_t));
837 if (b->bh.bb.bsize == 0) {
840 bdh = BDH(((
char *) buf) -
sizeof(bdhead_t));
841 KMP_DEBUG_ASSERT(b->bh.bb.prevfree == 0);
843 thr->totalloc -= (size_t) bdh->tsize;
848 (
void) memset((
char *) buf, 0x55,
849 (
size_t) (bdh->tsize -
sizeof(bdhead_t)));
852 KE_TRACE( 10, (
"%%%%%% FREE( %p )\n", (
void *) bdh ) );
854 KMP_DEBUG_ASSERT( thr->relfcn != 0 );
855 (*thr->relfcn)((
void *) bdh);
859 bth = (kmp_info_t *)( (kmp_uintptr_t)TCR_PTR(b->bh.bb.bthr) & ~1 );
862 __kmp_bget_enqueue( bth, buf
863 #ifdef USE_QUEUING_LOCK_FOR_BGET
864 , __kmp_gtid_from_thread( th )
873 if (b->bh.bb.bsize >= 0) {
876 KMP_DEBUG_ASSERT(b->bh.bb.bsize < 0);
881 KMP_DEBUG_ASSERT(BH((
char *) b - b->bh.bb.bsize)->bb.prevfree == 0);
885 thr->totalloc += (size_t) b->bh.bb.bsize;
890 if (b->bh.bb.prevfree != 0) {
897 register bufsize size = b->bh.bb.bsize;
900 KMP_DEBUG_ASSERT(BH((
char *) b - b->bh.bb.prevfree)->bb.bsize == b->bh.bb.prevfree);
901 b = BFH(((
char *) b) - b->bh.bb.prevfree);
902 b->bh.bb.bsize -= size;
905 __kmp_bget_remove_from_freelist( b );
912 b->bh.bb.bsize = -b->bh.bb.bsize;
916 __kmp_bget_insert_into_freelist( thr, b );
924 bn = BFH(((
char *) b) + b->bh.bb.bsize);
925 if (bn->bh.bb.bsize > 0) {
930 KMP_DEBUG_ASSERT(BH((
char *) bn + bn->bh.bb.bsize)->bb.prevfree == bn->bh.bb.bsize);
932 __kmp_bget_remove_from_freelist( bn );
934 b->bh.bb.bsize += bn->bh.bb.bsize;
938 __kmp_bget_remove_from_freelist( b );
939 __kmp_bget_insert_into_freelist( thr, b );
948 bn = BFH(((
char *) b) + b->bh.bb.bsize);
951 (void) memset(((
char *) b) +
sizeof(bfhead_t), 0x55,
952 (
size_t) (b->bh.bb.bsize -
sizeof(bfhead_t)));
954 KMP_DEBUG_ASSERT(bn->bh.bb.bsize < 0);
959 bn->bh.bb.prevfree = b->bh.bb.bsize;
966 if (thr->relfcn != 0 &&
967 b->bh.bb.bsize == (bufsize)(thr->pool_len -
sizeof(bhead_t)))
970 if (thr->numpblk != 1) {
973 KMP_DEBUG_ASSERT(b->bh.bb.prevfree == 0);
974 KMP_DEBUG_ASSERT(BH((
char *) b + b->bh.bb.bsize)->bb.bsize == ESent);
975 KMP_DEBUG_ASSERT(BH((
char *) b + b->bh.bb.bsize)->bb.prevfree == b->bh.bb.bsize);
978 __kmp_bget_remove_from_freelist( b );
980 KE_TRACE( 10, (
"%%%%%% FREE( %p )\n", (
void *) b ) );
986 KMP_DEBUG_ASSERT(thr->numpblk == thr->numpget - thr->numprel);
989 if (thr->last_pool == b) thr->last_pool = 0;
1001 bectl( kmp_info_t *th, bget_compact_t compact, bget_acquire_t acquire, bget_release_t release, bufsize pool_incr)
1003 thr_data_t *thr = get_thr_data( th );
1005 thr->compfcn = compact;
1006 thr->acqfcn = acquire;
1007 thr->relfcn = release;
1008 thr->exp_incr = pool_incr;
1014 bpool( kmp_info_t *th,
void *buf, bufsize len)
1017 thr_data_t *thr = get_thr_data( th );
1018 bfhead_t *b = BFH(buf);
1021 __kmp_bget_dequeue( th );
1024 len &= ~(SizeQuant - 1);
1026 if (thr->pool_len == 0) {
1027 thr->pool_len = len;
1028 }
else if (len != thr->pool_len) {
1034 KMP_DEBUG_ASSERT(thr->numpblk == thr->numpget - thr->numprel);
1041 KMP_DEBUG_ASSERT(len -
sizeof(bhead_t) <= -((bufsize) ESent + 1));
1047 b->bh.bb.prevfree = 0;
1057 len -=
sizeof(bhead_t);
1058 b->bh.bb.bsize = (bufsize) len;
1060 TCW_PTR( b->bh.bb.bthr, (kmp_info_t*)((kmp_uintptr_t)th | 1) );
1063 __kmp_bget_insert_into_freelist( thr, b );
1066 (void) memset(((
char *) b) +
sizeof(bfhead_t), 0x55,
1067 (
size_t) (len -
sizeof(bfhead_t)));
1069 bn = BH(((
char *) b) + len);
1070 bn->bb.prevfree = (bufsize) len;
1072 KMP_DEBUG_ASSERT( (~0) == -1 && (bn != 0) );
1074 bn->bb.bsize = ESent;
1082 bfreed( kmp_info_t *th )
1084 int bin = 0, count = 0;
1085 int gtid = __kmp_gtid_from_thread( th );
1086 thr_data_t *thr = get_thr_data( th );
1089 __kmp_printf_no_lock(
"__kmp_printpool: T#%d total=%" KMP_UINT64_SPEC
" get=%" KMP_INT64_SPEC
" rel=%" \
1090 KMP_INT64_SPEC
" pblk=%" KMP_INT64_SPEC
" pget=%" KMP_INT64_SPEC
" prel=%" KMP_INT64_SPEC \
1091 " dget=%" KMP_INT64_SPEC
" drel=%" KMP_INT64_SPEC
"\n",
1092 gtid, (kmp_uint64) thr->totalloc,
1093 (kmp_int64) thr->numget, (kmp_int64) thr->numrel,
1094 (kmp_int64) thr->numpblk,
1095 (kmp_int64) thr->numpget, (kmp_int64) thr->numprel,
1096 (kmp_int64) thr->numdget, (kmp_int64) thr->numdrel );
1099 for (bin = 0; bin < MAX_BGET_BINS; ++bin) {
1102 for (b = thr->freelist[ bin ].ql.flink; b != &thr->freelist[ bin ]; b = b->ql.flink) {
1103 bufsize bs = b->bh.bb.bsize;
1105 KMP_DEBUG_ASSERT( b->ql.blink->ql.flink == b );
1106 KMP_DEBUG_ASSERT( b->ql.flink->ql.blink == b );
1107 KMP_DEBUG_ASSERT( bs > 0 );
1111 __kmp_printf_no_lock(
"__kmp_printpool: T#%d Free block: 0x%p size %6ld bytes.\n", gtid, b, (
long) bs );
1114 char *lerr = ((
char *) b) +
sizeof(bfhead_t);
1115 if ((bs >
sizeof(bfhead_t)) && ((*lerr != 0x55) || (memcmp(lerr, lerr + 1, (
size_t) (bs - (
sizeof(bfhead_t) + 1))) != 0))) {
1116 __kmp_printf_no_lock(
"__kmp_printpool: T#%d (Contents of above free block have been overstored.)\n", gtid );
1124 __kmp_printf_no_lock(
"__kmp_printpool: T#%d No free blocks\n", gtid );
1136 bstats( kmp_info_t *th, bufsize *curalloc, bufsize *totfree, bufsize *maxfree,
long *nget,
long *nrel)
1139 thr_data_t *thr = get_thr_data( th );
1141 *nget = thr->numget;
1142 *nrel = thr->numrel;
1143 *curalloc = (bufsize) thr->totalloc;
1147 for (bin = 0; bin < MAX_BGET_BINS; ++bin) {
1148 bfhead_t *b = thr->freelist[ bin ].ql.flink;
1150 while (b != &thr->freelist[ bin ]) {
1151 KMP_DEBUG_ASSERT(b->bh.bb.bsize > 0);
1152 *totfree += b->bh.bb.bsize;
1153 if (b->bh.bb.bsize > *maxfree) {
1154 *maxfree = b->bh.bb.bsize;
1164 bstatse( kmp_info_t *th, bufsize *pool_incr,
long *npool,
long *npget,
long *nprel,
long *ndget,
long *ndrel)
1166 thr_data_t *thr = get_thr_data( th );
1168 *pool_incr = (thr->pool_len < 0) ? -thr->exp_incr : thr->exp_incr;
1169 *npool = thr->numpblk;
1170 *npget = thr->numpget;
1171 *nprel = thr->numprel;
1172 *ndget = thr->numdget;
1173 *ndrel = thr->numdrel;
1183 bufdump( kmp_info_t *th,
void *buf )
1186 unsigned char *bdump;
1189 b = BFH(((
char *) buf) -
sizeof(bhead_t));
1190 KMP_DEBUG_ASSERT(b->bh.bb.bsize != 0);
1191 if (b->bh.bb.bsize < 0) {
1192 bdump = (
unsigned char *) buf;
1193 bdlen = (-b->bh.bb.bsize) - (bufsize)
sizeof(bhead_t);
1195 bdump = (
unsigned char *) (((
char *) b) +
sizeof(bfhead_t));
1196 bdlen = b->bh.bb.bsize - (bufsize)
sizeof(bfhead_t);
1202 char bhex[50], bascii[20];
1208 for (i = 0; i < l; i++) {
1209 (void) sprintf(bhex + i * 3,
"%02X ", bdump[i]);
1210 if (bdump[i] > 0x20 && bdump[i] < 0x7F)
1211 bascii[ i ] = bdump[ i ];
1216 (void) __kmp_printf_no_lock(
"%-48s %s\n", bhex, bascii);
1219 while ((bdlen > 16) && (memcmp((
char *) (bdump - 16),
1220 (
char *) bdump, 16) == 0)) {
1226 (void) __kmp_printf_no_lock(
1227 " (%d lines [%d bytes] identical to above line skipped)\n",
1229 }
else if (dupes == 1) {
1243 bpoold( kmp_info_t *th,
void *buf,
int dumpalloc,
int dumpfree)
1245 bfhead_t *b = BFH( (
char*)buf -
sizeof(bhead_t));
1247 while (b->bh.bb.bsize != ESent) {
1248 bufsize bs = b->bh.bb.bsize;
1252 (void) __kmp_printf_no_lock(
"Allocated buffer: size %6ld bytes.\n", (
long) bs);
1254 bufdump( th, (
void *) (((
char *) b) +
sizeof(bhead_t)));
1259 KMP_DEBUG_ASSERT(bs > 0);
1260 if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b)) {
1261 lerr =
" (Bad free list links)";
1263 (void) __kmp_printf_no_lock(
"Free block: size %6ld bytes.%s\n",
1266 lerr = ((
char *) b) +
sizeof(bfhead_t);
1267 if ((bs >
sizeof(bfhead_t)) && ((*lerr != 0x55) ||
1268 (memcmp(lerr, lerr + 1,
1269 (
size_t) (bs - (
sizeof(bfhead_t) + 1))) != 0))) {
1270 (void) __kmp_printf_no_lock(
1271 "(Contents of above free block have been overstored.)\n");
1272 bufdump( th, (
void *) (((
char *) b) +
sizeof(bhead_t)));
1276 bufdump( th, (
void *) (((
char *) b) +
sizeof(bhead_t)));
1279 b = BFH(((
char *) b) + bs);
1286 bpoolv( kmp_info_t *th,
void *buf )
1288 bfhead_t *b = BFH(buf);
1290 while (b->bh.bb.bsize != ESent) {
1291 bufsize bs = b->bh.bb.bsize;
1300 KMP_DEBUG_ASSERT(bs > 0);
1304 if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b)) {
1305 (void) __kmp_printf_no_lock(
"Free block: size %6ld bytes. (Bad free list links)\n",
1307 KMP_DEBUG_ASSERT(0);
1311 lerr = ((
char *) b) +
sizeof(bfhead_t);
1312 if ((bs >
sizeof(bfhead_t)) && ((*lerr != 0x55) ||
1313 (memcmp(lerr, lerr + 1,
1314 (
size_t) (bs - (
sizeof(bfhead_t) + 1))) != 0))) {
1315 (void) __kmp_printf_no_lock(
1316 "(Contents of above free block have been overstored.)\n");
1317 bufdump( th, (
void *) (((
char *) b) +
sizeof(bhead_t)));
1318 KMP_DEBUG_ASSERT(0);
1323 b = BFH(((
char *) b) + bs);
1333 __kmp_initialize_bget( kmp_info_t *th )
1335 KMP_DEBUG_ASSERT( SizeQuant >=
sizeof(
void * ) && (th != 0) );
1339 bectl( th, (bget_compact_t) 0, (bget_acquire_t) malloc, (bget_release_t) free,
1340 (bufsize) __kmp_malloc_pool_incr );
1344 __kmp_finalize_bget( kmp_info_t *th )
1349 KMP_DEBUG_ASSERT( th != 0 );
1352 thr = (thr_data_t *) th->th.th_local.bget_data;
1353 KMP_DEBUG_ASSERT( thr != NULL );
1362 if (thr->relfcn != 0 && b != 0 && thr->numpblk != 0 &&
1363 b->bh.bb.bsize == (bufsize)(thr->pool_len -
sizeof(bhead_t)))
1365 KMP_DEBUG_ASSERT(b->bh.bb.prevfree == 0);
1366 KMP_DEBUG_ASSERT(BH((
char *) b + b->bh.bb.bsize)->bb.bsize == ESent);
1367 KMP_DEBUG_ASSERT(BH((
char *) b + b->bh.bb.bsize)->bb.prevfree == b->bh.bb.bsize);
1370 __kmp_bget_remove_from_freelist( b );
1372 KE_TRACE( 10, (
"%%%%%% FREE( %p )\n", (
void *) b ) );
1377 KMP_DEBUG_ASSERT(thr->numpblk == thr->numpget - thr->numprel);
1382 if ( th->th.th_local.bget_data != NULL ) {
1383 __kmp_free( th->th.th_local.bget_data );
1384 th->th.th_local.bget_data = NULL;
1389 kmpc_set_poolsize(
size_t size )
1391 bectl( __kmp_get_thread(), (bget_compact_t) 0, (bget_acquire_t) malloc,
1392 (bget_release_t) free, (bufsize) size );
1396 kmpc_get_poolsize(
void )
1400 p = get_thr_data( __kmp_get_thread() );
1406 kmpc_set_poolmode(
int mode )
1410 if (mode == bget_mode_fifo || mode == bget_mode_lifo || mode == bget_mode_best) {
1411 p = get_thr_data( __kmp_get_thread() );
1412 p->mode = (bget_mode_t) mode;
1417 kmpc_get_poolmode(
void )
1421 p = get_thr_data( __kmp_get_thread() );
1427 kmpc_get_poolstat(
size_t *maxmem,
size_t *allmem )
1429 kmp_info_t *th = __kmp_get_thread();
1432 __kmp_bget_dequeue( th );
1434 bcheck( th, &a, &b );
1441 kmpc_poolprint(
void )
1443 kmp_info_t *th = __kmp_get_thread();
1445 __kmp_bget_dequeue( th );
1450 #endif // #if KMP_USE_BGET
1455 kmpc_malloc(
size_t size )
1458 ptr = bget( __kmp_entry_thread(), (bufsize) size );
1464 kmpc_calloc(
size_t nelem,
size_t elsize )
1467 ptr = bgetz( __kmp_entry_thread(), (bufsize) (nelem * elsize) );
1473 kmpc_realloc(
void * ptr,
size_t size )
1475 void * result = NULL;
1477 if ( ptr == NULL ) {
1479 result = bget( __kmp_entry_thread(), (bufsize) size );
1480 }
else if ( size == 0 ) {
1484 brel( __kmp_get_thread(), ptr );
1486 result = bgetr( __kmp_entry_thread(), ptr, (bufsize) size );
1495 kmpc_free(
void * ptr )
1497 if ( ! __kmp_init_serial ) {
1500 if ( ptr != NULL ) {
1501 kmp_info_t *th = __kmp_get_thread();
1502 __kmp_bget_dequeue( th );
1511 ___kmp_thread_malloc( kmp_info_t *th,
size_t size KMP_SRC_LOC_DECL )
1515 "-> __kmp_thread_malloc( %p, %d ) called from %s:%d\n",
1520 ptr = bget( th, (bufsize) size );
1521 KE_TRACE( 30, (
"<- __kmp_thread_malloc() returns %p\n", ptr ) );
1526 ___kmp_thread_calloc( kmp_info_t *th,
size_t nelem,
size_t elsize KMP_SRC_LOC_DECL )
1530 "-> __kmp_thread_calloc( %p, %d, %d ) called from %s:%d\n",
1536 ptr = bgetz( th, (bufsize) (nelem * elsize) );
1537 KE_TRACE( 30, (
"<- __kmp_thread_calloc() returns %p\n", ptr ) );
1542 ___kmp_thread_realloc( kmp_info_t *th,
void *ptr,
size_t size KMP_SRC_LOC_DECL )
1545 "-> __kmp_thread_realloc( %p, %p, %d ) called from %s:%d\n",
1551 ptr = bgetr( th, ptr, (bufsize) size );
1552 KE_TRACE( 30, (
"<- __kmp_thread_realloc() returns %p\n", ptr ) );
1557 ___kmp_thread_free( kmp_info_t *th,
void *ptr KMP_SRC_LOC_DECL )
1560 "-> __kmp_thread_free( %p, %p ) called from %s:%d\n",
1565 if ( ptr != NULL ) {
1566 __kmp_bget_dequeue( th );
1569 KE_TRACE( 30, (
"<- __kmp_thread_free()\n" ) );
1580 struct kmp_mem_descr {
1581 void * ptr_allocated;
1582 size_t size_allocated;
1584 size_t size_aligned;
1586 typedef struct kmp_mem_descr kmp_mem_descr_t;
1595 ___kmp_allocate_align(
size_t size,
size_t alignment KMP_SRC_LOC_DECL )
1614 kmp_mem_descr_t descr;
1615 kmp_uintptr_t addr_allocated;
1616 kmp_uintptr_t addr_aligned;
1617 kmp_uintptr_t addr_descr;
1620 "-> ___kmp_allocate_align( %d, %d ) called from %s:%d\n",
1626 KMP_DEBUG_ASSERT( alignment < 32 * 1024 );
1627 KMP_DEBUG_ASSERT(
sizeof(
void * ) <=
sizeof( kmp_uintptr_t ) );
1630 descr.size_aligned = size;
1631 descr.size_allocated = descr.size_aligned +
sizeof( kmp_mem_descr_t ) + alignment;
1634 descr.ptr_allocated = _malloc_src_loc( descr.size_allocated, _file_, _line_ );
1636 descr.ptr_allocated = malloc_src_loc( descr.size_allocated KMP_SRC_LOC_PARM );
1639 " malloc( %d ) returned %p\n",
1640 (
int) descr.size_allocated,
1643 if ( descr.ptr_allocated == NULL ) {
1644 KMP_FATAL( OutOfHeapMemory );
1647 addr_allocated = (kmp_uintptr_t) descr.ptr_allocated;
1649 ( addr_allocated +
sizeof( kmp_mem_descr_t ) + alignment )
1650 & ~ ( alignment - 1 );
1651 addr_descr = addr_aligned -
sizeof( kmp_mem_descr_t );
1653 descr.ptr_aligned = (
void *) addr_aligned;
1656 " ___kmp_allocate_align: "
1657 "ptr_allocated=%p, size_allocated=%d, "
1658 "ptr_aligned=%p, size_aligned=%d\n",
1659 descr.ptr_allocated,
1660 (
int) descr.size_allocated,
1662 (
int) descr.size_aligned
1665 KMP_DEBUG_ASSERT( addr_allocated <= addr_descr );
1666 KMP_DEBUG_ASSERT( addr_descr +
sizeof( kmp_mem_descr_t ) == addr_aligned );
1667 KMP_DEBUG_ASSERT( addr_aligned + descr.size_aligned <= addr_allocated + descr.size_allocated );
1668 KMP_DEBUG_ASSERT( addr_aligned % alignment == 0 );
1671 memset( descr.ptr_allocated, 0xEF, descr.size_allocated );
1674 memset( descr.ptr_aligned, 0x00, descr.size_aligned );
1678 * ( (kmp_mem_descr_t *) addr_descr ) = descr;
1682 KE_TRACE( 25, (
"<- ___kmp_allocate_align() returns %p\n", descr.ptr_aligned ) );
1683 return descr.ptr_aligned;
1695 ___kmp_allocate(
size_t size KMP_SRC_LOC_DECL )
1699 KE_TRACE( 25, (
"-> __kmp_allocate( %d ) called from %s:%d\n", (
int) size KMP_SRC_LOC_PARM ) );
1700 ptr = ___kmp_allocate_align( size, __kmp_align_alloc KMP_SRC_LOC_PARM );
1701 KE_TRACE( 25, (
"<- __kmp_allocate() returns %p\n", ptr ) );
1706 #if (BUILD_MEMORY==FIRST_TOUCH)
1708 __kmp_ft_page_allocate(
size_t size)
1713 int page_size = getpagesize();
1716 int page_size = PAGE_SIZE;
1719 adr = (
void *) __kmp_thread_malloc( __kmp_get_thread(),
1720 size + page_size + KMP_PTR_SKIP);
1722 KMP_FATAL( OutOfHeapMemory );
1725 if ( ( (kmp_uintptr_t) adr & (page_size - 1)) == 0)
1730 aadr = (
void *) ( ( (kmp_uintptr_t) adr + page_size) & ~(page_size - 1) );
1733 *((
void**)aadr) = adr;
1736 return (
void*)((
char*)aadr + KMP_PTR_SKIP);
1747 ___kmp_page_allocate(
size_t size KMP_SRC_LOC_DECL )
1749 int page_size = 8 * 1024;
1753 "-> __kmp_page_allocate( %d ) called from %s:%d\n",
1757 ptr = ___kmp_allocate_align( size, page_size KMP_SRC_LOC_PARM );
1758 KE_TRACE( 25, (
"<- __kmp_page_allocate( %d ) returns %p\n", (
int) size, ptr ) );
1767 ___kmp_free(
void * ptr KMP_SRC_LOC_DECL )
1770 kmp_mem_descr_t descr;
1771 kmp_uintptr_t addr_allocated;
1772 kmp_uintptr_t addr_aligned;
1774 KE_TRACE( 25, (
"-> __kmp_free( %p ) called from %s:%d\n", ptr KMP_SRC_LOC_PARM ) );
1775 KMP_ASSERT( ptr != NULL );
1777 descr = * ( kmp_mem_descr_t *) ( (kmp_uintptr_t) ptr -
sizeof( kmp_mem_descr_t ) );
1779 KE_TRACE( 26, (
" __kmp_free: "
1780 "ptr_allocated=%p, size_allocated=%d, "
1781 "ptr_aligned=%p, size_aligned=%d\n",
1782 descr.ptr_allocated, (
int) descr.size_allocated,
1783 descr.ptr_aligned, (
int) descr.size_aligned ));
1785 addr_allocated = (kmp_uintptr_t) descr.ptr_allocated;
1786 addr_aligned = (kmp_uintptr_t) descr.ptr_aligned;
1788 KMP_DEBUG_ASSERT( addr_aligned % CACHE_LINE == 0 );
1789 KMP_DEBUG_ASSERT( descr.ptr_aligned == ptr );
1790 KMP_DEBUG_ASSERT( addr_allocated +
sizeof( kmp_mem_descr_t ) <= addr_aligned );
1791 KMP_DEBUG_ASSERT( descr.size_aligned < descr.size_allocated );
1792 KMP_DEBUG_ASSERT( addr_aligned + descr.size_aligned <= addr_allocated + descr.size_allocated );
1795 memset( descr.ptr_allocated, 0xEF, descr.size_allocated );
1800 KE_TRACE( 10, (
" free( %p )\n", descr.ptr_allocated ) );
1801 free_src_loc( descr.ptr_allocated KMP_SRC_LOC_PARM );
1806 KE_TRACE( 25, (
"<- __kmp_free() returns\n" ) );
1813 #if USE_FAST_MEMORY == 3
1819 static int const __kmp_free_list_limit = 16;
1822 #define DCACHE_LINE 128
1825 ___kmp_fast_allocate( kmp_info_t *this_thr,
size_t size KMP_SRC_LOC_DECL )
1833 kmp_mem_descr_t * descr;
1835 KE_TRACE( 25, (
"-> __kmp_fast_allocate( T#%d, %d ) called from %s:%d\n",
1836 __kmp_gtid_from_thread(this_thr), (
int) size KMP_SRC_LOC_PARM ) );
1838 num_lines = ( size + DCACHE_LINE - 1 ) / DCACHE_LINE;
1839 idx = num_lines - 1;
1840 KMP_DEBUG_ASSERT( idx >= 0 );
1844 }
else if ( ( idx >>= 2 ) == 0 ) {
1847 }
else if ( ( idx >>= 2 ) == 0 ) {
1850 }
else if ( ( idx >>= 2 ) == 0 ) {
1857 ptr = this_thr->th.th_free_lists[index].th_free_list_self;
1858 if ( ptr != NULL ) {
1860 this_thr->th.th_free_lists[index].th_free_list_self = *((
void **)ptr);
1861 KMP_DEBUG_ASSERT( this_thr ==
1862 ((kmp_mem_descr_t *)( (kmp_uintptr_t)ptr -
sizeof(kmp_mem_descr_t) ))->ptr_aligned );
1865 ptr = TCR_SYNC_PTR( this_thr->th.th_free_lists[index].th_free_list_sync );
1866 if ( ptr != NULL ) {
1869 while ( ! KMP_COMPARE_AND_STORE_PTR(
1870 &this_thr->th.th_free_lists[index].th_free_list_sync, ptr, NULL ) )
1873 ptr = TCR_SYNC_PTR( this_thr->th.th_free_lists[index].th_free_list_sync );
1876 this_thr->th.th_free_lists[index].th_free_list_self = *((
void **)ptr);
1877 KMP_DEBUG_ASSERT( this_thr ==
1878 ((kmp_mem_descr_t *)( (kmp_uintptr_t)ptr -
sizeof(kmp_mem_descr_t) ))->ptr_aligned );
1884 size = num_lines * DCACHE_LINE;
1886 alloc_size = size +
sizeof( kmp_mem_descr_t ) + DCACHE_LINE;
1887 KE_TRACE( 25, (
"__kmp_fast_allocate: T#%d Calling __kmp_thread_malloc with alloc_size %d\n",
1888 __kmp_gtid_from_thread( this_thr ), alloc_size ) );
1889 alloc_ptr = bget( this_thr, (bufsize) alloc_size );
1892 ptr = (
void *)(( ((kmp_uintptr_t)alloc_ptr) +
sizeof(kmp_mem_descr_t) + DCACHE_LINE ) & ~( DCACHE_LINE - 1 ));
1893 descr = (kmp_mem_descr_t *)( ((kmp_uintptr_t)ptr) -
sizeof(kmp_mem_descr_t) );
1895 descr->ptr_allocated = alloc_ptr;
1897 descr->ptr_aligned = (
void *)this_thr;
1900 descr->size_aligned = size;
1903 KE_TRACE( 25, (
"<- __kmp_fast_allocate( T#%d ) returns %p\n",
1904 __kmp_gtid_from_thread( this_thr ), ptr ) );
1911 ___kmp_fast_free( kmp_info_t *this_thr,
void * ptr KMP_SRC_LOC_DECL )
1913 kmp_mem_descr_t * descr;
1914 kmp_info_t * alloc_thr;
1919 KE_TRACE( 25, (
"-> __kmp_fast_free( T#%d, %p ) called from %s:%d\n",
1920 __kmp_gtid_from_thread(this_thr), ptr KMP_SRC_LOC_PARM ) );
1921 KMP_ASSERT( ptr != NULL );
1923 descr = (kmp_mem_descr_t *)( ((kmp_uintptr_t)ptr) -
sizeof(kmp_mem_descr_t) );
1925 KE_TRACE(26, (
" __kmp_fast_free: size_aligned=%d\n",
1926 (
int) descr->size_aligned ) );
1928 size = descr->size_aligned;
1930 idx = DCACHE_LINE * 2;
1931 if ( idx == size ) {
1933 }
else if ( ( idx <<= 1 ) == size ) {
1935 }
else if ( ( idx <<= 2 ) == size ) {
1937 }
else if ( ( idx <<= 2 ) == size ) {
1940 KMP_DEBUG_ASSERT( size > DCACHE_LINE * 64 );
1944 alloc_thr = (kmp_info_t *)descr->ptr_aligned;
1945 if ( alloc_thr == this_thr ) {
1947 *((
void **)ptr) = this_thr->th.th_free_lists[index].th_free_list_self;
1948 this_thr->th.th_free_lists[index].th_free_list_self = ptr;
1950 void * head = this_thr->th.th_free_lists[index].th_free_list_other;
1951 if ( head == NULL ) {
1953 this_thr->th.th_free_lists[index].th_free_list_other = ptr;
1954 *((
void **)ptr) = NULL;
1955 descr->size_allocated = (size_t)1;
1958 kmp_mem_descr_t * dsc = (kmp_mem_descr_t *)( (
char*)head -
sizeof(kmp_mem_descr_t) );
1959 kmp_info_t * q_th = (kmp_info_t *)(dsc->ptr_aligned);
1960 size_t q_sz = dsc->size_allocated + 1;
1961 if ( q_th == alloc_thr && q_sz <= __kmp_free_list_limit ) {
1963 *((
void **)ptr) = head;
1964 descr->size_allocated = q_sz;
1965 this_thr->th.th_free_lists[index].th_free_list_other = ptr;
1972 void * next = *((
void **)head);
1973 while ( next != NULL ) {
1976 ((kmp_mem_descr_t*)((
char*)next -
sizeof(kmp_mem_descr_t)))->size_allocated + 1 ==
1977 ((kmp_mem_descr_t*)((
char*)tail -
sizeof(kmp_mem_descr_t)))->size_allocated );
1979 next = *((
void **)next);
1981 KMP_DEBUG_ASSERT( q_th != NULL );
1983 old_ptr = TCR_PTR( q_th->th.th_free_lists[index].th_free_list_sync );
1986 *((
void **)tail) = old_ptr;
1989 #if defined(USE_ITT)
1990 KMP_FSYNC_RELEASING( & q_th->th.th_free_lists[index].th_free_list_sync );
1993 while ( ! KMP_COMPARE_AND_STORE_PTR(
1994 &q_th->th.th_free_lists[index].th_free_list_sync,
1999 old_ptr = TCR_PTR( q_th->th.th_free_lists[index].th_free_list_sync );
2000 *((
void **)tail) = old_ptr;
2001 #if defined(USE_ITT)
2002 KMP_FSYNC_RELEASING( & q_th->th.th_free_lists[index].th_free_list_sync );
2007 this_thr->th.th_free_lists[index].th_free_list_other = ptr;
2008 *((
void **)ptr) = NULL;
2009 descr->size_allocated = (size_t)1;
2016 KE_TRACE(25, (
"__kmp_fast_free: T#%d Calling __kmp_thread_free for size %d\n",
2017 __kmp_gtid_from_thread( this_thr), size ) );
2018 __kmp_bget_dequeue( this_thr );
2019 brel( this_thr, descr->ptr_allocated );
2022 KE_TRACE( 25, (
"<- __kmp_fast_free() returns\n" ) );
2030 __kmp_initialize_fast_memory( kmp_info_t *this_thr )
2032 KE_TRACE(10, (
"__kmp_initialize_fast_memory: Called from th %p\n", this_thr ) );
2034 memset ( this_thr->th.th_free_lists, 0, NUM_LISTS *
sizeof( kmp_free_list_t ) );
2040 __kmp_free_fast_memory( kmp_info_t *th )
2044 thr_data_t * thr = get_thr_data( th );
2047 KE_TRACE(5, (
"__kmp_free_fast_memory: Called T#%d\n",
2048 __kmp_gtid_from_thread( th ) ) );
2050 __kmp_bget_dequeue( th );
2053 for ( bin = 0; bin < MAX_BGET_BINS; ++bin ) {
2054 bfhead_t * b = thr->freelist[ bin ].ql.flink;
2055 while ( b != &thr->freelist[ bin ] ) {
2056 if ( (kmp_uintptr_t)b->bh.bb.bthr & 1 ) {
2063 while ( lst != NULL ) {
2065 KE_TRACE(10, (
"__kmp_free_fast_memory: freeing %p, next=%p th %p (%d)\n",
2066 lst, next, th, __kmp_gtid_from_thread( th ) ) );
2067 (*thr->relfcn)(lst);
2076 KE_TRACE(5, (
"__kmp_free_fast_memory: Freed T#%d\n",
2077 __kmp_gtid_from_thread( th ) ) );
2080 #endif // USE_FAST_MEMORY