gator: ARM DS-5.6 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_annotate.c
index 18441576c183967bd0cbbfd58ec05543c9782d04..d8d86afd10a717d59dfe8afce90123dfd96bda41 100644 (file)
@@ -1,5 +1,5 @@
 /**
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,7 +15,7 @@
 #include <asm/current.h>
 #include <linux/spinlock.h>
 
 #include <asm/current.h>
 #include <linux/spinlock.h>
 
-#define INSTSIZE       1024
+#define ANNOTATE_SIZE  (16*1024)
 static DEFINE_SPINLOCK(annotate_lock);
 static char *annotateBuf;
 static char *annotateBuf0;
 static DEFINE_SPINLOCK(annotate_lock);
 static char *annotateBuf;
 static char *annotateBuf0;
@@ -23,113 +23,144 @@ static char *annotateBuf1;
 static int annotatePos;
 static int annotateSel;
 
 static int annotatePos;
 static int annotateSel;
 
-static int gatorfs_copy_from_user(char* localbuf, char const __user *buf, size_t count)
-{
-       if (count == 0)
-               return 0;
-
-       if (copy_from_user(localbuf, buf, count))
-               return -EFAULT;
-
-       return 0;
-}
-
 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
 {
 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
 {
-       char tempBuffer[32];
-       unsigned long flags;
+       char tempBuffer[512];
        int retval, remaining, size;
 
        if (*offset)
                return -EINVAL;
 
        // determine size to capture
        int retval, remaining, size;
 
        if (*offset)
                return -EINVAL;
 
        // determine size to capture
-       remaining = INSTSIZE - annotatePos - 24; // leave some extra space
+       remaining = ANNOTATE_SIZE - annotatePos - 256; // pad for headers and release
        size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
        size = size < remaining ? size : remaining;
        size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
        size = size < remaining ? size : remaining;
-       if (size <= 0)
+       if (size <= 0) {
+               wake_up(&gator_buffer_wait);
                return 0;
                return 0;
+       }
 
        // copy from user space
 
        // copy from user space
-       retval = gatorfs_copy_from_user(tempBuffer, buf, size);
+       retval = copy_from_user(tempBuffer, buf, size);
        if (retval == 0) {
                // synchronize shared variables annotateBuf and annotatePos
        if (retval == 0) {
                // synchronize shared variables annotateBuf and annotatePos
-               spin_lock_irqsave(&annotate_lock, flags);
-               if (!annotateBuf) {
-                       size = -EINVAL;
-               } else  {
-                       *(int*)&annotateBuf[annotatePos + 0] = current->pid;            // thread id
-                       *(int*)&annotateBuf[annotatePos + 4] = size;                            // length in bytes
-                       memcpy(&annotateBuf[annotatePos + 8], tempBuffer, size);        // data
-                       annotatePos = annotatePos + 8 + size;                                           // increment position
-                       annotatePos = (annotatePos + 3) & ~3;                                           // align to 4-byte boundary
+               spin_lock(&annotate_lock);
+               if (annotateBuf) {
+                       uint32_t tid = current->pid;
+                       uint32_t tick = gator_master_tick;
+                       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_int(&annotateBuf[pos], tick);
+                       pos += gator_write_packed_int(&annotateBuf[pos], time);
+                       pos += gator_write_packed_int(&annotateBuf[pos], time >> 32);
+                       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_irqrestore(&annotate_lock, flags);
+               spin_unlock(&annotate_lock);
 
                // return the number of bytes written
                retval = size;
 
                // return the number of bytes written
                retval = size;
+       } else {
+               retval = -EINVAL;
        }
 
        return retval;
 }
 
        }
 
        return retval;
 }
 
+static int annotate_release(struct inode *inode, struct file *file)
+{
+       int remaining = ANNOTATE_SIZE - annotatePos;
+       if (remaining < 16) {
+               return -EFAULT;
+       }
+
+       spin_lock(&annotate_lock);
+       if (annotateBuf) {
+               uint32_t tid = current->pid;
+               uint32_t tick = gator_master_tick;
+               int pos = annotatePos;
+               pos += gator_write_packed_int(&annotateBuf[pos], tid);
+               pos += gator_write_packed_int(&annotateBuf[pos], tick);
+               pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
+               pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
+               pos += gator_write_packed_int(&annotateBuf[pos], 0); // cpuid
+               pos += gator_write_packed_int(&annotateBuf[pos], 0); // size
+               annotatePos = pos;
+       }
+       spin_unlock(&annotate_lock);
+
+       return 0;
+}
+
 static const struct file_operations annotate_fops = {
 static const struct file_operations annotate_fops = {
-       .write          = annotate_write
+       .write          = annotate_write,
+       .release        = annotate_release
 };
 
 };
 
-int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
+static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
 {
 {
-       annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
+       annotateBuf = NULL;
        return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
 }
 
        return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
 }
 
-int gator_annotate_init(void)
+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;
 }
 
        return 0;
 }
 
-int gator_annotate_start(void)
+static int gator_annotate_start(void)
 {
        annotatePos = annotateSel = 0;
 {
        annotatePos = annotateSel = 0;
-       annotateBuf0 = kmalloc(INSTSIZE, GFP_KERNEL);
-       annotateBuf1 = kmalloc(INSTSIZE, GFP_KERNEL);
        annotateBuf = annotateBuf0;
        annotateBuf = annotateBuf0;
-       if (!annotateBuf0 || !annotateBuf1)
-               return -1;
        return 0;
 }
 
        return 0;
 }
 
-void gator_annotate_stop(void)
+static void gator_annotate_stop(void)
 {
        spin_lock(&annotate_lock);
 {
        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;
        kfree(annotateBuf0);
        kfree(annotateBuf1);
        annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
-
        spin_unlock(&annotate_lock);
 }
 
        spin_unlock(&annotate_lock);
 }
 
-int gator_annotate_read(int **buffer)
+static int gator_annotate_ready(void)
+{
+       return annotatePos && annotateBuf;
+}
+
+static int gator_annotate_read(char **buffer)
 {
        int len;
 
 {
        int len;
 
-       if (smp_processor_id() || !annotatePos || !annotateBuf)
+       if (!gator_annotate_ready())
                return 0;
 
        annotateSel = !annotateSel;
 
        if (buffer)
                return 0;
 
        annotateSel = !annotateSel;
 
        if (buffer)
-               *buffer = (int *)annotateBuf;
+               *buffer = annotateBuf;
 
        spin_lock(&annotate_lock);
 
        spin_lock(&annotate_lock);
-
        len = annotatePos;
        annotatePos = 0;
        annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
        len = annotatePos;
        annotatePos = 0;
        annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
-
        spin_unlock(&annotate_lock);
 
        spin_unlock(&annotate_lock);
 
-       // Return number of 4-byte words
-       return len / 4;
+       return len;
 }
 }