Пример #1
0
ssize_t
qb_rb_chunk_peek(struct qb_ringbuffer_s * rb, void **data_out, int32_t timeout)
{
	uint32_t read_pt;
	uint32_t chunk_size;
	uint32_t chunk_magic;
	int32_t res;

	if (rb == NULL) {
		return -EINVAL;
	}
	res = rb->sem_timedwait_fn(rb, timeout);
	if (res < 0 && res != -EIDRM) {
		if (res != -ETIMEDOUT) {
			qb_util_perror(LOG_ERR, "sem_timedwait");
		}
		return res;
	}
	read_pt = rb->shared_hdr->read_pt;
	chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
	chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, read_pt);
	*data_out = &rb->shared_data[read_pt + QB_RB_CHUNK_HEADER_WORDS];

	if (chunk_magic != QB_RB_CHUNK_MAGIC) {
		errno = ENOMSG;
		return 0;
	} else {
		return chunk_size;
	}
}
Пример #2
0
ssize_t
qb_rb_chunk_peek(struct qb_ringbuffer_s * rb, void **data_out, int32_t timeout)
{
	uint32_t read_pt;
	uint32_t chunk_size;
	uint32_t chunk_magic;
	int32_t res = 0;

	if (rb == NULL) {
		return -EINVAL;
	}
	if (rb->notifier.timedwait_fn) {
		res = rb->notifier.timedwait_fn(rb->notifier.instance, timeout);
	}
	if (res < 0 && res != -EIDRM) {
		if (res == -ETIMEDOUT) {
			return 0;
		} else {
			errno = -res;
			qb_util_perror(LOG_ERR, "sem_timedwait");
		}
		return res;
	}
	read_pt = rb->shared_hdr->read_pt;
	chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, read_pt);
	if (chunk_magic != QB_RB_CHUNK_MAGIC) {
		if (rb->notifier.post_fn) {
			(void)rb->notifier.post_fn(rb->notifier.instance, res);
		}
		return 0;
	}
	chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
	*data_out = QB_RB_CHUNK_DATA_GET(rb, read_pt);
	return chunk_size;
}
Пример #3
0
ssize_t
qb_rb_chunk_read(struct qb_ringbuffer_s * rb, void *data_out, size_t len,
		 int32_t timeout)
{
	uint32_t read_pt;
	uint32_t chunk_size;
	uint32_t chunk_magic;
	int32_t res = 0;

	if (rb == NULL) {
		return -EINVAL;
	}
	if (rb->notifier.timedwait_fn) {
		res = rb->notifier.timedwait_fn(rb->notifier.instance, timeout);
	}
	if (res < 0 && res != -EIDRM) {
		if (res != -ETIMEDOUT) {
			errno = -res;
			qb_util_perror(LOG_ERR, "sem_timedwait");
		}
		return res;
	}

	read_pt = rb->shared_hdr->read_pt;
	chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, read_pt);

	if (chunk_magic != QB_RB_CHUNK_MAGIC) {
		if (rb->notifier.timedwait_fn == NULL) {
			return -ETIMEDOUT;
		} else {
			(void)rb->notifier.post_fn(rb->notifier.instance, res);
#ifdef EBADMSG
			return -EBADMSG;
#else
			return -EINVAL;
#endif
		}
	}

	chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
	if (len < chunk_size) {
		qb_util_log(LOG_ERR,
			    "trying to recv chunk of size %d but %d available",
			    len, chunk_size);
		if (rb->notifier.post_fn) {
			(void)rb->notifier.post_fn(rb->notifier.instance, chunk_size);
		}
		return -ENOBUFS;
	}

	memcpy(data_out,
	       QB_RB_CHUNK_DATA_GET(rb, read_pt),
	       chunk_size);

	_rb_chunk_reclaim(rb);

	return chunk_size;
}
Пример #4
0
static void
qb_rb_chunk_check(struct qb_ringbuffer_s * rb, uint32_t pointer)
{
	uint32_t chunk_size;
	uint32_t chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, pointer);

	if (chunk_magic != QB_RB_CHUNK_MAGIC) {
		chunk_size = QB_RB_CHUNK_SIZE_GET(rb, pointer);
		printf("size: %x\n", chunk_size);
		printf("magic: %x\n", chunk_magic);
		print_header(rb);
		assert(0);
	}
}
Пример #5
0
static int
_rb_chunk_reclaim(struct qb_ringbuffer_s * rb)
{
	uint32_t old_read_pt;
	uint32_t new_read_pt;
	uint32_t old_chunk_size;
	uint32_t chunk_magic;
	int rc = 0;

	old_read_pt = rb->shared_hdr->read_pt;
	chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, old_read_pt);
	if (chunk_magic != QB_RB_CHUNK_MAGIC) {
		return -EINVAL;
	}

	old_chunk_size = QB_RB_CHUNK_SIZE_GET(rb, old_read_pt);
	new_read_pt = qb_rb_chunk_step(rb, old_read_pt);

	/*
	 * clear the header
	 */
	rb->shared_data[old_read_pt] = 0;
	QB_RB_CHUNK_MAGIC_SET(rb, old_read_pt, QB_RB_CHUNK_MAGIC_DEAD);

	/*
	 * set the new read pointer after clearing the header
	 * to prevent a situation where a fast writer will write their
	 * new chunk between setting the new read pointer and clearing the
	 * header.
	 */
	rb->shared_hdr->read_pt = new_read_pt;

	if (rb->notifier.reclaim_fn) {
		rc = rb->notifier.reclaim_fn(rb->notifier.instance,
						 old_chunk_size);
		if (rc < 0) {
			errno = -rc;
			qb_util_perror(LOG_WARNING, "reclaim_fn");
		}
	}

	DEBUG_PRINTF("reclaim [%zd]: read: %u -> %u, write: %u\n",
		     (rb->notifier.q_len_fn ?
		      rb->notifier.q_len_fn(rb->notifier.instance) : 0),
		     old_read_pt,
		     rb->shared_hdr->read_pt,
		     rb->shared_hdr->write_pt);

	return rc;
}
Пример #6
0
ssize_t
qb_rb_chunk_read(struct qb_ringbuffer_s * rb, void *data_out, size_t len,
		 int32_t timeout)
{
	uint32_t read_pt;
	uint32_t chunk_size;
	int32_t res = 0;

	if (rb == NULL) {
		return -EINVAL;
	}
	if (rb->sem_timedwait_fn) {
		res = rb->sem_timedwait_fn(rb, timeout);
	}
	if (res < 0 && res != -EIDRM) {
		if (res != -ETIMEDOUT) {
			qb_util_perror(LOG_ERR, "sem_timedwait");
		}
		return res;
	}

	if (qb_rb_space_used(rb) == 0) {
		return -ENOMSG;
	}

	read_pt = rb->shared_hdr->read_pt;
	qb_rb_chunk_check(rb, read_pt);
	chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);

	if (len < chunk_size) {
		qb_util_log(LOG_ERR,
			    "trying to recv chunk of size %d but %d available",
			    len, chunk_size);
		return -ENOBUFS;
	}

	memcpy(data_out,
	       &rb->shared_data[read_pt + QB_RB_CHUNK_HEADER_WORDS],
	       chunk_size);

	qb_rb_chunk_reclaim(rb);

	return chunk_size;
}
Пример #7
0
static uint32_t
qb_rb_chunk_step(struct qb_ringbuffer_s * rb, uint32_t pointer)
{
	uint32_t chunk_size = QB_RB_CHUNK_SIZE_GET(rb, pointer);
	/*
	 * skip over the chunk header
	 */
	pointer += QB_RB_CHUNK_HEADER_WORDS;

	/*
	 * skip over the user's data.
	 */
	pointer += (chunk_size / sizeof(uint32_t));
	/* make allowance for non-word sizes */
	if ((chunk_size % (sizeof(uint32_t) * QB_RB_WORD_ALIGN)) != 0) {
		pointer++;
	}

	idx_cache_line_step(pointer);
	return pointer;
}