80 lines
2.2 KiB
C
Executable File
80 lines
2.2 KiB
C
Executable File
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_RING_BUFFER_EXT_H
|
|
#define _LINUX_RING_BUFFER_EXT_H
|
|
#include <linux/mm.h>
|
|
#include <linux/types.h>
|
|
|
|
struct rb_ext_stats {
|
|
u64 entries;
|
|
unsigned long pages_touched;
|
|
unsigned long overrun;
|
|
};
|
|
|
|
#define RB_PAGE_FT_HEAD (1 << 0)
|
|
#define RB_PAGE_FT_READER (1 << 1)
|
|
#define RB_PAGE_FT_COMMIT (1 << 2)
|
|
|
|
/*
|
|
* The pages where the events are stored are the only shared elements between
|
|
* the reader and the external writer. They are convenient to enable
|
|
* communication from the writer to the reader. The data will be used by the
|
|
* reader to update its view on the ring buffer.
|
|
*/
|
|
struct rb_ext_page_footer {
|
|
atomic_t writer_status;
|
|
atomic_t reader_status;
|
|
struct rb_ext_stats stats;
|
|
};
|
|
|
|
static inline struct rb_ext_page_footer *rb_ext_page_get_footer(void *page)
|
|
{
|
|
struct rb_ext_page_footer *footer;
|
|
unsigned long page_va = (unsigned long)page;
|
|
|
|
page_va = ALIGN_DOWN(page_va, PAGE_SIZE);
|
|
|
|
return (struct rb_ext_page_footer *)(page_va + PAGE_SIZE -
|
|
sizeof(*footer));
|
|
}
|
|
|
|
#define BUF_EXT_PAGE_SIZE (BUF_PAGE_SIZE - sizeof(struct rb_ext_page_footer))
|
|
|
|
/*
|
|
* An external writer can't rely on the internal struct ring_buffer_per_cpu.
|
|
* Instead, allow to pack the relevant information into struct
|
|
* ring_buffer_pack which can be sent to the writer. The latter can then create
|
|
* its own view on the ring buffer.
|
|
*/
|
|
struct ring_buffer_pack {
|
|
int cpu;
|
|
unsigned long reader_page_va;
|
|
unsigned long nr_pages;
|
|
unsigned long page_va[];
|
|
};
|
|
|
|
struct trace_buffer_pack {
|
|
int nr_cpus;
|
|
unsigned long total_pages;
|
|
char __data[]; /* contains ring_buffer_pack */
|
|
};
|
|
|
|
static inline
|
|
struct ring_buffer_pack *__next_ring_buffer_pack(struct ring_buffer_pack *rb_pack)
|
|
{
|
|
size_t len;
|
|
|
|
len = offsetof(struct ring_buffer_pack, page_va) +
|
|
sizeof(unsigned long) * rb_pack->nr_pages;
|
|
|
|
return (struct ring_buffer_pack *)((void *)rb_pack + len);
|
|
}
|
|
|
|
/*
|
|
* Accessor for ring_buffer_pack's within trace_buffer_pack
|
|
*/
|
|
#define for_each_ring_buffer_pack(rb_pack, cpu, trace_pack) \
|
|
for (rb_pack = (struct ring_buffer_pack *)&trace_pack->__data[0], cpu = 0; \
|
|
cpu < trace_pack->nr_cpus; \
|
|
cpu++, rb_pack = __next_ring_buffer_pack(rb_pack))
|
|
#endif
|