Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/* 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;
}
Exemplo n.º 4
0
/* 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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/* 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);
}
Exemplo n.º 7
0
/* and this after */
void ggc_post_blocking()
{
    struct GGGGC_PoolList *plCur;
    struct GGGGC_PointerStackList *pslCur;

    /* get a lock on the thread count etc */
    while (ggc_mutex_trylock(&ggggc_worldBarrierLock) != 0);
    /* FIXME: can't yield here, as yielding waits for stop-the-world if
     * applicable. Perhaps something would be more ideal than a spin-loop
     * though. */

    /* add ourselves back to the world barrier */
    ggc_barrier_destroy(&ggggc_worldBarrier);
    ggc_barrier_init(&ggggc_worldBarrier, ++ggggc_threadCount);

    /* remove our roots and pools from the list */
    if (ggggc_blockedThreadPool0s == &blockedPoolListNode) {
        ggggc_blockedThreadPool0s = ggggc_blockedThreadPool0s->next;

    } else {
        for (plCur = ggggc_blockedThreadPool0s; plCur->next; plCur = plCur->next) {
            if (plCur->next == &blockedPoolListNode) {
                plCur->next = plCur->next->next;
                break;
            }
        }

    }
    if (ggggc_blockedThreadPointerStacks == &blockedPointerStackListNode) {
        ggggc_blockedThreadPointerStacks = ggggc_blockedThreadPointerStacks->next;

    } else {
        for (pslCur = ggggc_blockedThreadPointerStacks; pslCur->next; pslCur = pslCur->next) {
            if (pslCur->next == &blockedPointerStackListNode) {
                pslCur->next = pslCur->next->next;
                break;
            }
        }

    }

    ggc_mutex_unlock(&ggggc_worldBarrierLock);
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
/* 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);
}