gator: ARM DS-5.3 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_annotate.c
1 /**
2  * Copyright (C) ARM Limited 2010. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
10 #include <linux/slab.h>
11 #include <linux/fs.h>
12 #include <linux/mm.h>
13 #include <linux/sched.h>
14 #include <asm/uaccess.h>
15 #include <asm/current.h>
16 #include <linux/spinlock.h>
18 #define INSTSIZE        1024
19 static DEFINE_SPINLOCK(annotate_lock);
20 static char *annotateBuf;
21 static char *annotateBuf0;
22 static char *annotateBuf1;
23 static int annotatePos;
24 static int annotateSel;
26 static int gatorfs_copy_from_user(char* localbuf, char const __user *buf, size_t count)
27 {
28         if (count == 0)
29                 return 0;
31         if (copy_from_user(localbuf, buf, count))
32                 return -EFAULT;
34         return 0;
35 }
37 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
38 {
39         char tempBuffer[32];
40         unsigned long flags;
41         int retval, remaining, size;
43         if (*offset)
44                 return -EINVAL;
46         // determine size to capture
47         remaining = INSTSIZE - annotatePos - 24; // leave some extra space
48         size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
49         size = size < remaining ? size : remaining;
50         if (size <= 0)
51                 return 0;
53         // copy from user space
54         retval = gatorfs_copy_from_user(tempBuffer, buf, size);
55         if (retval == 0) {
56                 // synchronize shared variables annotateBuf and annotatePos
57                 spin_lock_irqsave(&annotate_lock, flags);
58                 if (!annotateBuf) {
59                         size = -EINVAL;
60                 } else  {
61                         *(int*)&annotateBuf[annotatePos + 0] = current->pid;            // thread id
62                         *(int*)&annotateBuf[annotatePos + 4] = size;                            // length in bytes
63                         memcpy(&annotateBuf[annotatePos + 8], tempBuffer, size);        // data
64                         annotatePos = annotatePos + 8 + size;                                           // increment position
65                         annotatePos = (annotatePos + 3) & ~3;                                           // align to 4-byte boundary
66                 }
67                 spin_unlock_irqrestore(&annotate_lock, flags);
69                 // return the number of bytes written
70                 retval = size;
71         }
73         return retval;
74 }
76 static const struct file_operations annotate_fops = {
77         .write          = annotate_write
78 };
80 int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
81 {
82         annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
83         return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
84 }
86 int gator_annotate_init(void)
87 {
88         return 0;
89 }
91 int gator_annotate_start(void)
92 {
93         annotatePos = annotateSel = 0;
94         annotateBuf0 = kmalloc(INSTSIZE, GFP_KERNEL);
95         annotateBuf1 = kmalloc(INSTSIZE, GFP_KERNEL);
96         annotateBuf = annotateBuf0;
97         if (!annotateBuf0 || !annotateBuf1)
98                 return -1;
99         return 0;
102 void gator_annotate_stop(void)
104         spin_lock(&annotate_lock);
106         kfree(annotateBuf0);
107         kfree(annotateBuf1);
108         annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
110         spin_unlock(&annotate_lock);
113 int gator_annotate_read(int **buffer)
115         int len;
117         if (smp_processor_id() || !annotatePos || !annotateBuf)
118                 return 0;
120         annotateSel = !annotateSel;
122         if (buffer)
123                 *buffer = (int *)annotateBuf;
125         spin_lock(&annotate_lock);
127         len = annotatePos;
128         annotatePos = 0;
129         annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
131         spin_unlock(&annotate_lock);
133         // Return number of 4-byte words
134         return len / 4;