mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-10 23:20:54 +00:00
Communicate traces to userspace through shared memory instead of copying.
2006-10-22 Soren Sandmann <sandmann@daimi.au.dk> Communicate traces to userspace through shared memory instead of copying. * module/sysprof-module.c: Store the traces in a SysprofMmapArea. (sysprof_mmap): Implement this method. (sysprof_nopage): Implement this. (sysprof_read): Just reset the tail pointer and return zero. * module/sysprof-module.h (struct SysprofMmapArea): New structure. * collector.c (collector_stop): Unmap the device (in_dead_period): New function (on_read): Read the traces out of mmap()ed area instead of reading them. Call read() to prevent poll() from firing. (struct Collector): New members map_area and current. * Makefile.am (insert-module): Prefix modprobe with /sbin * collector.c (open_fd): mmap() the sysprof device.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
5eb19d00fa
commit
4dd37d092c
23
ChangeLog
23
ChangeLog
@ -1,3 +1,26 @@
|
|||||||
|
2006-10-22 Soren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
|
Communicate traces to userspace through shared memory instead of
|
||||||
|
copying.
|
||||||
|
|
||||||
|
* module/sysprof-module.c: Store the traces in a SysprofMmapArea.
|
||||||
|
(sysprof_mmap): Implement this method.
|
||||||
|
(sysprof_nopage): Implement this.
|
||||||
|
(sysprof_read): Just reset the tail pointer and return zero.
|
||||||
|
|
||||||
|
* module/sysprof-module.h (struct SysprofMmapArea): New
|
||||||
|
structure.
|
||||||
|
|
||||||
|
* collector.c (collector_stop): Unmap the device
|
||||||
|
(in_dead_period): New function
|
||||||
|
(on_read): Read the traces out of mmap()ed area instead of reading
|
||||||
|
them. Call read() to prevent poll() from firing.
|
||||||
|
(struct Collector): New members map_area and current.
|
||||||
|
|
||||||
|
* Makefile.am (insert-module): Prefix modprobe with /sbin
|
||||||
|
|
||||||
|
* collector.c (open_fd): mmap() the sysprof device.
|
||||||
|
|
||||||
2006-10-11 Soren Sandmann <sandmann@daimi.au.dk>
|
2006-10-11 Soren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* profile.c (profile_list_callers): Skip nodes that don't have a
|
* profile.c (profile_list_callers): Skip nodes that don't have a
|
||||||
|
|||||||
@ -90,5 +90,5 @@ EXTRA_DIST = \
|
|||||||
module/Makefile
|
module/Makefile
|
||||||
|
|
||||||
insert-module:
|
insert-module:
|
||||||
modprobe -r sysprof-module
|
/sbin/modprobe -r sysprof-module
|
||||||
modprobe sysprof-module
|
/sbin/modprobe sysprof-module
|
||||||
|
|||||||
114
collector.c
114
collector.c
@ -29,6 +29,9 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define SYSPROF_FILE "/dev/sysprof-trace"
|
||||||
|
|
||||||
static void set_no_module_error (GError **err);
|
static void set_no_module_error (GError **err);
|
||||||
static void set_cant_open_error (GError **err, int eno);
|
static void set_cant_open_error (GError **err, int eno);
|
||||||
@ -42,12 +45,14 @@ struct Collector
|
|||||||
int fd;
|
int fd;
|
||||||
GTimeVal latest_reset;
|
GTimeVal latest_reset;
|
||||||
int n_samples;
|
int n_samples;
|
||||||
|
SysprofMmapArea * map_area;
|
||||||
|
unsigned int current;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* callback is called whenever a new sample arrives */
|
/* callback is called whenever a new sample arrives */
|
||||||
Collector *
|
Collector *
|
||||||
collector_new (CollectorFunc callback,
|
collector_new (CollectorFunc callback,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
Collector *collector = g_new0 (Collector, 1);
|
Collector *collector = g_new0 (Collector, 1);
|
||||||
|
|
||||||
@ -80,7 +85,7 @@ time_diff (const GTimeVal *first,
|
|||||||
#define RESET_DEAD_PERIOD 250
|
#define RESET_DEAD_PERIOD 250
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_trace_to_stash (SysprofStackTrace *trace,
|
add_trace_to_stash (const SysprofStackTrace *trace,
|
||||||
StackStash *stash)
|
StackStash *stash)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -105,46 +110,64 @@ add_trace_to_stash (SysprofStackTrace *trace,
|
|||||||
g_free (addrs);
|
g_free (addrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
on_read (gpointer data)
|
in_dead_period (Collector *collector)
|
||||||
{
|
{
|
||||||
SysprofStackTrace trace;
|
|
||||||
Collector *collector = data;
|
|
||||||
GTimeVal now;
|
GTimeVal now;
|
||||||
int rd;
|
|
||||||
double diff;
|
double diff;
|
||||||
|
|
||||||
rd = read (collector->fd, &trace, sizeof (trace));
|
|
||||||
|
|
||||||
if (rd == -1 && errno == EWOULDBLOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_get_current_time (&now);
|
g_get_current_time (&now);
|
||||||
|
|
||||||
|
diff = time_diff (&now, &collector->latest_reset);
|
||||||
|
|
||||||
|
if (diff >= 0.0 && diff < RESET_DEAD_PERIOD)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_read (gpointer data)
|
||||||
|
{
|
||||||
|
Collector *collector = data;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
/* Make sure poll() doesn't fire immediately again */
|
||||||
|
read (collector->fd, &c, 1);
|
||||||
|
|
||||||
/* After a reset we ignore samples for a short period so that
|
/* After a reset we ignore samples for a short period so that
|
||||||
* a reset will actually cause 'samples' to become 0
|
* a reset will actually cause 'samples' to become 0
|
||||||
*/
|
*/
|
||||||
diff = time_diff (&now, &collector->latest_reset);
|
if (in_dead_period (collector))
|
||||||
|
{
|
||||||
if (diff >= 0.0 && diff < RESET_DEAD_PERIOD)
|
collector->current = collector->map_area->head;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
g_print ("pid: %d (%d)\n", trace.pid, trace.n_addresses);
|
|
||||||
for (i=0; i < trace.n_addresses; ++i)
|
|
||||||
g_print ("rd: %08x\n", trace.addresses[i]);
|
|
||||||
g_print ("-=-\n");
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (rd > 0)
|
while (collector->current != collector->map_area->head)
|
||||||
{
|
{
|
||||||
add_trace_to_stash (&trace, collector->stash);
|
const SysprofStackTrace *trace;
|
||||||
|
|
||||||
|
trace = &(collector->map_area->traces[collector->current]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
g_print ("pid: %d (%d)\n", trace.pid, trace.n_addresses);
|
||||||
|
for (i=0; i < trace.n_addresses; ++i)
|
||||||
|
g_print ("rd: %08x\n", trace.addresses[i]);
|
||||||
|
g_print ("-=-\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
add_trace_to_stash (trace, collector->stash);
|
||||||
|
|
||||||
|
collector->current++;
|
||||||
|
if (collector->current >= SYSPROF_N_TRACES)
|
||||||
|
collector->current = 0;
|
||||||
|
|
||||||
collector->n_samples++;
|
collector->n_samples++;
|
||||||
|
|
||||||
if (collector->callback)
|
if (collector->callback)
|
||||||
collector->callback (collector->data);
|
collector->callback (collector->data);
|
||||||
}
|
}
|
||||||
@ -176,6 +199,7 @@ open_fd (Collector *collector,
|
|||||||
GError **err)
|
GError **err)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
void *map_area;
|
||||||
|
|
||||||
fd = open (SYSPROF_FILE, O_RDONLY);
|
fd = open (SYSPROF_FILE, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -183,16 +207,16 @@ open_fd (Collector *collector,
|
|||||||
if (load_module())
|
if (load_module())
|
||||||
{
|
{
|
||||||
GTimer *timer = g_timer_new ();
|
GTimer *timer = g_timer_new ();
|
||||||
|
|
||||||
while (fd < 0 && g_timer_elapsed (timer, NULL) < 0.5)
|
while (fd < 0 && g_timer_elapsed (timer, NULL) < 0.5)
|
||||||
{
|
{
|
||||||
/* Wait for udev to discover the new device */
|
/* Wait for udev to discover the new device */
|
||||||
usleep (100000);
|
usleep (100000);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
fd = open (SYSPROF_FILE, O_RDONLY);
|
fd = open (SYSPROF_FILE, O_RDONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_timer_destroy (timer);
|
g_timer_destroy (timer);
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -201,7 +225,7 @@ open_fd (Collector *collector,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
set_no_module_error (err);
|
set_no_module_error (err);
|
||||||
@ -210,6 +234,18 @@ open_fd (Collector *collector,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map_area = mmap (NULL, sizeof (SysprofMmapArea), PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
|
if (map_area == MAP_FAILED)
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
set_cant_open_error (err, errno);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
collector->map_area = map_area;
|
||||||
|
collector->current = 0;
|
||||||
collector->fd = fd;
|
collector->fd = fd;
|
||||||
fd_add_watch (collector->fd, collector);
|
fd_add_watch (collector->fd, collector);
|
||||||
|
|
||||||
@ -218,7 +254,7 @@ open_fd (Collector *collector,
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
collector_start (Collector *collector,
|
collector_start (Collector *collector,
|
||||||
GError **err)
|
GError **err)
|
||||||
{
|
{
|
||||||
if (collector->fd < 0 && !open_fd (collector, err))
|
if (collector->fd < 0 && !open_fd (collector, err))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -234,6 +270,10 @@ collector_stop (Collector *collector)
|
|||||||
{
|
{
|
||||||
fd_remove_watch (collector->fd);
|
fd_remove_watch (collector->fd);
|
||||||
|
|
||||||
|
munmap (collector->map_area, sizeof (SysprofMmapArea));
|
||||||
|
collector->map_area = NULL;
|
||||||
|
collector->current = 0;
|
||||||
|
|
||||||
close (collector->fd);
|
close (collector->fd);
|
||||||
collector->fd = -1;
|
collector->fd = -1;
|
||||||
}
|
}
|
||||||
@ -244,7 +284,7 @@ collector_reset (Collector *collector)
|
|||||||
{
|
{
|
||||||
if (collector->stash)
|
if (collector->stash)
|
||||||
stack_stash_unref (collector->stash);
|
stack_stash_unref (collector->stash);
|
||||||
|
|
||||||
process_flush_caches();
|
process_flush_caches();
|
||||||
|
|
||||||
collector->stash = stack_stash_new (NULL);
|
collector->stash = stack_stash_new (NULL);
|
||||||
@ -316,7 +356,7 @@ resolve_symbols (GList *trace, gint size, gpointer data)
|
|||||||
stack_stash_add_trace (info->resolved_stash,
|
stack_stash_add_trace (info->resolved_stash,
|
||||||
(gulong *)resolved_trace->pdata,
|
(gulong *)resolved_trace->pdata,
|
||||||
resolved_trace->len, size);
|
resolved_trace->len, size);
|
||||||
|
|
||||||
g_ptr_array_free (resolved_trace, TRUE);
|
g_ptr_array_free (resolved_trace, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,13 +370,13 @@ collector_create_profile (Collector *collector)
|
|||||||
info.unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal);
|
info.unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||||
|
|
||||||
stack_stash_foreach (collector->stash, resolve_symbols, &info);
|
stack_stash_foreach (collector->stash, resolve_symbols, &info);
|
||||||
|
|
||||||
/* FIXME: we are leaking the value strings in info.unique_symbols */
|
/* FIXME: we are leaking the value strings in info.unique_symbols */
|
||||||
|
|
||||||
g_hash_table_destroy (info.unique_symbols);
|
g_hash_table_destroy (info.unique_symbols);
|
||||||
|
|
||||||
profile = profile_new (info.resolved_stash);
|
profile = profile_new (info.resolved_stash);
|
||||||
|
|
||||||
stack_stash_unref (info.resolved_stash);
|
stack_stash_unref (info.resolved_stash);
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
|
|||||||
@ -53,11 +53,9 @@
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
|
MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
|
||||||
|
|
||||||
#define N_TRACES 256
|
static unsigned char area_backing [sizeof (SysprofMmapArea) + PAGE_SIZE];
|
||||||
|
static SysprofMmapArea *area;
|
||||||
static SysprofStackTrace stack_traces[N_TRACES];
|
static atomic_t client_count = ATOMIC_INIT(0);
|
||||||
static SysprofStackTrace * head = &stack_traces[0];
|
|
||||||
static atomic_t client_count = ATOMIC_INIT(0);
|
|
||||||
|
|
||||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_trace);
|
DECLARE_WAIT_QUEUE_HEAD (wait_for_trace);
|
||||||
|
|
||||||
@ -119,7 +117,7 @@ timer_notify (struct pt_regs *regs)
|
|||||||
struct pt_regs * regs = (struct pt_regs *)data;
|
struct pt_regs * regs = (struct pt_regs *)data;
|
||||||
#endif
|
#endif
|
||||||
void *frame_pointer;
|
void *frame_pointer;
|
||||||
SysprofStackTrace *trace = head;
|
SysprofStackTrace *trace = &(area->traces[area->head]);
|
||||||
int i;
|
int i;
|
||||||
int is_user;
|
int is_user;
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
@ -211,8 +209,8 @@ timer_notify (struct pt_regs *regs)
|
|||||||
else
|
else
|
||||||
trace->truncated = 0;
|
trace->truncated = 0;
|
||||||
|
|
||||||
if (head++ == &stack_traces[N_TRACES - 1])
|
if (area->head++ == SYSPROF_N_TRACES - 1)
|
||||||
head = &stack_traces[0];
|
area->head = 0;
|
||||||
|
|
||||||
wake_up (&wait_for_trace);
|
wake_up (&wait_for_trace);
|
||||||
|
|
||||||
@ -232,27 +230,9 @@ static struct notifier_block timer_notifier = {
|
|||||||
static int
|
static int
|
||||||
sysprof_read(struct file *file, char *buffer, size_t count, loff_t *offset)
|
sysprof_read(struct file *file, char *buffer, size_t count, loff_t *offset)
|
||||||
{
|
{
|
||||||
SysprofStackTrace *trace;
|
file->private_data = &(area->traces[area->head]);
|
||||||
SysprofStackTrace *tail = file->private_data;
|
|
||||||
|
|
||||||
if (count < sizeof *tail)
|
|
||||||
return -EMSGSIZE;
|
|
||||||
|
|
||||||
if (head == tail)
|
return 0;
|
||||||
return -EWOULDBLOCK;
|
|
||||||
|
|
||||||
trace = tail;
|
|
||||||
if (tail++ == &stack_traces[N_TRACES - 1])
|
|
||||||
tail = &stack_traces[0];
|
|
||||||
|
|
||||||
BUG_ON(trace->pid == 0);
|
|
||||||
|
|
||||||
if (copy_to_user(buffer, trace, sizeof *trace))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
file->private_data = tail;
|
|
||||||
|
|
||||||
return sizeof *tail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@ -260,12 +240,12 @@ sysprof_poll(struct file *file, poll_table *poll_table)
|
|||||||
{
|
{
|
||||||
SysprofStackTrace *tail = file->private_data;
|
SysprofStackTrace *tail = file->private_data;
|
||||||
|
|
||||||
if (head != tail)
|
if (&(area->traces[area->head]) != tail)
|
||||||
return POLLIN | POLLRDNORM;
|
return POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
poll_wait(file, &wait_for_trace, poll_table);
|
poll_wait(file, &wait_for_trace, poll_table);
|
||||||
|
|
||||||
if (head != tail)
|
if (&(area->traces[area->head]) != tail)
|
||||||
return POLLIN | POLLRDNORM;
|
return POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -284,11 +264,56 @@ sysprof_open(struct inode *inode, struct file *file)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
file->private_data = head;
|
file->private_data = &(area->traces[area->head]);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct page *
|
||||||
|
sysprof_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
|
||||||
|
{
|
||||||
|
unsigned long area_start;
|
||||||
|
unsigned long virt;
|
||||||
|
struct page *page_ptr;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printk (KERN_ALERT "nopage called: %p (offset: %d) area: %p\n", addr, addr - vma->vm_start, area);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
area_start = (unsigned long)area;
|
||||||
|
|
||||||
|
virt = area_start + (addr - vma->vm_start);
|
||||||
|
|
||||||
|
if (virt > area_start + sizeof (SysprofMmapArea))
|
||||||
|
return NOPAGE_SIGBUS;
|
||||||
|
|
||||||
|
page_ptr = vmalloc_to_page ((void *)virt);
|
||||||
|
|
||||||
|
get_page (page_ptr);
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
*type = VM_FAULT_MINOR;
|
||||||
|
|
||||||
|
return page_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sysprof_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
static struct vm_operations_struct ops = {
|
||||||
|
.nopage = sysprof_nopage,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vma->vm_flags & (VM_WRITE | VM_EXEC))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
vma->vm_flags |= VM_RESERVED;
|
||||||
|
|
||||||
|
vma->vm_ops = &ops;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sysprof_release(struct inode *inode, struct file *file)
|
sysprof_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
@ -309,6 +334,7 @@ static struct file_operations sysprof_fops = {
|
|||||||
.poll = sysprof_poll,
|
.poll = sysprof_poll,
|
||||||
.open = sysprof_open,
|
.open = sysprof_open,
|
||||||
.release = sysprof_release,
|
.release = sysprof_release,
|
||||||
|
.mmap = sysprof_mmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct miscdevice sysprof_miscdev = {
|
static struct miscdevice sysprof_miscdev = {
|
||||||
@ -321,6 +347,7 @@ int
|
|||||||
init_module(void)
|
init_module(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long area_page;
|
||||||
|
|
||||||
ret = misc_register(&sysprof_miscdev);
|
ret = misc_register(&sysprof_miscdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -328,8 +355,12 @@ init_module(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
area_page = (unsigned long)&(area_backing[4096]) & PAGE_MASK;
|
||||||
|
area = (SysprofMmapArea *)area_page;
|
||||||
|
area->head = 0;
|
||||||
|
|
||||||
printk(KERN_ALERT "sysprof: loaded (%s)\n", PACKAGE_VERSION);
|
printk(KERN_ALERT "sysprof: loaded (%s)\n", PACKAGE_VERSION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,9 +373,6 @@ cleanup_module(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* The old userspace_reader code - someday it may be useful again */
|
/* The old userspace_reader code - someday it may be useful again */
|
||||||
|
|
||||||
|
|||||||
@ -20,10 +20,11 @@
|
|||||||
#ifndef SYSPROF_MODULE_H
|
#ifndef SYSPROF_MODULE_H
|
||||||
#define SYSPROF_MODULE_H
|
#define SYSPROF_MODULE_H
|
||||||
|
|
||||||
#define SYSPROF_FILE "/dev/sysprof-trace"
|
|
||||||
|
|
||||||
typedef struct SysprofStackTrace SysprofStackTrace;
|
typedef struct SysprofStackTrace SysprofStackTrace;
|
||||||
|
typedef struct SysprofStackInfo SysprofStackInfo;
|
||||||
|
typedef struct SysprofMmapArea SysprofMmapArea;
|
||||||
|
|
||||||
|
#define SYSPROF_N_TRACES 256
|
||||||
#define SYSPROF_MAX_ADDRESSES 512
|
#define SYSPROF_MAX_ADDRESSES 512
|
||||||
|
|
||||||
struct SysprofStackTrace
|
struct SysprofStackTrace
|
||||||
@ -36,4 +37,11 @@ struct SysprofStackTrace
|
|||||||
void *addresses[SYSPROF_MAX_ADDRESSES];
|
void *addresses[SYSPROF_MAX_ADDRESSES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SysprofMmapArea
|
||||||
|
{
|
||||||
|
unsigned int head;
|
||||||
|
|
||||||
|
SysprofStackTrace traces[SYSPROF_N_TRACES];
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user