This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-variable-monitor/source/buffer/trace_buffer.c
2023-11-16 14:07:37 +08:00

216 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* diagnose-tools 工具通用调试缓冲区模块
* 这是为了解决procfs/trace的问题而编写
*
* Copyright (C) 20 Alibaba Ltd.
*
* 作者: Baoyou Xie <baoyou.xie@linux.alibaba.com>
*
* License terms: GNU General Public License (GPL) version 3
*
*/
#include <linux/vmalloc.h>
// #include "internal.h"
#include "trace_buffer.h"
int init_diag_trace_buffer(struct diag_trace_buffer *buffer,
unsigned int buf_size)
{
int ret = -ENOMEM;
char *buf1 = NULL, *buf2 = NULL;
ret = -EINVAL;
if (buf_size < 10 * DIAG_TRACE_BUF_SIZE)
return ret;
buf1 = vmalloc(buf_size);
if (!buf1)
goto out_nomem;
buf2 = vmalloc(buf_size);
if (!buf2)
goto out_nomem;
memset(buf1, 0, buf_size);
memset(buf2, 0, buf_size);
memset(buffer, 0, sizeof(struct diag_trace_buffer));
buffer->buf_size = buf_size;
buffer->buffer.data = buf1;
spin_lock_init(&buffer->buffer.lock);
mutex_init(&buffer->buffer.mutex);
buffer->product.data = buf2;
ret = 0;
return ret;
out_nomem:
if (buf1)
vfree(buf1);
if (buf2)
vfree(buf2);
return ret;
}
void destroy_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
if (buffer->buffer.data)
vfree(buffer->buffer.data);
if (buffer->product.data)
vfree(buffer->product.data);
memset(buffer, 0, sizeof(struct diag_trace_buffer));
}
void discard_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
unsigned long flags;
diag_trace_buffer_mutex_lock(buffer);
diag_trace_buffer_spin_lock(buffer, flags);
buffer->buffer.circle = buffer->buffer.pos = buffer->buffer.tail = 0;
diag_trace_buffer_spin_unlock(buffer, flags);
diag_trace_buffer_mutex_unlock(buffer);
}
void backup_diag_trace_buffer(struct diag_trace_buffer *buffer)
{
unsigned long flags;
if (!buffer->buffer.data || !buffer->product.data)
return;
diag_trace_buffer_mutex_lock(buffer);
diag_trace_buffer_spin_lock(buffer, flags);
buffer->product.len = 0;
if (buffer->buffer.pos < buffer->buf_size) {
if (buffer->buffer.circle) {
int tail_len = 0;
if (buffer->buffer.tail > buffer->buffer.pos) {
tail_len = buffer->buffer.tail - buffer->buffer.pos;
memcpy(buffer->product.data,
buffer->buffer.data + buffer->buffer.pos,
tail_len);
}
memcpy(buffer->product.data + tail_len,
buffer->buffer.data,
buffer->buffer.pos);
buffer->product.len = buffer->buffer.pos + tail_len;
} else {
memcpy(buffer->product.data, buffer->buffer.data, buffer->buffer.pos);
buffer->product.len = buffer->buffer.pos;
}
}
buffer->buffer.circle = buffer->buffer.pos = buffer->buffer.tail = 0;
diag_trace_buffer_spin_unlock(buffer, flags);
diag_trace_buffer_mutex_unlock(buffer);
}
asmlinkage int
diag_trace_buffer_write_nolock(struct diag_trace_buffer *buffer,
const void *data, size_t len)
{
unsigned int left;
left = buffer->buf_size - buffer->buffer.pos;
if (len < left) {
memcpy(buffer->buffer.data + buffer->buffer.pos,
data, len);
buffer->buffer.pos += len;
} else {
buffer->buffer.tail = buffer->buffer.pos;
memcpy(buffer->buffer.data, data, len);
buffer->buffer.pos = len;
buffer->buffer.circle = 1;
}
return len;
}
asmlinkage int
diag_trace_buffer_write(struct diag_trace_buffer *buffer,
const void *data, size_t len)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&buffer->buffer.lock, flags);
ret = diag_trace_buffer_write_nolock(buffer, data, len);
spin_unlock_irqrestore(&buffer->buffer.lock, flags);
return ret;
}
static asmlinkage int
__diag_trace_buffer_printk_nolock(struct diag_trace_buffer *buffer,
const char *fmt, va_list ap)
{
unsigned int len = 0;
unsigned int left;
len = vsnprintf(buffer->fmt_buffer, DIAG_TRACE_BUF_SIZE, fmt, ap);
if (len > DIAG_TRACE_BUF_SIZE)
return len;
left = buffer->buf_size - buffer->buffer.pos;
if (len < left) {
memcpy(buffer->buffer.data + buffer->buffer.pos,
buffer->fmt_buffer, len);
buffer->buffer.pos += len;
} else {
buffer->buffer.tail = buffer->buffer.pos;
memcpy(buffer->buffer.data, buffer->fmt_buffer, len);
buffer->buffer.pos = len;
buffer->buffer.circle = 1;
}
return len;
}
asmlinkage int
diag_trace_buffer_printk_nolock(struct diag_trace_buffer *buffer,
const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = __diag_trace_buffer_printk_nolock(buffer, fmt, ap);
va_end(ap);
return ret;
}
asmlinkage int
diag_trace_buffer_printk(struct diag_trace_buffer *buffer,
const char *fmt, ...)
{
int ret;
unsigned long flags;
va_list ap;
spin_lock_irqsave(&buffer->buffer.lock, flags);
va_start(ap, fmt);
ret = __diag_trace_buffer_printk_nolock(buffer, fmt, ap);
va_end(ap);
spin_unlock_irqrestore(&buffer->buffer.lock, flags);
return ret;
}
void diag_trace_buffer_mutex_lock(struct diag_trace_buffer *buffer)
{
mutex_lock(&buffer->buffer.mutex);
}
void diag_trace_buffer_mutex_unlock(struct diag_trace_buffer *buffer)
{
mutex_unlock(&buffer->buffer.mutex);
}