diff --git a/driver/gator_main.c b/driver/gator_main.c
index 3e62b59680278bf6c342b41a3f72cfa6aa5b062d..5eab03456ce67060b0828dc82247aec3ba91be85 100644 (file)
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
*/
// This version must match the gator daemon version
-static unsigned long gator_protocol_version = 13;
+static unsigned long gator_protocol_version = 14;
#include <linux/slab.h>
#include <linux/cpu.h>
#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
#ifndef CONFIG_PERF_EVENTS
-#error gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
+#warning gator requires the kernel to have CONFIG_PERF_EVENTS defined to support pmu hardware counters
#elif !defined CONFIG_HW_PERF_EVENTS
-#error gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
+#warning gator requires the kernel to have CONFIG_HW_PERF_EVENTS defined to support pmu hardware counters
#endif
#endif
static int buffer_bytes_available(int cpu, int buftype);
static bool buffer_check_space(int cpu, int buftype, int bytes);
static int contiguous_space_available(int cpu, int bufytpe);
-static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x);
-static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x);
+static void gator_buffer_write_packed_int(int cpu, int buftype, int x);
+static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x);
static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
static void gator_buffer_write_string(int cpu, int buftype, const char *x);
static void gator_add_trace(int cpu, unsigned long address);
return true;
}
}
+ *cpu = -1;
+ *buftype = -1;
return false;
}
if (length < 0) {
length += gator_buffer_size[buftype];
}
- length = length - type_length - sizeof(int);
+ length = length - type_length - sizeof(s32);
if (length <= FRAME_HEADER_SIZE) {
// Nothing to write, only the frame header is present
return;
}
- for (byte = 0; byte < sizeof(int); byte++) {
+ for (byte = 0; byte < sizeof(s32); byte++) {
per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
}
// Offline any events and output counters
time = gator_get_time();
- if (marshal_event_header()) {
+ if (marshal_event_header(time)) {
list_for_each_entry(gi, &gator_events, list) {
if (gi->offline) {
len = gi->offline(&buffer, migrate);
struct gator_interface *gi;
int len, cpu = get_physical_cpu();
int *buffer;
+ u64 time;
gator_trace_power_online();
// online any events and output counters
- if (marshal_event_header()) {
+ time = gator_get_time();
+ if (marshal_event_header(time)) {
list_for_each_entry(gi, &gator_events, list) {
if (gi->online) {
len = gi->online(&buffer, migrate);
}
}
// Only check after writing all counters so that time and corresponding counters appear in the same frame
- buffer_check(cpu, BLOCK_COUNTER_BUF, gator_get_time());
+ buffer_check(cpu, BLOCK_COUNTER_BUF, time);
}
if (!migrate) {
if (!printed_monotonic_warning && delta > 500000) {
printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta);
printed_monotonic_warning = true;
- } else {
- pr_debug("%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\n", __FUNCTION__, cpu, delta);
}
timestamp = prev_timestamp;
}
if (gator_events_list[i])
gator_events_list[i]();
+ gator_trace_sched_init();
gator_trace_power_init();
return 0;
return 0;
}
-static ssize_t userspace_buffer_read(struct file *file, char __user *buf,
- size_t count, loff_t *offset)
+static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- int retval = -EINVAL;
- int commit = 0, length1, length2, read;
+ int commit, length1, length2, read;
char *buffer1;
- char *buffer2 = NULL;
+ char *buffer2;
int cpu, buftype;
+ int written = 0;
- /* do not handle partial reads */
- if (count != userspace_buffer_size || *offset)
+ // ensure there is enough space for a whole frame
+ if (count < userspace_buffer_size || *offset) {
return -EINVAL;
+ }
// sleep until the condition is true or a signal is received
// the condition is checked each time gator_buffer_wait is woken up
- buftype = cpu = -1;
wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || !gator_started);
- if (signal_pending(current))
+ if (signal_pending(current)) {
return -EINTR;
-
- length2 = 0;
- retval = -EFAULT;
-
- mutex_lock(&gator_buffer_mutex);
+ }
if (buftype == -1 || cpu == -1) {
- retval = 0;
- goto out;
+ return 0;
}
- read = per_cpu(gator_buffer_read, cpu)[buftype];
- commit = per_cpu(gator_buffer_commit, cpu)[buftype];
+ mutex_lock(&gator_buffer_mutex);
- /* May happen if the buffer is freed during pending reads. */
- if (!per_cpu(gator_buffer, cpu)[buftype]) {
- retval = -EFAULT;
- goto out;
- }
+ do {
+ read = per_cpu(gator_buffer_read, cpu)[buftype];
+ commit = per_cpu(gator_buffer_commit, cpu)[buftype];
- /* determine the size of two halves */
- length1 = commit - read;
- buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]);
- buffer2 = &(per_cpu(gator_buffer, cpu)[buftype][0]);
- if (length1 < 0) {
- length1 = gator_buffer_size[buftype] - read;
- length2 = commit;
- }
+ // May happen if the buffer is freed during pending reads.
+ if (!per_cpu(gator_buffer, cpu)[buftype]) {
+ break;
+ }
- /* start, middle or end */
- if (length1 > 0) {
- if (copy_to_user(&buf[0], buffer1, length1)) {
- goto out;
+ // determine the size of two halves
+ length1 = commit - read;
+ length2 = 0;
+ buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]);
+ buffer2 = &(per_cpu(gator_buffer, cpu)[buftype][0]);
+ if (length1 < 0) {
+ length1 = gator_buffer_size[buftype] - read;
+ length2 = commit;
}
- }
- /* possible wrap around */
- if (length2 > 0) {
- if (copy_to_user(&buf[length1], buffer2, length2)) {
- goto out;
+ if (length1 + length2 > count - written) {
+ break;
}
- }
- per_cpu(gator_buffer_read, cpu)[buftype] = commit;
- retval = length1 + length2;
+ // start, middle or end
+ if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) {
+ break;
+ }
- /* kick just in case we've lost an SMP event */
- wake_up(&gator_buffer_wait);
+ // possible wrap around
+ if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) {
+ break;
+ }
- // Wake up annotate_write if more space is available
- if (buftype == ANNOTATE_BUF) {
- wake_up(&gator_annotate_wait);
- }
+ per_cpu(gator_buffer_read, cpu)[buftype] = commit;
+ written += length1 + length2;
+
+ // Wake up annotate_write if more space is available
+ if (buftype == ANNOTATE_BUF) {
+ wake_up(&gator_annotate_wait);
+ }
+ } while (buffer_commit_ready(&cpu, &buftype));
-out:
mutex_unlock(&gator_buffer_mutex);
- return retval;
+
+ // kick just in case we've lost an SMP event
+ wake_up(&gator_buffer_wait);
+
+ return written > 0 ? written : -EFAULT;
}
const struct file_operations gator_event_buffer_fops = {
if (gi->create_files)
gi->create_files(sb, dir);
+ // Sched Events
+ sched_trace_create_files(sb, dir);
+
// Power interface
gator_trace_power_create_files(sb, dir);
}