int ggc_thread_create(ggc_thread_t *thread, void (*func)(ThreadArg), ThreadArg arg) { ThreadInfo ti = NULL; GGC_PUSH_2(arg, ti); /* set up its thread info */ ti = GGC_NEW(ThreadInfo); GGC_WD(ti, func, func); GGC_WP(ti, arg, arg); /* update our thread barrier */ while (ggc_mutex_trylock(&ggggc_worldBarrierLock) != 0) GGC_YIELD(); if (ggggc_threadCount == 0) ggggc_threadCount++; else ggc_barrier_destroy(&ggggc_worldBarrier); ggc_barrier_init(&ggggc_worldBarrier, ++ggggc_threadCount); ggc_mutex_unlock(&ggggc_worldBarrierLock); /* spawn the pthread */ if ((errno = pthread_create(thread, NULL, ggggcThreadWrapper, ti))) return -1; return 0; }
/* general purpose thread wrapper */ static void *ggggcThreadWrapper(void *arg) { ThreadInfo ti = (ThreadInfo) arg; GGC_PUSH_1(ti); GGC_RD(ti, func)(GGC_RP(ti, arg)); /* now remove this thread from the thread barrier */ while (ggc_mutex_trylock(&ggggc_worldBarrierLock) != 0) GGC_YIELD(); ggggc_threadCount--; if (ggggc_threadCount > 0) { ggc_barrier_destroy(&ggggc_worldBarrier); ggc_barrier_init(&ggggc_worldBarrier, ggggc_threadCount); } ggc_mutex_unlock(&ggggc_worldBarrierLock); /* and give back its pools */ ggggc_freeGeneration(ggggc_gen0); return 0; }
/* allocate an object */ void *ggggc_malloc(struct GGGGC_Descriptor *descriptor) { GGC_YIELD(); void * userPtr = NULL; struct GGGGC_Header header; header.descriptor__ptr = descriptor; if (!ggggc_curPool) { ggggc_curPool = ggggc_fromList = newPool(1); ggggc_toList = newPool(1); ggggc_forceCollect = 0; } ggc_size_t size = descriptor->size; if (ggggc_curPool->free + size >= ggggc_curPool->end) { if (ggggc_curPool->next) { ggggc_curPool = ggggc_curPool->next; return ggggc_malloc(descriptor); } struct GGGGC_Pool *temp = newPool(1); ggggc_curPool->next = temp; ggggc_curPool = temp; temp = newPool(1); struct GGGGC_Pool *poolIter = ggggc_toList; while(poolIter) { if (!(poolIter->next)) { poolIter->next = temp; break; } poolIter = poolIter->next; } ggggc_forceCollect = 1; } userPtr = (ggggc_curPool->free); ggggc_curPool->free += size; ((struct GGGGC_Header *) userPtr)[0] = header; ggggc_zero_object((struct GGGGC_Header*)userPtr); return userPtr; }
/* call this before blocking */ void ggc_pre_blocking() { /* get a lock on the thread count etc */ while (ggc_mutex_trylock(&ggggc_worldBarrierLock) != 0) GGC_YIELD(); /* take ourselves out of contention */ ggggc_threadCount--; if (ggggc_threadCount > 0) { ggc_barrier_destroy(&ggggc_worldBarrier); ggc_barrier_init(&ggggc_worldBarrier, ggggc_threadCount); } /* add our roots and pools */ blockedPoolListNode.pool = ggggc_gen0; blockedPoolListNode.next = ggggc_blockedThreadPool0s; ggggc_blockedThreadPool0s = &blockedPoolListNode; blockedPointerStackListNode.pointerStack = ggggc_pointerStack; blockedPointerStackListNode.next = ggggc_blockedThreadPointerStacks; ggggc_blockedThreadPointerStacks = &blockedPointerStackListNode; ggc_mutex_unlock(&ggggc_worldBarrierLock); }
LLL buildLLL(int sz) { int i; LLL ll0 = NULL, lll = NULL, llc = NULL; GGC_PUSH_3(ll0, lll, llc); printf("calling malloc\n"); ll0 = GGC_NEW(LLL); printf("here obj is %u\n",ll0); GGC_WD(ll0, val, 0); lll = ll0; for (i = 1; i < sz; i++) { llc = GGC_NEW(LLL); //printf("here obj is %zu\n",llc); GGC_WD(llc, val, i); GGC_WP(lll, next, llc); lll = llc; GGC_YIELD(); } return ll0; }
/* allocate an object */ void *ggggc_malloc(struct GGGGC_Descriptor *descriptor) { /* FILLME */ GGC_YIELD(); return GC_MALLOC(descriptor->size * sizeof(void*)); }