Beispiel #1
0
void
process_blocking_resp(
	blocking_child *	c
	)
{
	blocking_pipe_header *	resp;
	void *			data;

#ifdef USE_WORK_THREAD
	do {
#endif
		resp = receive_blocking_resp_internal(c);
		if (NULL != resp) {
			DEBUG_REQUIRE(BLOCKING_RESP_MAGIC ==
				      resp->magic_sig);
			data = (char *)resp + sizeof(*resp);
			intres_req_pending--;
			(*resp->done_func)(resp->rtype, resp->context,
					   resp->octets - sizeof(*resp),
					   data);
			free(resp);
		}
#ifdef USE_WORK_THREAD
	} while (NULL != resp);
#endif
	if (!worker_per_query && 0 == intres_req_pending)
		intres_timeout_req(CHILD_MAX_IDLE);
	else if (worker_per_query)
		req_child_exit(c);
}
Beispiel #2
0
int
queue_blocking_request(
	blocking_work_req	rtype,
	void *			req,
	size_t			reqsize,
	blocking_work_callback	done_func,
	void *			context
	)
{
	static u_int		intres_slot = UINT_MAX;
	u_int			child_slot;
	blocking_child *	c;
	blocking_pipe_header	req_hdr;

	req_hdr.octets = sizeof(req_hdr) + reqsize;
	req_hdr.magic_sig = BLOCKING_REQ_MAGIC;
	req_hdr.rtype = rtype;
	req_hdr.done_func = done_func;
	req_hdr.context = context;

	child_slot = UINT_MAX;
	if (worker_per_query || UINT_MAX == intres_slot ||
	    blocking_children[intres_slot]->reusable)
		child_slot = available_blocking_child_slot();
	if (!worker_per_query) {
		if (UINT_MAX == intres_slot)
			intres_slot = child_slot;
		else
			child_slot = intres_slot;
		if (0 == intres_req_pending)
			intres_timeout_req(0);
	}
	intres_req_pending++;
	INSIST(UINT_MAX != child_slot);
	c = blocking_children[child_slot];
	if (NULL == c) {
		c = emalloc_zero(sizeof(*c));
#ifdef WORK_FORK
		c->req_read_pipe = -1;
		c->req_write_pipe = -1;
#endif
#ifdef WORK_PIPE
		c->resp_read_pipe = -1;
		c->resp_write_pipe = -1;
#endif
		blocking_children[child_slot] = c;
	}
	req_hdr.child_idx = child_slot;

	return send_blocking_req_internal(c, &req_hdr, req);
}
Beispiel #3
0
/*
 * worker_idle_timer_fired()
 *
 * The parent starts this timer when the last pending response has been
 * received from the child, making it idle, and clears the timer when a
 * request is dispatched to the child.  Once the timer expires, the
 * child is sent packing.
 *
 * This is called when worker_idle_timer is nonzero and less than or
 * equal to current_time.
 */
void
worker_idle_timer_fired(void)
{
	u_int			idx;
	blocking_child *	c;

	DEBUG_REQUIRE(0 == intres_req_pending);

	intres_timeout_req(0);
	for (idx = 0; idx < blocking_children_alloc; idx++) {
		c = blocking_children[idx];
		if (NULL == c)
			continue;
		req_child_exit(c);
	}
}
Beispiel #4
0
void
process_blocking_resp(
	blocking_child *	c
	)
{
	blocking_pipe_header *	resp;
	void *			data;

	/*
	 * On Windows send_blocking_resp_internal() may signal the
	 * blocking_response_ready event multiple times while we're
	 * processing a response, so always consume all available
	 * responses before returning to test the event again.
	 */
#ifdef WORK_THREAD
	do {
#endif
		resp = receive_blocking_resp_internal(c);
		if (NULL != resp) {
			DEBUG_REQUIRE(BLOCKING_RESP_MAGIC ==
				      resp->magic_sig);
			data = (char *)resp + sizeof(*resp);
			intres_req_pending--;
			(*resp->done_func)(resp->rtype, resp->context,
					   resp->octets - sizeof(*resp),
					   data);
			free(resp);
		}
#ifdef WORK_THREAD
	} while (NULL != resp);
#endif
	if (!worker_per_query && 0 == intres_req_pending)
		intres_timeout_req(CHILD_MAX_IDLE);
	else if (worker_per_query)
		req_child_exit(c);
}