gator: ARM DS-5.5 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_annotate.c
1 /**
2  * Copyright (C) ARM Limited 2010-2011. 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 ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
27 {
28         char tempBuffer[32];
29         unsigned long flags;
30         int retval, remaining, size;
32         if (*offset)
33                 return -EINVAL;
35         // determine size to capture
36         remaining = INSTSIZE - annotatePos - 24; // leave some extra space
37         size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
38         size = size < remaining ? size : remaining;
39         if (size <= 0)
40                 return 0;
42         // copy from user space
43         retval = copy_from_user(tempBuffer, buf, size);
44         if (retval == 0) {
45                 // synchronize shared variables annotateBuf and annotatePos
46                 spin_lock_irqsave(&annotate_lock, flags);
47                 if (!annotateBuf) {
48                         size = -EINVAL;
49                 } else  {
50                         *(int*)&annotateBuf[annotatePos + 0] = current->pid;            // thread id
51                         *(int*)&annotateBuf[annotatePos + 4] = size;                            // length in bytes
52                         memcpy(&annotateBuf[annotatePos + 8], tempBuffer, size);        // data
53                         annotatePos = annotatePos + 8 + size;                                           // increment position
54                         annotatePos = (annotatePos + 3) & ~3;                                           // align to 4-byte boundary
55                 }
56                 spin_unlock_irqrestore(&annotate_lock, flags);
58                 // return the number of bytes written
59                 retval = size;
60         } else {
61                 retval = -EINVAL;
62         }
64         return retval;
65 }
67 static const struct file_operations annotate_fops = {
68         .write          = annotate_write
69 };
71 int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
72 {
73         annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
74         return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
75 }
77 int gator_annotate_init(void)
78 {
79         return 0;
80 }
82 int gator_annotate_start(void)
83 {
84         annotatePos = annotateSel = 0;
85         annotateBuf0 = kmalloc(INSTSIZE, GFP_KERNEL);
86         annotateBuf1 = kmalloc(INSTSIZE, GFP_KERNEL);
87         annotateBuf = annotateBuf0;
88         if (!annotateBuf0 || !annotateBuf1)
89                 return -1;
90         return 0;
91 }
93 void gator_annotate_stop(void)
94 {
95         unsigned long flags;
96         spin_lock_irqsave(&annotate_lock, flags);
98         kfree(annotateBuf0);
99         kfree(annotateBuf1);
100         annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
102         spin_unlock_irqrestore(&annotate_lock, flags);
105 int gator_annotate_read(int **buffer)
107         int len;
109         if (smp_processor_id() || !annotatePos || !annotateBuf)
110                 return 0;
112         annotateSel = !annotateSel;
114         if (buffer)
115                 *buffer = (int *)annotateBuf;
117         spin_lock(&annotate_lock);
119         len = annotatePos;
120         annotatePos = 0;
121         annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
123         spin_unlock(&annotate_lock);
125         // Return number of 4-byte words
126         return len / 4;