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; }
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; }
Cond () : cond(), ref_count(0) { gu_cond_init (&cond, NULL); }