39 #define IA32_LINUX_GCC
51 #ifdef PPC32_LINUX_GCC
72 #ifdef PPC64_LINUX_GCC
79 #ifdef AMD64_LINUX_GCC
98 #ifdef SPARC32_SOLARIS_SCC
112 #define MIN(x,y) ((x)<=(y)?(x):(y))
115 mmap(0,size,PROT_READ|PROT_WRITE,MAP_ANON|MAP_PRIVATE,-1,0)
117 #if defined(X86) || defined(SPARC)
124 #define ASSERT(x) if (!(x)) { debug(); assert(x);}
134 #if defined(X86) || defined(SPARC)
136 #define rc_ret_t char
139 #define rc_ret_t unsigned
144 #define ISYNC IFUNI asm volatile ("isync")
145 #define LWSYNC IFUNI asm volatile ("lwsync")
151 #define LL64(ret,addr) asm volatile ("ldarx %0,0,%1;":"=r"(ret):"r"(addr))
152 #define LL32(ret,addr) asm volatile ("lwarx %0,0,%1;":"=r"(ret):"r"(addr))
153 #define SC64(ret,addr,new_val) \
155 " stdcx. %2,0,%1;\n" \
157 " andis. %0,%0,0x2000;" \
158 : "=r"(ret):"r"(addr),"r"(new_val) \
160 #define SC32(ret,addr,new_val) \
162 " stwcx. %2,0,%1;\n" \
164 " andis. %0,%0,0x2000;" \
165 : "=r"(ret):"r"(addr),"r"(new_val) \
167 #define CAS64(ret,addr,expval,new_val) \
169 unsigned long long oldval; \
171 if (oldval != (unsigned long long)expval) { ret = 0; break; } \
172 SC64(ret,addr,new_val); \
174 #define CAS32(ret,addr,expval,new_val) \
178 if (oldval != (unsigned)expval) { ret = 0; break; } \
179 SC32(ret,addr,new_val); \
184 #define LL(ret,addr) LL64(ret,addr)
185 #define SC(ret,addr,new_val) SC64(ret,addr,new_val)
186 #define CAS(ret,addr,expval,new_val) CAS64(ret,addr,expval,new_val)
187 #define ptrsize_t unsigned long
191 #define LL(ret,addr) LL32(ret,addr)
192 #define SC(ret,addr,new_val) SC32(ret,addr,new_val)
193 #define CAS(ret,addr,expval,new_val) CAS32(ret,addr,expval,new_val)
194 #define ptrsize_t unsigned
198 #define anchorsize_t ptrsize_t
199 #define LLA(ret,addr) LL(ret,addr)
200 #define SCA(ret,addr,expval,new_val) SC(ret,addr,new_val)
204 #define CAS32(ret,addr,expval,new_val) \
205 __asm__ __volatile__( \
206 "lock; cmpxchg %2, %1; setz %0;\n" \
207 : "=a"(ret), "=m"(*(addr)) \
208 : "r" (new_val), "a"(expval) \
211 char cas64(
unsigned long long volatile * addr,
212 unsigned long long oval,
213 unsigned long long nval);
215 #define CAS64(ret,addr,expval,new_val) \
216 ret = cas64((unsigned long long volatile *)addr, \
217 (unsigned long long)expval, \
218 (unsigned long long)new_val)
230 #define ptrsize_t unsigned long
231 #define CAS(ret,addr,expval,new_val) CAS32(ret,addr,expval,new_val)
232 #define LLA(ret,addr) ret = *(addr);
233 #define SCA(ret,addr,expval,new_val) CAS32(ret,addr,expval,new_val)
234 #define anchorsize_t unsigned long
238 #define ptrsize_t unsigned long long
239 #define CAS(ret,addr,expval,new_val) CAS64(ret,addr,expval,new_val)
240 #define LLA(ret,addr) ret = *(addr);
241 #define SCA(ret,addr,expval,new_val) CAS64(ret,addr,expval,new_val)
242 #define anchorsize_t unsigned long long
248 #define CAS32(ret,addr,expval,new_val) \
249 ret = cas32((unsigned volatile *)addr,(unsigned)expval,(unsigned)new_val)
251 static char cas32(
unsigned volatile * addr,
unsigned expval,
unsigned new_val) {
253 "casa [%2] 0x80, %3, %1\n" \
254 :
"+m"(*(addr)),
"+r"(new_val) \
255 :
"r"(addr),
"r" (expval) \
257 return (new_val == expval);
260 #define CAS64(ret,addr,expval,new_val) \
261 ret = cas64((unsigned long long volatile *)addr,(unsigned long long)expval,(unsigned long long)new_val)
263 static char cas64(
unsigned long long volatile * addr,
unsigned long long expval,
unsigned long long new_val) {
265 "casxa [%2] 0x80, %3, %1\n" \
266 :
"+m"(*(addr)),
"+r"(new_val) \
267 :
"r"(addr),
"r" (expval) \
269 return (new_val == expval);
275 #define RBR IFUNI asm volatile ("membar #LoadLoad")
276 #define RBW IFUNI asm volatile ("membar #LoadStore")
277 #define WBW IFUNI asm volatile ("membar #StoreStore")
281 #define ptrsize_t unsigned
282 #define CAS(ret,addr,expval,new_val) CAS32(ret,addr,expval,new_val)
283 #define LLA(ret,addr) ret = *(addr);
284 #define SCA(ret,addr,expval,new_val) CAS32(ret,addr,expval,new_val)
285 #define anchorsize_t unsigned
289 #define ptrsize_t unsigned long long
290 #define CAS(ret,addr,expval,new_val) CAS64(ret,addr,expval,new_val)
291 #define LLA(ret,addr) ret = *(addr);
292 #define SCA(ret,addr,expval,new_val) CAS64(ret,addr,expval,new_val)
293 #define anchorsize_t unsigned long long
298 #error architecture not defined
301 #if defined(X86) || defined(SPARC)
304 #define aret_t void *
307 #define FAA(oldval,addr,val) \
312 new_val = (ptrsize_t)oldval + val; \
313 CAS(ret,addr,new_val); \
318 #define SAFE_READ(x) rc_safe_read(&x)
319 #define DESC_RETIRE(x) rc_desc_release(x)
320 #define RC_INIT(x) x->rc = 1
321 #define RC_RELEASE(x) rc_desc_release(x)
331 anchorsize_t tag : 8 *
sizeof (anchorsize_t) - 16;
337 typedef struct desc {
339 struct desc *
volatile Next;
342 struct desc *
volatile Pdesc;
343 struct desc *
volatile Ptr;
357 desc_t *
volatile Partial;
359 char pad[32 - 3 *
sizeof (
void*) ];
365 desc_t *
volatile PartialHead;
366 desc_t *
volatile PartialTail;
367 unsigned numprocheaps;
374 - 4 *
sizeof (unsigned)
378 #define MAXSIZECLASSES 32
386 #define MAXCREDITS 128
387 #define CREDITSMASK 127
388 #define DESCBATCHSIZE 128
389 #define DESCSBSIZE DESCBATCHSIZE*sizeof(desc_t)
390 #define HYPERBLOCKSIZE 1024*1024
391 #define DEFAULTNUMHEAPS 64
392 #define MAXNUMHEAPS 512
393 #define NUMSIZECLASSES 27
397 static unsigned numprocheaps = DEFAULTNUMHEAPS;
398 static unsigned heapidmask;
400 static unsigned scsz[NUMSIZECLASSES] = {
401 16, 24, 32, 40, 48, 64, 80, 96,
402 128, 160, 192, 256, 320, 384, 512, 640,
403 768, 1024, 1280, 2048, 4096, 8192, 16384, 32768,
404 65536, 131072, 262144
407 static desc_t *
volatile DescAvail = NULL;
408 static desc_t *
volatile HyperblockHead = NULL;
411 #define DOTRACE(a,b,c,d,e,f,g) \
415 id = (pthread_self() & 0xf)-1; \
416 i = trace_ind[id][0]++ & TRACEMASK; \
419 tr[id][i].desc = d; \
420 tr[id][i].heap = f; \
421 tr[id][i].anchor.all = g; \
431 #define TRACE(a,b,c,d,e,f,g) std::cout<<a<<","<<b<<","<<c<<","<<d<<","<<e<<","<<f<<","<<g<<"\n";
433 #define TRACE(a,b,c,d,e,f,g)
438 typedef struct trace {
450 #define MAXTRACE 0x8000
451 #define TRACEMASK MAXTRACE-1
452 #define OP_MAKE_ACTIVE 1
453 #define OP_MADE_ACTIVE 2
454 #define OP_NOT_ACTIVE 3
455 #define OP_PARTIAL_STR 4
456 #define OP_PARTIAL_RSRV 5
457 #define OP_PARTIAL_END 6
458 #define OP_new__STR 7
459 #define OP_NOT_new_ 8
460 #define OP_new__END 9
461 #define OP_MALLOC_STR 10
462 #define OP_REGULAR_RSRV 11
463 #define OP_REGULAR_END 12
464 #define OP_FREE_STR 13
465 #define OP_FREE_END 14
466 #define OP_LIST_ENQ_STR 15
467 #define OP_LIST_ENQ_END 16
468 #define OP_PARTIAL_PUSH 17
469 #define OP_PARTIAL_POP_SLT 18
470 #define OP_PARTIAL_POP_LST 19
471 #define OP_PARTIAL_POPPED 20
472 #define OP_DESC_REMOVE_SLT 21
473 #define OP_DESC_REMOVE_LST 22
474 #define OP_DESC_REMOVED 23
475 #define OP_DESC_NOT_REMOVED 24
477 unsigned volatile trace_ind[3][32];
478 ptrsize_t
volatile trace_stop = 0;
479 unsigned volatile trace_dumped = 0;
480 trace_t tr[3][MAXTRACE];
484 unsigned total, i, j, k;
490 printf(
"%d assertion failed .....\n", pthread_self());
491 CAS(ret, &trace_stop, 0, 1);
493 while (!trace_dumped);
496 printf(
"%d dumping trace .....\n", pthread_self());
497 strcpy(trfile,
"trace");
498 fd = fopen(trfile,
"w");
500 for (k = 0; k < 3; k++) {
501 if (trace_ind[k][0] <= MAXTRACE) {
503 total = trace_ind[k][0];
505 j = trace_ind[k][0] % MAXTRACE;
508 printf(
"%d total trace = %lld %d\n", k, trace_ind[k][0], total);
509 for (i = 1; i <= total; i++) {
510 switch (tr[k][j].op) {
511 case OP_MAKE_ACTIVE: strcpy(opstr,
"MAKE_ACTIVE");
513 case OP_MADE_ACTIVE: strcpy(opstr,
"MADE_ACTIVE");
515 case OP_NOT_ACTIVE: strcpy(opstr,
"NOT_ACTIVE");
517 case OP_PARTIAL_STR: strcpy(opstr,
"PARTIAL_STR");
519 case OP_PARTIAL_RSRV: strcpy(opstr,
"PARTIAL_RSRV");
521 case OP_PARTIAL_END: strcpy(opstr,
"PARTIAL_END");
523 case OP_new__STR: strcpy(opstr,
"new__STR");
525 case OP_NOT_new_: strcpy(opstr,
"NOT_new_");
527 case OP_new__END: strcpy(opstr,
"new__END");
529 case OP_MALLOC_STR: strcpy(opstr,
"MALLOC_STR");
531 case OP_REGULAR_RSRV: strcpy(opstr,
"REGULAR_RSRV");
533 case OP_REGULAR_END: strcpy(opstr,
"REGULAR_END");
535 case OP_FREE_STR: strcpy(opstr,
"FREE_STR");
537 case OP_FREE_END: strcpy(opstr,
"FREE_END");
539 case OP_LIST_ENQ_STR: strcpy(opstr,
"LIST_ENQ_STR");
541 case OP_LIST_ENQ_END: strcpy(opstr,
"LIST_ENQ_END");
543 case OP_PARTIAL_PUSH: strcpy(opstr,
"PARTIAL_PUSH");
545 case OP_PARTIAL_POP_SLT: strcpy(opstr,
"PARTIAL_POP_SLT");
547 case OP_PARTIAL_POP_LST: strcpy(opstr,
"PARTIAL_POP_LST");
549 case OP_PARTIAL_POPPED: strcpy(opstr,
"PARTIAL_POPPED");
551 case OP_DESC_REMOVE_SLT: strcpy(opstr,
"DESC_REMOVE_SLT");
553 case OP_DESC_REMOVE_LST: strcpy(opstr,
"DESC_REMOVE_LST");
555 case OP_DESC_REMOVED: strcpy(opstr,
"DESC_REMOVED");
557 case OP_DESC_NOT_REMOVED: strcpy(opstr,
"DESC_NOT_REMOVED");
561 fprintf(fd,
"%5d ", i);
563 fprintf(fd,
"p%d ", k);
564 fprintf(fd,
"sz=%5d ", tr[k][j].sz);
566 fprintf(fd,
"d=%6llx ", (ptrsize_t) tr[k][j].
desc % 0x1000000);
568 fprintf(fd,
"h=%5llx ", (ptrsize_t) tr[k][j].heap % 0x100000);
569 fprintf(fd,
"<%2d,", tr[k][j].
anchor.sep.head);
570 fprintf(fd,
"%05x,", tr[k][j].
anchor.sep.tag % 0x100000);
571 fprintf(fd,
"%2d,", tr[k][j].
anchor.sep.count);
572 fprintf(fd,
"%d,", tr[k][j].
anchor.sep.active);
573 fprintf(fd,
"%d> ", tr[k][j].
anchor.sep.valid);
574 fprintf(fd,
"%s ", opstr);
576 j = (j + 1) % MAXTRACE;
587 void __malloc_start__()
590 __attribute__((constructor)) void clfmalloc_init()
600 assert(
sizeof (
desc_t) == 128);
603 assert(NUMSIZECLASSES <= MAXSIZECLASSES);
607 char * nphstr = getenv(
"CLFMALLOC_NUMHEAPS");
609 int nph = atoi(nphstr);
610 if ((nph >= 1) && (nph <= MAXNUMHEAPS)) {
612 while (numprocheaps < nph)
616 heapidmask = numprocheaps - 1;
619 size = 4096 + numprocheaps * 1024;
621 perror(
"clfmalloc_init mmap failed\n");
624 for (i = 0; i < NUMSIZECLASSES; i++) {
625 sc = &cb->sizeclass[i];
626 sc->PartialHead = NULL;
627 sc->PartialTail = NULL;
630 sc->sbsize = 2 * 1024;
631 }
else if (sc->sz <= 64) {
632 sc->sbsize = 4 * 1024;
633 }
else if (sc->sz <= 128) {
634 sc->sbsize = 8 * 1024;
635 }
else if (sc->sz <= 256) {
636 sc->sbsize = 16 * 1024;
637 }
else if (sc->sz <= 512) {
638 sc->sbsize = 32 * 1024;
639 }
else if (sc->sz <= (32 * 1024)) {
640 sc->sbsize = 64 * 1024;
642 sc->sbsize = HYPERBLOCKSIZE;
644 sc->maxcount = sc->sbsize / sc->sz;
645 if ((i < 20) && (numprocheaps > 1)) {
647 sc->numprocheaps = numprocheaps;
648 for (j = 0; j < sc->numprocheaps; j++) {
649 cb->procheap[j][i].Active = NULL;
650 cb->procheap[j][i].Partial = NULL;
651 cb->procheap[j][i].sc = sc;
654 sc->numprocheaps = 1;
655 sc->procheap.Active = NULL;
656 sc->procheap.Partial = NULL;
657 sc->procheap.sc = sc;
662 CAS(ret, &controlblock, NULL, cb);
664 if (munmap((
void *) cb, size)) {
665 perror(
"clfmalloc_init munmap failed\n");
674 desc_t * head = DescAvail;
678 CAS(ret, &DescAvail, head, desc);
684 static void rc_desc_release(
desc_t * desc) {
694 CAS32(ret, &desc->rc, old, new_);
702 CAS32(ret, &desc->rc, old, new_);
709 static desc_t * rc_safe_read(
desc_t *
volatile * addr) {
716 if (desc == NULL)
return NULL;
721 CAS32(ret, &desc->rc, old, new_);
723 if (old == 0)
continue;
726 if (desc == *addr)
return desc;
727 rc_desc_release(desc);
733 static desc_t * desc_alloc() {
738 desc = SAFE_READ(DescAvail);
740 desc_t * next = desc->Next;
741 CAS(ret, &DescAvail, desc, next);
748 if ((desc = (
desc_t *) MMAP(DESCSBSIZE)) == MAP_FAILED) {
749 perror(
"desc_alloc mmap failed\n");
753 (ptrsize_t) (ptr + 1)<(ptrsize_t) (desc) + DESCSBSIZE;
762 CAS(ret, &DescAvail, NULL, (
desc_t *) (desc + 1));
765 if (munmap((
void *) desc, DESCSBSIZE)) {
766 perror(
"desc_alloc munmap failed\n");
770 desc->Ptr = (
desc_t *) 0xfedcba98;
775 static void * super_malloc(
unsigned sz);
776 static void super_free(
void * ptr);
779 static void sb_alloc(
desc_t * desc) {
786 if (sc->sbsize < HYPERBLOCKSIZE) {
788 addr = (
void**) super_malloc(sc->sbsize - EIGHT);
789 num = (ptrsize_t) addr;
792 desc->Pdesc = *(
desc_t**) addr;
801 head = SAFE_READ(HyperblockHead);
804 CAS(ret, &HyperblockHead, head, next);
807 addr = (
void**) head->SB;
812 ASSERT(sc->sbsize == 0x100000);
813 if ((addr = (
void **) MMAP(sc->sbsize)) == MAP_FAILED) {
814 perror(
"sb_alloc mmap failed\n");
828 num1 = (ptrsize_t) addr;
829 for (i = 0; i < sc->maxcount; i++) {
833 ptr2 = (
unsigned*) num2;
842 static void sb_dealloc(
void * sb,
desc_t * pdesc) {
846 sb = (
char*) sb + EIGHT;
852 desc_t * desc = desc_alloc();
856 head = HyperblockHead;
860 CAS(ret, &HyperblockHead, head, desc);
871 desc_t * aux = desc_alloc();
874 desc_t * head = sc->PartialHead;
878 CAS(ret, &sc->PartialHead, head, aux);
880 TRACE(OP_LIST_ENQ_END, desc->sz, 0, desc, desc->SB, desc->Heap, desc->Anchor.all);
888 TRACE(OP_PARTIAL_POP_LST, 0, 0, 0, 0, 0, 0);
890 desc_t * head = SAFE_READ(sc->PartialHead);
893 desc_t * next = head->Next;
895 CAS(ret, &sc->PartialHead, head, next);
903 TRACE(OP_PARTIAL_POPPED, desc->sz, 0, desc, desc->SB, desc->Heap, desc->Anchor.all);
917 desc2 = heap->Partial;
918 CAS(ret, &heap->Partial, desc2, desc);
920 TRACE(OP_PARTIAL_PUSH, desc->sz, 0, desc, desc->SB, heap, desc->Anchor.all);
923 if (!desc2->Anchor.sep.valid) {
926 list_enqueue(heap->sc, desc2);
933 TRACE(OP_PARTIAL_POP_SLT, 0, 0, 0, 0, heap, 0);
937 desc_t * desc = heap->Partial;
940 CAS(ret, &heap->Partial, desc, NULL);
946 return list_pop(heap->sc);
950 static void list_desc_remove(
procheap_t * heap) {
956 static void list_enqueue(
desc_t * desc) {
970 tail = sc->PartialTail;
972 LL(tail, &sc->PartialTail);
975 SC(ret, &sc->PartialTail, desc);
978 CAS(ret, &sc->PartialHead, NULL, desc);
982 if (sc->PartialHead == NULL) {
983 LL(head, &sc->PartialHead);
987 if (sc->PartialTail != tail)
989 SC(ret, &sc->PartialHead, tail);
996 LL(ret, &sc->PartialTail);
1000 if (tail->Next != next)
1002 SC(ret, &sc->PartialTail, next);
1006 LL(next, &tail->Next);
1010 if (sc->PartialTail != tail)
1012 SC(ret, &tail->Next, desc);
1015 LL(ret, &sc->PartialTail);
1019 if (tail->Next != desc)
1021 SC(ret, &sc->PartialTail, desc);
1024 TRACE(OP_LIST_ENQ_END, desc->sz, 0, desc, desc->SB, desc->Heap, desc->Anchor.all);
1036 LL(desc2, &heap->Partial);
1037 SC(ret, &heap->Partial, desc);
1039 TRACE(OP_PARTIAL_PUSH, desc->sz, 0, desc, desc->SB, heap, desc->Anchor.all);
1041 if (!desc2->Anchor.sep.valid) {
1045 list_enqueue(desc2);
1057 TRACE(OP_PARTIAL_POP_SLT, 0, 0, 0, 0, heap, 0);
1061 LL(desc, &heap->Partial);
1064 SC(ret, &heap->Partial, NULL);
1076 TRACE(OP_PARTIAL_POP_LST, 0, 0, 0, 0, heap, 0);
1079 LL(desc, &sc->PartialHead);
1084 if (!desc->Anchor.sep.valid)
1088 desc2 = desc_alloc();
1089 desc2->Anchor.sep.valid = FALSE;
1091 list_enqueue(desc2);
1096 if (sc->PartialTail == desc) {
1098 LL(ret, &sc->PartialTail);
1102 if (desc->Next != next)
1104 SC(ret, &sc->PartialTail, next);
1107 SC(ret, &sc->PartialHead, next);
1112 TRACE(OP_PARTIAL_POPPED, desc->sz, 0, desc, desc->SB, heap, desc->Anchor.all);
1117 static void list_desc_remove(
procheap_t * heap) {
1122 unsigned nonempty = 0;
1124 TRACE(OP_DESC_REMOVE_SLT, 0, 0, 0, 0, heap, 0);
1128 LL(head, &heap->Partial);
1131 if (head->Anchor.sep.valid)
1133 SC(ret, &heap->Partial, NULL);
1136 if (head->Anchor.sep.valid) {
1138 partial_push(heap, head);
1142 TRACE(OP_DESC_REMOVED, head->sz, 0, head, head->SB, heap, head->Anchor.all);
1149 TRACE(OP_DESC_REMOVE_LST, 0, 0, 0, 0, heap, 0);
1152 LL(head, &sc->PartialHead);
1159 if (sc->PartialTail != head) {
1161 if (head->Next != next)
1163 SC(ret, &sc->PartialHead, next);
1165 if (head->Anchor.sep.valid) {
1167 ASSERT(head->Heap->sc);
1173 TRACE(OP_DESC_REMOVED, head->sz, 0, head, head->SB, heap, head->Anchor.all);
1180 LL(ret, &sc->PartialTail);
1184 if (head->Next != next)
1186 SC(ret, &sc->PartialTail, next);
1189 TRACE(OP_DESC_NOT_REMOVED, 0, 0, 0, 0, heap, 0);
1197 static void make_active(
procheap_t * heap,
desc_t * desc,
unsigned morecredits) {
1198 ptrsize_t new_active;
1203 TRACE(OP_MAKE_ACTIVE, desc->sz, 0, desc, desc->SB, heap, desc->Anchor.all);
1204 new_active = (ptrsize_t) (desc)+(morecredits - 1);
1205 CAS(ret, &heap->Active, NULL, new_active);
1207 TRACE(OP_MADE_ACTIVE, desc->sz, 0, desc, desc->SB, heap, desc->Anchor.all);
1216 LLA(oldanchor.all, &desc->Anchor.all);
1217 new_anchor.all = oldanchor.all;
1218 new_anchor.sep.count += morecredits;
1219 new_anchor.sep.active = FALSE;
1220 new_anchor.sep.tag++;
1221 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1225 TRACE(OP_NOT_ACTIVE, desc->sz, 0, desc, desc->SB, heap, new_anchor.all);
1228 partial_push(heap, desc);
1232 static void * malloc_from_partial(
procheap_t * heap) {
1238 unsigned morecredits;
1241 TRACE(OP_PARTIAL_STR, 0, 0, 0, 0, heap, 0);
1243 desc = partial_pop(heap);
1248 LLA(oldanchor.all, &desc->Anchor.all);
1249 new_anchor.all = oldanchor.all;
1250 if (!oldanchor.sep.valid) {
1254 morecredits = MIN(oldanchor.sep.count - 1, MAXCREDITS);
1255 new_anchor.sep.count -= morecredits + 1;
1256 new_anchor.sep.active = (morecredits > 0);
1257 new_anchor.sep.tag++;
1258 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1262 ASSERT(!oldanchor.sep.active);
1263 ASSERT(oldanchor.sep.count > 0);
1264 ASSERT(oldanchor.sep.count < desc->maxcount);
1267 TRACE(OP_PARTIAL_RSRV, sz, 0, desc, sb, heap, new_anchor.all);
1270 LLA(oldanchor.all, &desc->Anchor.all);
1271 new_anchor.all = oldanchor.all;
1272 ASSERT(oldanchor.sep.valid);
1273 addr = sb + oldanchor.sep.head * sz + EIGHT;
1274 new_anchor.sep.head = *(
unsigned *) addr;
1275 new_anchor.sep.tag++;
1276 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1280 TRACE(OP_PARTIAL_END, sz, addr, desc, sb, heap, new_anchor.all);
1281 if (morecredits > 0) {
1285 ASSERT(new_anchor.sep.active);
1289 make_active(heap, desc, morecredits);
1295 static void * malloc_from_new__sb(
procheap_t * heap) {
1301 ptrsize_t new_active;
1304 desc = desc_alloc();
1307 credits = MIN(heap->sc->maxcount - 1, MAXCREDITS);
1308 new_active = (ptrsize_t) (desc)+(credits - 1);
1309 new_anchor.all = desc->Anchor.all;
1310 TRACE(OP_new__STR, desc->sz, 0, desc, desc->SB, heap, new_anchor.all);
1311 new_anchor.sep.head = 1;
1312 new_anchor.sep.count = (heap->sc->maxcount - 1) - credits;
1313 new_anchor.sep.active = TRUE;
1314 new_anchor.sep.valid = TRUE;
1315 new_anchor.sep.tag++;
1316 desc->Anchor.all = new_anchor.all;
1317 desc->sz = heap->sc->sz;
1318 desc->maxcount = heap->sc->maxcount;
1321 CAS(ret, &heap->Active, NULL, new_active);
1323 sb_dealloc(desc->SB, desc->Pdesc);
1324 new_anchor.sep.valid = FALSE;
1325 desc->Anchor.all = new_anchor.all;
1326 TRACE(OP_NOT_new_, desc->sz, 0, desc, desc->SB, heap, new_anchor.all);
1332 TRACE(OP_new__END, heap->sc->sz, addr, desc, sb, heap, new_anchor.all);
1337 static void * malloc_regular(
procheap_t * heap) {
1340 ptrsize_t oldactive;
1341 ptrsize_t new_active;
1346 unsigned morecredits = 0;
1348 TRACE(OP_MALLOC_STR, heap->sc->sz, 0, 0, 0, heap, 0);
1351 oldactive = (ptrsize_t) (heap->Active);
1352 new_active = oldactive;
1354 addr = malloc_from_partial(heap);
1355 if (addr)
return addr;
1356 addr = malloc_from_new__sb(heap);
1357 if (addr)
return addr;
1360 credits = oldactive & CREDITSMASK;
1362 new_active = (ptrsize_t) NULL;
1366 CAS(ret, &heap->Active, oldactive, new_active);
1370 desc = (
desc_t*) (oldactive - credits);
1372 TRACE(OP_REGULAR_RSRV, desc->sz, 0, desc, sb, heap, desc->Anchor.all);
1375 LLA(oldanchor.all, &desc->Anchor.all);
1376 new_anchor.all = oldanchor.all;
1377 ASSERT(oldanchor.sep.valid);
1381 addr = sb + oldanchor.sep.head * desc->sz + EIGHT;
1382 new_anchor.sep.head = *(
unsigned *) addr;
1384 ASSERT(oldanchor.sep.active);
1385 morecredits = MIN(oldanchor.sep.count, MAXCREDITS);
1386 new_anchor.sep.count -= morecredits;
1387 new_anchor.sep.active = (morecredits > 0);
1389 new_anchor.sep.tag++;
1390 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1394 TRACE(OP_REGULAR_END, desc->sz, addr, desc, sb, heap, new_anchor.all);
1395 if (morecredits > 0)
1396 make_active(heap, desc, morecredits);
1401 void __free__(
void * ptr)
1404 void free(
void * ptr)
1419 header = ptr - EIGHT;
1421 num = (ptrsize_t) desc;
1425 if (munmap((
void *) header, num)) {
1426 perror(
"free munmap failed\n");
1434 TRACE(OP_FREE_STR, sz, header, desc, sb, heap, desc->Anchor.all);
1438 LLA(oldanchor.all, &desc->Anchor.all);
1439 new_anchor.all = oldanchor.all;
1440 ASSERT(oldanchor.sep.valid);
1441 *(
unsigned *) ptr = oldanchor.sep.head;
1445 new_anchor.sep.head = ((ptr - sb) / sz);
1446 if ((!oldanchor.sep.active) &&
1448 (oldanchor.sep.count == desc->maxcount - 1)) {
1449 new_anchor.sep.valid = FALSE;
1450 pdesc = desc->Pdesc;
1451 if (pdesc == (
void*) 1)
continue;
1454 new_anchor.sep.count++;
1455 new_anchor.sep.tag++;
1456 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1460 TRACE(OP_FREE_END, sz, header, desc, sb, heap, new_anchor.all);
1461 if (!new_anchor.sep.valid) {
1462 sb_dealloc(sb, pdesc);
1463 list_desc_remove(heap);
1464 }
else if ((!new_anchor.sep.active) && (new_anchor.sep.count == 1)) {
1467 partial_push(heap, desc);
1479 CAS(ret, &heap->Active, NULL, desc);
1488 LLA(oldanchor.all, &desc->Anchor.all);
1489 new_anchor.all = oldanchor.all;
1490 new_anchor.sep.count++;
1491 new_anchor.sep.active = FALSE;
1492 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1498 partial_push(heap, desc);
1502 static void * malloc_from_partial(
procheap_t * heap) {
1511 desc = partial_pop(heap);
1516 LLA(oldanchor.all, &desc->Anchor.all);
1517 new_anchor.all = oldanchor.all;
1518 if (!oldanchor.sep.valid) {
1522 ASSERT(!oldanchor.sep.active);
1523 ASSERT(oldanchor.sep.count > 0);
1524 ASSERT(oldanchor.sep.count < desc->maxcount);
1527 addr = (
desc_t**) ((
char*) sb + oldanchor.sep.head * sz + EIGHT);
1528 new_anchor.sep.head = *(
unsigned *) addr;
1529 if (oldanchor.sep.count > 1) {
1530 new_anchor.sep.count -= 2;
1531 new_anchor.sep.active = TRUE;
1533 ASSERT(oldanchor.sep.count == 1);
1534 new_anchor.sep.count = 0;
1536 new_anchor.sep.tag++;
1537 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1542 if (new_anchor.sep.active) {
1546 make_active(heap, desc);
1552 static void * malloc_from_new__sb(
procheap_t * heap) {
1559 desc = desc_alloc();
1562 new_anchor.all = desc->Anchor.all;
1563 new_anchor.sep.head = 1;
1564 new_anchor.sep.count = heap->sc->maxcount - 2;
1565 new_anchor.sep.active = TRUE;
1566 new_anchor.sep.valid = TRUE;
1567 desc->Anchor.all = new_anchor.all;
1568 desc->sz = heap->sc->sz;
1569 desc->maxcount = heap->sc->maxcount;
1572 CAS(ret, &heap->Active, NULL, desc);
1574 sb_dealloc(desc->SB, desc->Pdesc);
1575 new_anchor.sep.valid = FALSE;
1576 desc->Anchor.all = new_anchor.all;
1581 addr = (
desc_t**) ((
char*) sb + EIGHT);
1586 static void * malloc_regular(
procheap_t * heap) {
1596 desc = heap->Active;
1598 addr = (
void**) malloc_from_partial(heap);
1600 addr = (
void**) malloc_from_new__sb(heap);
1604 LLA(oldanchor.all, &desc->Anchor.all);
1605 new_anchor.all = oldanchor.all;
1606 if (oldanchor.sep.count == 0) {
1607 CAS(ret, &heap->Active, desc, NULL);
1610 LLA(oldanchor.all, &desc->Anchor.all);
1611 new_anchor.all = oldanchor.all;
1612 ASSERT(oldanchor.sep.active);
1615 addr = (
void**) ((
char*) sb + oldanchor.sep.head * desc->sz + EIGHT);
1616 new_anchor.sep.head = *(
unsigned *) addr;
1617 if (oldanchor.sep.count == 0)
1618 new_anchor.sep.active = FALSE;
1620 new_anchor.sep.count--;
1621 new_anchor.sep.tag++;
1622 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1626 if (new_anchor.sep.active)
1627 make_active(heap, desc);
1634 addr = (
void**) ((
char*) sb + oldanchor.sep.head * desc->sz + EIGHT);
1635 if (heap->Active != desc)
continue;
1639 if (desc->Anchor.all != oldanchor.all)
continue;
1640 ASSERT(oldanchor.sep.valid);
1641 ASSERT(oldanchor.sep.active);
1642 new_anchor.sep.head = *(
unsigned *) addr;
1643 new_anchor.sep.count--;
1644 new_anchor.sep.tag++;
1645 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1654 void __free__(
void * ptr)
1657 void free(
void * ptr)
1672 header = (
desc_t**) ((
char*) ptr - EIGHT);
1674 num = (ptrsize_t) desc;
1678 if (munmap((
void *) header, num)) {
1679 perror(
"free munmap failed\n");
1690 LLA(oldanchor.all, &desc->Anchor.all);
1691 new_anchor.all = oldanchor.all;
1692 ASSERT(oldanchor.sep.valid);
1693 *(
unsigned *) ptr = oldanchor.sep.head;
1697 new_anchor.sep.head = (((
char*) ptr - (
char*) sb) / sz);
1698 if ((!oldanchor.sep.active) &&
1699 (oldanchor.sep.count == desc->maxcount - 1)) {
1701 new_anchor.sep.valid = FALSE;
1702 pdesc = desc->Pdesc;
1703 if (pdesc == (
void*) 1)
continue;
1706 new_anchor.sep.count++;
1707 SCA(aret, &desc->Anchor.all, oldanchor.all, new_anchor.all);
1711 if (!new_anchor.sep.valid) {
1712 sb_dealloc(sb, pdesc);
1713 list_desc_remove(heap);
1714 }
else if ((!new_anchor.sep.active) && (new_anchor.sep.count == 1)) {
1717 partial_push(heap, desc);
1724 void * __malloc__(
size_t sz)
1727 void * malloc(
size_t sz)
1740 if (controlblock == NULL) clfmalloc_init();
1746 for (ind = 0; ind < NUMSIZECLASSES; ind++) {
1747 if (sz <= scsz[ind])
1750 if (ind == NUMSIZECLASSES) {
1753 sz = sz + 8 - (sz & 7);
1754 if ((addr = (
void **) MMAP(sz)) == MAP_FAILED) {
1755 perror(
"malloc mmap failed\n");
1758 *addr = (
void*) (sz + 1);
1761 return (
void *) ((ptrsize_t) (addr) + EIGHT);
1764 sc = &controlblock->sizeclass[ind];
1765 if (sc->numprocheaps == 1) {
1766 heap = &sc->procheap;
1773 id = (
unsigned long) pthread_self();
1776 x ^= (
id >> 11) & 0x7ff;
1777 x ^= (
id >> 22) & 0x7ff;
1779 heapid = x & heapidmask;
1781 heap = &controlblock->procheap[heapid][ind];
1784 return malloc_regular(heap);
1788 static void * super_malloc(
unsigned sz) {
1793 static void super_free(
void * ptr) {
1798 void * __calloc__(
size_t n,
size_t sz)
1801 void * calloc(
size_t n,
size_t sz)
1804 void * addr = malloc(n * sz);
1805 memset(addr, 0, n * sz);
1810 void * __realloc__(
void * ptr,
size_t sz)
1813 void * realloc(
void * ptr,
size_t sz)
1830 header = (
desc_t**) (reinterpret_cast<char*> (ptr) - EIGHT);
1832 num = (ptrsize_t) desc;
1838 copysz = MIN(num, sz);
1839 memcpy(addr, ptr, copysz);
1844 copysz = desc->sz - EIGHT;
1850 memcpy(addr, ptr, copysz);
1859 int __mallopt__(
int cmd,
int value) {
1861 perror(
"mallopt not supported");
1865 static struct mallinfo mi;
1867 struct mallinfo __mallinfo__() {
1869 perror(
"mallinfo not supported");
1874 int __posix_memalign__(
void **p2p,
size_t align,
size_t sz) {
1876 perror(
"posix_memalign not supported");
1882 void __malloc_init__() {
1886 void __malloc_prefork_lock__() {
1890 void __malloc_postfork_unlock__() {
Definition: clfmalloc.h:363
Definition: clfmalloc.h:324
Definition: clfmalloc.h:337
Definition: clfmalloc.h:380
Definition: clfmalloc.h:355