int ggc_barrier_wait_raw(ggc_barrier_t *barrier) { ggc_mutex_lock_raw(&barrier->lock); /* if we're the last one, great */ if (barrier->cur == barrier->ct - 1) { unsigned long i; /* signal all the others */ for (i = 0; i < barrier->cur; i++) ggc_sem_post(&barrier->waiters); /* wait for them to wake up */ for (i = 0; i < barrier->cur; i++) ggc_sem_wait_raw(&barrier->leader); /* and reset the barrier */ barrier->cur = 0; ggc_mutex_unlock(&barrier->lock); return 0; } /* otherwise, wait on the others */ barrier->cur++; ggc_mutex_unlock(&barrier->lock); ggc_sem_wait_raw(&barrier->waiters); ggc_sem_post(&barrier->leader); return 0; }
/* allocate and initialize a pool */ static struct GGGGC_Pool *newPool(unsigned char gen, int mustSucceed) { struct GGGGC_Pool *ret; #ifdef GGGGC_DEBUG_TINY_HEAP static ggc_thread_local int allocationsLeft = GGGGC_GENERATIONS; if (allocationsLeft-- <= 0) { allocationsLeft = 0; if (mustSucceed) { fprintf(stderr, "GGGGC: exceeded tiny heap size\n"); abort(); } return NULL; } #endif ret = NULL; /* try to reuse a pool */ if (freePoolsHead) { ggc_mutex_lock_raw(&freePoolsLock); if (freePoolsHead) { ret = freePoolsHead; freePoolsHead = freePoolsHead->next; if (!freePoolsHead) freePoolsTail = NULL; } ggc_mutex_unlock(&freePoolsLock); } /* otherwise, allocate one */ if (!ret) ret = (struct GGGGC_Pool *) allocPool(mustSucceed); if (!ret) return NULL; /* set it up */ ret->next = NULL; ret->gen = gen; ret->free = ret->start; ret->end = (ggc_size_t *) ((unsigned char *) ret + GGGGC_POOL_BYTES); #if GGGGC_GENERATIONS > 1 /* clear the remembered set */ if (gen > 0) memset(ret->remember, 0, GGGGC_CARDS_PER_POOL); /* the first object in the first usable card */ ret->firstObject[GGGGC_CARD_OF(ret->start)] = (((ggc_size_t) ret->start) & GGGGC_CARD_INNER_MASK) / sizeof(ggc_size_t); #endif return ret; }
/* free a generation (used when a thread exits) */ void ggggc_freeGeneration(struct GGGGC_Pool *pool) { if (!pool) return; ggc_mutex_lock_raw(&freePoolsLock); if (freePoolsHead) { freePoolsTail->next = pool; } else { freePoolsHead = pool; } while (pool->next) pool = pool->next; freePoolsTail = pool; ggc_mutex_unlock(&freePoolsLock); }
/* allocate a descriptor from a descriptor slot */ struct GGGGC_Descriptor *ggggc_allocateDescriptorSlot(struct GGGGC_DescriptorSlot *slot) { if (slot->descriptor) return slot->descriptor; ggc_mutex_lock_raw(&slot->lock); if (slot->descriptor) { ggc_mutex_unlock(&slot->lock); return slot->descriptor; } slot->descriptor = ggggc_allocateDescriptor(slot->size, slot->pointers); /* make the slot descriptor a root */ GGC_PUSH_1(slot->descriptor); GGC_GLOBALIZE(); ggc_mutex_unlock(&slot->lock); return slot->descriptor; }
/* allocate a descriptor-descriptor for a descriptor of the given size */ struct GGGGC_Descriptor *ggggc_allocateDescriptorDescriptor(ggc_size_t size) { struct GGGGC_Descriptor tmpDescriptor, *ret; ggc_size_t ddSize; /* need one description bit for every word in the object */ ddSize = GGGGC_WORD_SIZEOF(struct GGGGC_Descriptor) + GGGGC_DESCRIPTOR_WORDS_REQ(size); /* check if we already have a descriptor */ if (ggggc_descriptorDescriptors[size]) return ggggc_descriptorDescriptors[size]; /* otherwise, need to allocate one. First lock the space */ ggc_mutex_lock_raw(&ggggc_descriptorDescriptorsLock); if (ggggc_descriptorDescriptors[size]) { ggc_mutex_unlock(&ggggc_descriptorDescriptorsLock); return ggggc_descriptorDescriptors[size]; } /* now make a temporary descriptor to describe the descriptor descriptor */ tmpDescriptor.header.descriptor__ptr = NULL; tmpDescriptor.size = ddSize; tmpDescriptor.pointers[0] = GGGGC_DESCRIPTOR_DESCRIPTION; /* allocate the descriptor descriptor */ ret = (struct GGGGC_Descriptor *) ggggc_mallocGen0(&tmpDescriptor, 1); /* make it correct */ ret->size = size; ret->pointers[0] = GGGGC_DESCRIPTOR_DESCRIPTION; /* put it in the list */ ggggc_descriptorDescriptors[size] = ret; ggc_mutex_unlock(&ggggc_descriptorDescriptorsLock); GGC_PUSH_1(ggggc_descriptorDescriptors[size]); GGC_GLOBALIZE(); /* and give it a proper descriptor */ ret->header.descriptor__ptr = ggggc_allocateDescriptorDescriptor(ddSize); return ret; }