Esempio n. 1
0
blocking_pipe_header *
receive_blocking_req_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header *	req;
	int			rc;

	/*
	 * Child blocks here when idle.  SysV semaphores maintain a
	 * count and release from sem_wait() only when it reaches 0.
	 */
	do {
		rc = wait_for_sem(c->blocking_req_ready, NULL);
	} while (-1 == rc && EINTR == errno);
	INSIST(0 == rc);

	req = c->workitems[c->next_workeritem];
	INSIST(NULL != req);
	c->workitems[c->next_workeritem] = NULL;
	c->next_workeritem = (1 + c->next_workeritem) %
				c->workitems_alloc;

	if (CHILD_EXIT_REQ == req) {	/* idled out */
		send_blocking_resp_internal(c, CHILD_GONE_RESP);
		req = NULL;
	}

	return req;
}
Esempio n. 2
0
int queue_blocking_response(
	blocking_child *		c,
	blocking_pipe_header *		resp,
	size_t				respsize,
	const blocking_pipe_header *	req
	)
{
	resp->octets = respsize;
	resp->magic_sig = BLOCKING_RESP_MAGIC;
	resp->rtype = req->rtype;
	resp->context = req->context;
	resp->done_func = req->done_func;

	return send_blocking_resp_internal(c, resp);
}
Esempio n. 3
0
blocking_pipe_header *
receive_blocking_req_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header *	req;
	int			rc;

	/*
	 * Child blocks here when idle.  SysV semaphores maintain a
	 * count and release from sem_wait() only when it reaches 0.
	 * Windows auto-reset events are simpler, and multiple SetEvent
	 * calls before any thread waits result in a single wakeup.
	 * On Windows, the child drains all workitems each wakeup, while
	 * with SysV semaphores wait_sem() is used before each item.
	 */
#ifdef SYS_WINNT
	while (NULL == c->workitems[c->next_workeritem]) {
		/* !!!! SetEvent(c->child_is_blocking); */
		rc = wait_for_sem(c->blocking_req_ready, NULL);
		INSIST(0 == rc);
		/* !!!! ResetEvent(c->child_is_blocking); */
	}
#else
	do {
		rc = wait_for_sem(c->blocking_req_ready, NULL);
	} while (-1 == rc && EINTR == errno);
	INSIST(0 == rc);
#endif

	req = c->workitems[c->next_workeritem];
	INSIST(NULL != req);
	c->workitems[c->next_workeritem] = NULL;
	c->next_workeritem = (1 + c->next_workeritem) %
				c->workitems_alloc;

	if (CHILD_EXIT_REQ == req) {	/* idled out */
		send_blocking_resp_internal(c, CHILD_GONE_RESP);
		req = NULL;
	}

	return req;
}
Esempio n. 4
0
/* --------------------------------------------------------------------
 * Wait for the 'incoming queue no longer empty' signal, lock the shared
 * structure and dequeue an item.
 */
blocking_pipe_header *
receive_blocking_req_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header *	req;
	size_t			qhead, qtail;

	req = NULL;
	do {
		/* wait for tickle from the producer side */
		wait_for_sem(c->workitems_pending, NULL);

		/* >>>> ACCESS LOCKING STARTS >>>> */
		wait_for_sem(c->accesslock, NULL);
		qhead = c->head_workitem;
		do {
			qtail = c->tail_workitem;
			if (qhead == qtail)
				break;
			c->tail_workitem = qtail + 1;
			qtail %= c->workitems_alloc;
			req = c->workitems[qtail];
			c->workitems[qtail] = NULL;
		} while (NULL == req);
		tickle_sem(c->accesslock);
		/* <<<< ACCESS LOCKING ENDS <<<< */

	} while (NULL == req);

	INSIST(NULL != req);
	if (CHILD_EXIT_REQ == req) {	/* idled out */
		send_blocking_resp_internal(c, CHILD_GONE_RESP);
		req = NULL;
	}

	return req;
}