d8d86afd10a717d59dfe8afce90123dfd96bda41
[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 ANNOTATE_SIZE   (16*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[512];
29         int retval, remaining, size;
31         if (*offset)
32                 return -EINVAL;
34         // determine size to capture
35         remaining = ANNOTATE_SIZE - annotatePos - 256; // pad for headers and release
36         size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
37         size = size < remaining ? size : remaining;
38         if (size <= 0) {
39                 wake_up(&gator_buffer_wait);
40                 return 0;
41         }
43         // copy from user space
44         retval = copy_from_user(tempBuffer, buf, size);
45         if (retval == 0) {
46                 // synchronize shared variables annotateBuf and annotatePos
47                 spin_lock(&annotate_lock);
48                 if (annotateBuf) {
49                         uint32_t tid = current->pid;
50                         uint32_t tick = gator_master_tick;
51                         uint64_t time = gator_get_time();
52                         uint32_t cpuid = smp_processor_id();
53                         int pos = annotatePos;
54                         pos += gator_write_packed_int(&annotateBuf[pos], tid);
55                         pos += gator_write_packed_int(&annotateBuf[pos], tick);
56                         pos += gator_write_packed_int(&annotateBuf[pos], time);
57                         pos += gator_write_packed_int(&annotateBuf[pos], time >> 32);
58                         pos += gator_write_packed_int(&annotateBuf[pos], cpuid);
59                         pos += gator_write_packed_int(&annotateBuf[pos], size);
60                         memcpy(&annotateBuf[pos], tempBuffer, size);
61                         annotatePos = pos + size;
62                 }
63                 spin_unlock(&annotate_lock);
65                 // return the number of bytes written
66                 retval = size;
67         } else {
68                 retval = -EINVAL;
69         }
71         return retval;
72 }
74 static int annotate_release(struct inode *inode, struct file *file)
75 {
76         int remaining = ANNOTATE_SIZE - annotatePos;
77         if (remaining < 16) {
78                 return -EFAULT;
79         }
81         spin_lock(&annotate_lock);
82         if (annotateBuf) {
83                 uint32_t tid = current->pid;
84                 uint32_t tick = gator_master_tick;
85                 int pos = annotatePos;
86                 pos += gator_write_packed_int(&annotateBuf[pos], tid);
87                 pos += gator_write_packed_int(&annotateBuf[pos], tick);
88                 pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
89                 pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
90                 pos += gator_write_packed_int(&annotateBuf[pos], 0); // cpuid
91                 pos += gator_write_packed_int(&annotateBuf[pos], 0); // size
92                 annotatePos = pos;
93         }
94         spin_unlock(&annotate_lock);
96         return 0;
97 }
99 static const struct file_operations annotate_fops = {
100         .write          = annotate_write,
101         .release        = annotate_release
102 };
104 static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
106         annotateBuf = NULL;
107         return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
110 static int gator_annotate_init(void)
112         annotateBuf0 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
113         annotateBuf1 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
114         if (!annotateBuf0 || !annotateBuf1)
115                 return -1;
116         return 0;
119 static int gator_annotate_start(void)
121         annotatePos = annotateSel = 0;
122         annotateBuf = annotateBuf0;
123         return 0;
126 static void gator_annotate_stop(void)
128         spin_lock(&annotate_lock);
129         annotateBuf = NULL;
130         spin_unlock(&annotate_lock);
133 static void gator_annotate_exit(void)
135         spin_lock(&annotate_lock);
136         kfree(annotateBuf0);
137         kfree(annotateBuf1);
138         annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
139         spin_unlock(&annotate_lock);
142 static int gator_annotate_ready(void)
144         return annotatePos && annotateBuf;
147 static int gator_annotate_read(char **buffer)
149         int len;
151         if (!gator_annotate_ready())
152                 return 0;
154         annotateSel = !annotateSel;
156         if (buffer)
157                 *buffer = annotateBuf;
159         spin_lock(&annotate_lock);
160         len = annotatePos;
161         annotatePos = 0;
162         annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
163         spin_unlock(&annotate_lock);
165         return len;