aboutsummaryrefslogtreecommitdiff
path: root/driver/gator_annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/gator_annotate.c')
-rw-r--r--driver/gator_annotate.c184
1 files changed, 76 insertions, 108 deletions
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index 36a921c..b2288b3 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -15,65 +15,93 @@
#include <asm/current.h>
#include <linux/spinlock.h>
-#define ANNOTATE_SIZE (16*1024)
static DEFINE_SPINLOCK(annotate_lock);
-static char *annotateBuf;
-static char *annotateBuf0;
-static char *annotateBuf1;
-static int annotatePos;
-static int annotateSel;
static bool collect_annotations = false;
-static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
+static int annotate_copy(struct file *file, char const __user *buf, size_t count)
{
- char tempBuffer[512];
- int remaining, size;
- uint32_t tid;
+ int cpu = 0;
+ int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF];
+
+ if (file == NULL) {
+ // copy from kernel
+ memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count);
+ } else {
+ // copy from user space
+ if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0)
+ return -1;
+ }
+ per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF] = (write + count) & gator_buffer_mask[ANNOTATE_BUF];
+
+ return 0;
+}
+
+static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
+{
+ int tid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
if (*offset)
return -EINVAL;
- // determine size to capture
- size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
+ if (!collect_annotations) {
+ return count_orig;
+ }
+
+ cpu = 0; // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
- // note: copy may be for naught if remaining is zero, but better to do the copy outside of the spinlock
if (file == NULL) {
- // copy from kernel
- memcpy(tempBuffer, buf, size);
-
- // set the thread id to the kernel thread, not the current thread
- tid = -1;
+ tid = -1; // set the thread id to the kernel thread
} else {
- // copy from user space
- if (copy_from_user(tempBuffer, buf, size) != 0)
- return -EINVAL;
tid = current->pid;
}
- // synchronize shared variables annotateBuf and annotatePos
+ // synchronize between cores
spin_lock(&annotate_lock);
- if (collect_annotations && annotateBuf) {
- remaining = ANNOTATE_SIZE - annotatePos - 256; // pad for headers and release
- size = size < remaining ? size : remaining;
- if (size > 0) {
- uint64_t time = gator_get_time();
- uint32_t cpuid = smp_processor_id();
- int pos = annotatePos;
- pos += gator_write_packed_int(&annotateBuf[pos], tid);
- pos += gator_write_packed_int64(&annotateBuf[pos], time);
- pos += gator_write_packed_int(&annotateBuf[pos], cpuid);
- pos += gator_write_packed_int(&annotateBuf[pos], size);
- memcpy(&annotateBuf[pos], tempBuffer, size);
- annotatePos = pos + size;
- }
- }
- spin_unlock(&annotate_lock);
+
+ // determine total size of the payload
+ header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
+ available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
+ size = count < available ? count : available;
if (size <= 0) {
- wake_up(&gator_buffer_wait);
- return 0;
+ size = 0;
+ goto annotate_write_out;
}
+ // synchronize shared variables annotateBuf and annotatePos
+ if (collect_annotations && per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time());
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
+
+ // determine the sizes to capture, length1 + length2 will equal size
+ contiguous = contiguous_space_available(cpu, ANNOTATE_BUF);
+ if (size < contiguous) {
+ length1 = size;
+ length2 = 0;
+ } else {
+ length1 = contiguous;
+ length2 = size - contiguous;
+ }
+
+ if (annotate_copy(file, buf, length1) != 0) {
+ size = -EINVAL;
+ goto annotate_write_out;
+ }
+
+ if (length2 > 0 && annotate_copy(file, &buf[length1], length2) != 0) {
+ size = -EINVAL;
+ goto annotate_write_out;
+ }
+
+ // Check and commit; commit is set to occur once buffer is 3/4 full
+ buffer_check(cpu, ANNOTATE_BUF);
+ }
+
+annotate_write_out:
+ spin_unlock(&annotate_lock);
+
// return the number of bytes written
return size;
}
@@ -82,21 +110,18 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
static int annotate_release(struct inode *inode, struct file *file)
{
- int remaining = ANNOTATE_SIZE - annotatePos;
- if (remaining < 16) {
- return -EFAULT;
- }
+ int cpu = 0;
+ // synchronize between cores
spin_lock(&annotate_lock);
- if (annotateBuf) {
+
+ if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
uint32_t tid = current->pid;
- int pos = annotatePos;
- pos += gator_write_packed_int(&annotateBuf[pos], tid);
- pos += gator_write_packed_int64(&annotateBuf[pos], 0); // time
- pos += gator_write_packed_int(&annotateBuf[pos], 0); // cpuid
- pos += gator_write_packed_int(&annotateBuf[pos], 0); // size
- annotatePos = pos;
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, tid);
+ gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time
+ gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size
}
+
spin_unlock(&annotate_lock);
return 0;
@@ -109,25 +134,11 @@ static const struct file_operations annotate_fops = {
static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
{
- annotateBuf = NULL;
return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
}
-static int gator_annotate_init(void)
-{
- annotateBuf0 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
- annotateBuf1 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
- if (!annotateBuf0 || !annotateBuf1)
- return -1;
- return 0;
-}
-
static int gator_annotate_start(void)
{
- annotateSel = 0;
- annotatePos = 1;
- annotateBuf = annotateBuf0;
- annotateBuf[0] = FRAME_ANNOTATE;
collect_annotations = true;
return 0;
}
@@ -136,46 +147,3 @@ static void gator_annotate_stop(void)
{
collect_annotations = false;
}
-
-static void gator_annotate_shutdown(void)
-{
- spin_lock(&annotate_lock);
- annotateBuf = NULL;
- spin_unlock(&annotate_lock);
-}
-
-static void gator_annotate_exit(void)
-{
- spin_lock(&annotate_lock);
- kfree(annotateBuf0);
- kfree(annotateBuf1);
- annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
- spin_unlock(&annotate_lock);
-}
-
-static int gator_annotate_ready(void)
-{
- return annotatePos > 1 && annotateBuf;
-}
-
-static int gator_annotate_read(char **buffer)
-{
- int len;
-
- if (!gator_annotate_ready())
- return 0;
-
- annotateSel = !annotateSel;
-
- if (buffer)
- *buffer = annotateBuf;
-
- spin_lock(&annotate_lock);
- len = annotatePos;
- annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
- annotateBuf[0] = FRAME_ANNOTATE;
- annotatePos = 1;
- spin_unlock(&annotate_lock);
-
- return len;
-}