From 08ba6bfbd369cd5315f3832115ac23bcd63bd7fc Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Sun, 6 Sep 2009 20:43:57 -0400 Subject: [PATCH] Use two consecutive mappings of the ring buffer. This allows us to not ignore wrapping and just process events instead of having to copy the data to temporary storage. --- collector.c | 171 +++++++++++++++++++++++------------------------------------- 1 file changed, 66 insertions(+), 105 deletions(-) diff --git a/collector.c b/collector.c index 524696c..fbc8580 100644 --- a/collector.c +++ b/collector.c @@ -127,130 +127,92 @@ sysprof_perf_counter_open (struct perf_counter_attr *attr, return syscall (__NR_perf_counter_open, attr, pid, cpu, group_fd, flags); } -static int -process_event (counter_t *counter, void *data) -{ - struct perf_event_header *header = data; - - counter->callback ((counter_event_t *)header, counter->user_data); - - return header->size; -} - -static int -n_missing_bytes (const uint8_t *data, int n_bytes) -{ - const struct perf_event_header *header; - - if (n_bytes < sizeof (*header)) - return sizeof (*header) - n_bytes; - - header = (const void *)data; - - if (n_bytes < header->size) - return header->size - n_bytes; - - return 0; -} - -static void -process_events (counter_t *counter, uint8_t *data, int n_bytes, - GString *partial) -{ - int n_events; - ssize_t n_missing; - - n_events = 0; - - while (n_bytes && (n_missing = n_missing_bytes ( - (uint8_t *)partial->str, partial->len))) - { - n_missing = MIN (n_bytes, n_missing); - - g_string_append_len (partial, (const char *)data, n_missing); - - data += n_missing; - n_bytes -= n_missing; - } - - if (partial->len) - { - int n_used; - - if (n_missing_bytes ((uint8_t *)partial->str, partial->len)) - return; - - n_used = process_event (counter, partial->str); - - g_assert (n_used == partial->len); - - g_string_truncate (partial, 0); - } - - while (n_bytes && !n_missing_bytes (data, n_bytes)) - { - int n_used = process_event (counter, data); - - data += n_used; - n_bytes -= n_used; - } - - if (n_missing_bytes (data, n_bytes)) - g_string_append_len (partial, (char *)data, n_bytes); -} - - static void on_read (gpointer data) { uint64_t head, tail; counter_t *counter = data; int mask = (N_PAGES * process_get_page_size() - 1); - uint64_t size; - int diff; - +#if 0 + int n_bytes = mask + 1; + int x; +#endif + tail = counter->tail; head = counter->mmap_page->data_head; rmb(); - diff = head - tail; - - if (diff < 0) + if (head < tail) { - g_warning ("sysprof fails at reading the buffer\n"); + g_warning ("sysprof fails at ring buffers\n"); tail = head; } - size = head - tail; +#if 0 + /* Verify that the double mapping works */ + x = g_random_int() & mask; + g_assert (*(counter->data + x) == *(counter->data + x + n_bytes)); +#endif - if ((tail & mask) + size != (head & mask)) + while (head - tail >= sizeof (struct perf_event_header)) { - size = mask + 1 - (tail & mask); - - g_assert ((tail & mask) + size <= (N_PAGES * process_get_page_size())); - - process_events (counter, counter->data + (tail & mask), - size, counter->partial); - - tail += size; + struct perf_event_header *header = (void *)(counter->data + (tail & mask)); + + if (header->size > head - tail) + { + g_print ("asdf\n"); + break; + } + + counter->callback ((counter_event_t *)header, counter->user_data); + + tail += header->size; } - - size = head - tail; - - g_assert ((tail & mask) + size <= (N_PAGES * process_get_page_size())); - - process_events (counter, - counter->data + (tail & mask), size, counter->partial); - - tail += size; - + counter->tail = tail; counter->mmap_page->data_tail = tail; } -#define fail(x) +/* FIXME: return proper errors */ +#define fail(x) \ + do { \ + g_printerr ("the fail is strong %s\n", x); \ + exit (-1); \ + } while (0) + +static void * +map_buffer (counter_t *counter) +{ + int n_bytes = N_PAGES * process_get_page_size(); + void *address, *a; + + address = mmap (NULL, n_bytes * 2 + process_get_page_size(), PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + + if (address == MAP_FAILED) + fail ("mmap"); + + a = mmap (address + n_bytes, n_bytes + process_get_page_size(), + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, counter->fd, 0); + + if (a != address + n_bytes) + fail ("mmap"); + + a = mmap (address, n_bytes + process_get_page_size(), + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, counter->fd, 0); + + if (a == MAP_FAILED) + fail ("mmap"); + + if (a != address) + fail ("mmap"); + + return address; +} static counter_t * counter_new (int cpu, @@ -283,11 +245,10 @@ counter_new (int cpu, fail ("perf_counter_open"); return NULL; } - + counter->fd = fd; - counter->mmap_page = mmap ( - NULL, (N_PAGES + 1) * process_get_page_size(), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + counter->mmap_page = map_buffer (counter); if (counter->mmap_page == MAP_FAILED) { -- 2.7.4