예제 #1
0
const char *rt_print_buffer_name(void)
{
	struct print_buffer *buffer = pthread_getspecific(buffer_key);

	if (!buffer) {
		int res = -1;

		if (auto_init)
			res = rt_print_init(0, NULL);

		if (res)
			return NULL;

		buffer = pthread_getspecific(buffer_key);
	}

	return buffer->name;
}
예제 #2
0
static int 
vprint_to_buffer(FILE *stream, int fortify_level, int priority, 
		 unsigned int mode, size_t sz, const char *format, va_list args)
{
	struct print_buffer *buffer = pthread_getspecific(buffer_key);
	off_t write_pos, read_pos;
	struct entry_head *head;
	int len, str_len;
	int res = 0;

	if (!buffer) {
		res = 0;
		if (auto_init)
			res = rt_print_init(0, NULL);
		else
			res = EIO;

		if (res) {
			errno = res;
			return -1;
		}
		buffer = pthread_getspecific(buffer_key);
	}

	/* Take a snapshot of the ring buffer state */
	write_pos = buffer->write_pos;
	read_pos = buffer->read_pos;
	smp_mb();

	/* Is our write limit the end of the ring buffer? */
	if (write_pos >= read_pos) {
		/* Keep a safety margin to the end for at least an empty entry */
		len = buffer->size - write_pos - sizeof(struct entry_head);

		/* Special case: We were stuck at the end of the ring buffer
		   with space left there only for one empty entry. Now
		   read_pos was moved forward and we can wrap around. */
		if (len == 0 && read_pos > sizeof(struct entry_head)) {
			/* Write out empty entry */
			head = buffer->ring + write_pos;
			head->seq_no = seq_no;
			head->priority = 0;
			head->len = 0;

			/* Forward to the ring buffer start */
			write_pos = 0;
			len = read_pos - 1;
		}
	} else {
		/* Our limit is the read_pos ahead of our write_pos. One byte
		   margin is required to detect a full ring. */
		len = read_pos - write_pos - 1;
	}

	/* Account for head length */
	len -= sizeof(struct entry_head);
	if (len < 0)
		len = 0;

	head = buffer->ring + write_pos;

	if (mode == RT_PRINT_MODE_FORMAT) {
		if (stream != RT_PRINT_SYSLOG_STREAM) {
			/* We do not need the terminating \0 */
#ifdef CONFIG_XENO_FORTIFY
			if (fortify_level > 0)
				res = __vsnprintf_chk(head->data, len,
						      fortify_level - 1,
						      len > 0 ? len : 0, 
						      format, args);
			else
#else
				(void)fortify_level;
#endif
			res = vsnprintf(head->data, len, format, args);

			if (res < len) {
				/* Text was written completely, res contains its
				   length */
				len = res;
			} else {
				/* Text was truncated */
				res = len;
			}
		} else {
			/* We DO need the terminating \0 */
#ifdef CONFIG_XENO_FORTIFY
			if (fortify_level > 0)
				res = __vsnprintf_chk(head->data, len,
						      fortify_level - 1,
						      len > 0 ? len : 0, 
						      format, args);
			else
#endif
				res = vsnprintf(head->data, len, format, args);

			if (res < len) {
				/* Text was written completely, res contains its
				   length */
				len = res + 1;
			} else {
				/* Text was truncated */
				res = len;
			}
		}
	} else if (len >= 1) {
		str_len = sz;
		len = (str_len < len) ? str_len : len;
		memcpy(head->data, format, len);
	} else
		len = 0;

	/* If we were able to write some text, finalise the entry */
	if (len > 0) {
		head->seq_no = ++seq_no;
		head->priority = priority;
		head->dest = stream;
		head->len = len;

		/* Move forward by text and head length */
		write_pos += len + sizeof(struct entry_head);
	}

	/* Wrap around early if there is more space on the other side */
	if (write_pos >= buffer->size - RT_PRINT_LINE_BREAK &&
	    read_pos <= write_pos && read_pos > buffer->size - write_pos) {
		/* An empty entry marks the wrap-around */
		head = buffer->ring + write_pos;
		head->seq_no = seq_no;
		head->priority = priority;
		head->len = 0;

		write_pos = 0;
	}

	/* All entry data must be written before we can update write_pos */
	smp_wmb();

	buffer->write_pos = write_pos;

	return res;
}
예제 #3
0
int rt_vfprintf(FILE *stream, const char *format, va_list args)
{
	struct print_buffer *buffer = pthread_getspecific(__buffer_key);
	off_t write_pos, read_pos;
	struct entry_head *head;
	int len;
	int res;

	if (!buffer) {
		res = 0;
		if (__auto_init)
			res = rt_print_init(0, NULL);
		else
			res = EIO;

		if (res) {
			errno = res;
			return -1;
		}
		buffer = pthread_getspecific(__buffer_key);
	}

	/* Take a snapshot of the ring buffer state */
	write_pos = buffer->write_pos;
	read_pos = buffer->read_pos;
	xnarch_read_memory_barrier();

	/* Is our write limit the end of the ring buffer? */
	if (write_pos >= read_pos) {
		/* Keep a savety margin to the end for at least an empty entry */
		len = buffer->size - write_pos - sizeof(struct entry_head);

		/* Special case: We were stuck at the end of the ring buffer
		   with space left there only for one empty entry. Now
		   read_pos was moved forward and we can wrap around. */
		if (len == 0 && read_pos > sizeof(struct entry_head)) {
			/* Write out empty entry */
			head = buffer->ring + write_pos;
			head->seq_no = __seq_no;
			head->text[0] = 0;

			/* Forward to the ring buffer start */
			write_pos = 0;
			len = read_pos - 1;
		}
	} else {
		/* Our limit is the read_pos ahead of our write_pos. One byte
		   margin is required to detect a full ring. */
		len = read_pos - write_pos - 1;
	}

	/* Account for head length */
	len -= sizeof(struct entry_head);
	if (len < 0)
		len = 0;

	head = buffer->ring + write_pos;

	res = vsnprintf(head->text, len, format, args);

	if (res < len) {
		/* Text was written completely, res contains its length */
		len = res;
	} else {
		/* Text was truncated, remove closing \0 that entry_head
		   already includes */
		len--;
	}

	/* If we were able to write some text, finalise the entry */
	if (len > 0) {
		head->seq_no = ++__seq_no;
		head->dest = stream;

		/* Move forward by text and head length */
		write_pos += len + sizeof(struct entry_head);
	}

	/* Wrap around early if there is more space on the other side */
	if (write_pos >= buffer->size - RT_PRINT_LINE_BREAK &&
	    read_pos <= write_pos && read_pos > buffer->size - write_pos) {
		/* An empty entry marks the wrap-around */
		head = buffer->ring + write_pos;
		head->seq_no = __seq_no;
		head->text[0] = 0;

		write_pos = 0;
	}

	/* All entry data must be written before we can update write_pos */
	xnarch_write_memory_barrier();

	buffer->write_pos = write_pos;

	return res;
}