static void* pausing_thread (void* data)
{
    gu_info ("pausing_thread start, pause_order = %d", pause_order);
    gcs_sm_t* sm = (gcs_sm_t*)data;

    gu_cond_t cond;
    gu_cond_init (&cond, NULL);

    gcs_sm_schedule (sm);
    gu_info ("pausing_thread scheduled, pause_order = %d", pause_order);
    fail_if (pause_order != 0, "pause_order = %d, expected 0");
    pause_order = 1;
    gcs_sm_enter (sm, &cond, true);
    gu_info ("pausing_thread entered, pause_order = %d", pause_order);
    fail_if (pause_order != 2, "pause_order = %d, expected 2");
    pause_order = 3;
    usleep(TEST_USLEEP);
    gcs_sm_leave (sm);

    mark_point();
    gu_cond_destroy(&cond);

    gu_info ("pausing_thread exit, pause_order = %d", pause_order);
    return NULL;
}
/* Creates FIFO object. Since it practically consists of array of (void*),
 * the length can be chosen arbitrarily high - to minimize the risk
 * of overflow situation.
 */
gcs_fifo_lite_t* gcs_fifo_lite_create (size_t length, size_t item_size)
{
    gcs_fifo_lite_t* ret = NULL;
    uint64_t l = 1;

    /* check limits */
    if (length < 1 || item_size < 1)
        return NULL;

    /* Find real length. It must be power of 2*/
    while (l < length) l = l << 1;

    if (l * item_size > (uint64_t)GU_LONG_MAX) {
        gu_error ("Resulting FIFO size %lld exceeds signed limit: %lld",
                  (long long)(l*item_size), (long long)GU_LONG_MAX);
        return NULL;
    }

    ret = GU_CALLOC (1, gcs_fifo_lite_t);

    if (ret) {
        ret->length    = l;
        ret->item_size = item_size;
	ret->mask      = ret->length - 1;
        ret->closed    = true;
	ret->queue     = gu_malloc (ret->length * item_size);

	if (ret->queue) {
	    gu_mutex_init (&ret->lock,     NULL);
	    gu_cond_init  (&ret->put_cond, NULL);
	    gu_cond_init  (&ret->get_cond, NULL);
	    /* everything else must be initialized to 0 by calloc */
	}
	else {
	    gu_free (ret);
	    ret = NULL;
	}
    }

    return ret;
}
static void* simple_thread(void* arg)
{
    gcs_sm_t* sm = (gcs_sm_t*) arg;

    gu_cond_t cond;
    gu_cond_init (&cond, NULL);

    if (0 == (simple_ret = gcs_sm_enter (sm, &cond, false))) {
        usleep(1000);
        gcs_sm_leave (sm);
    }

    gu_cond_destroy (&cond);

    return NULL;
}
Example #4
0
gu_to_t *gu_to_create (int len, gu_seqno_t seqno)
{
    gu_to_t *ret;

    assert (seqno >= 0);

    if (len <= 0) {
        gu_error ("Negative length parameter: %d", len);
        return NULL;
    }

    ret = GU_CALLOC (1, gu_to_t);
    
    if (ret) {

        /* Make queue length a power of 2 */
        ret->qlen = 1;
        while (ret->qlen < len) {
            // unsigned, can be bigger than any integer
            ret->qlen = ret->qlen << 1;
        }
        ret->qmask = ret->qlen - 1;
        ret->seqno = seqno;

        ret->queue = GU_CALLOC (ret->qlen, to_waiter_t);

        if (ret->queue) {
            ssize_t i;
            for (i = 0; i < ret->qlen; i++) {
                to_waiter_t *w = ret->queue + i;
#ifdef TO_USE_SIGNAL
                gu_cond_init (&w->cond, NULL);
#else
                pthread_mutex_init (&w->mtx, NULL);
#endif
                w->state       = RELEASED;
            }
            gu_mutex_init (&ret->lock, NULL);
        
            return ret;
        }
        gu_free (ret);
    }

    return NULL;
}
gcs_sm_t*
gcs_sm_create (long len, long n)
{
    if ((len < 2 /* 2 is minimum */) || (len & (len - 1))) {
        gu_error ("Monitor length parameter is not a power of 2: %ld", len);
        return NULL;
    }

    if (n < 1) {
        gu_error ("Invalid monitor concurrency parameter: %ld", n);
        return NULL;
    }

    size_t sm_size = sizeof(gcs_sm_t) +
        len * sizeof(((gcs_sm_t*)(0))->wait_q[0]);

    gcs_sm_t* sm = static_cast<gcs_sm_t*>(gu_malloc(sm_size));

    if (sm) {
        sm_init_stats (&sm->stats);
        gu_mutex_init (&sm->lock, NULL);
#ifdef GCS_SM_GRAB_RELEASE
        gu_cond_init  (&sm->cond, NULL);
        sm->cond_wait   = 0;
#endif /* GCS_SM_GRAB_RELEASE */
        sm->wait_q_len  = len;
        sm->wait_q_mask = sm->wait_q_len - 1;
        sm->wait_q_head = 1;
        sm->wait_q_tail = 0;
        sm->users       = 0;
        sm->entered     = 0;
        sm->ret         = 0;
#ifdef GCS_SM_CONCURRENCY
        sm->cc          = n; // concurrency param.
#endif /* GCS_SM_CONCURRENCY */
        sm->pause       = false;
        memset (sm->wait_q, 0, sm->wait_q_len * sizeof(sm->wait_q[0]));
    }

    return sm;
}
long
gcs_sm_close (gcs_sm_t* sm)
{
    gu_info ("Closing send monitor...");

    if (gu_unlikely(gu_mutex_lock (&sm->lock))) abort();

    sm->ret = -EBADFD;

    if (sm->pause) _gcs_sm_continue_common (sm);

    gu_cond_t cond;
    gu_cond_init (&cond, NULL);

    // in case the queue is full
    while (sm->users >= (long)sm->wait_q_len) {
        gu_mutex_unlock (&sm->lock);
        usleep(1000);
        gu_mutex_lock (&sm->lock);
    }

    while (sm->users > 0) { // wait for cleared queue
        sm->users++;
        GCS_SM_INCREMENT(sm->wait_q_tail);
        _gcs_sm_enqueue_common (sm, &cond);
        sm->users--;
        GCS_SM_INCREMENT(sm->wait_q_head);
    }

    gu_cond_destroy (&cond);

    gu_mutex_unlock (&sm->lock);

    gu_info ("Closed send monitor.");

    return 0;
}
Example #7
0
 Cond () : cond(), ref_count(0)
 {
     gu_cond_init (&cond, NULL);
 }