e096d1552e3140d5c0401e6a6d2e1e40b66149bb
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;
25 static bool collect_annotations = false;
27 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
28 {
29 char tempBuffer[512];
30 int retval, remaining, size;
32 if (*offset)
33 return -EINVAL;
35 // determine size to capture
36 remaining = ANNOTATE_SIZE - annotatePos - 256; // pad for headers and release
37 size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
38 size = size < remaining ? size : remaining;
39 if (size <= 0) {
40 wake_up(&gator_buffer_wait);
41 return 0;
42 }
44 // copy from user space
45 retval = copy_from_user(tempBuffer, buf, size);
46 if (retval == 0) {
47 // synchronize shared variables annotateBuf and annotatePos
48 spin_lock(&annotate_lock);
49 if (collect_annotations && annotateBuf) {
50 uint32_t tid = current->pid;
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_int64(&annotateBuf[pos], time);
56 pos += gator_write_packed_int(&annotateBuf[pos], cpuid);
57 pos += gator_write_packed_int(&annotateBuf[pos], size);
58 memcpy(&annotateBuf[pos], tempBuffer, size);
59 annotatePos = pos + size;
60 }
61 spin_unlock(&annotate_lock);
63 // return the number of bytes written
64 retval = size;
65 } else {
66 retval = -EINVAL;
67 }
69 return retval;
70 }
72 static int annotate_release(struct inode *inode, struct file *file)
73 {
74 int remaining = ANNOTATE_SIZE - annotatePos;
75 if (remaining < 16) {
76 return -EFAULT;
77 }
79 spin_lock(&annotate_lock);
80 if (annotateBuf) {
81 uint32_t tid = current->pid;
82 int pos = annotatePos;
83 pos += gator_write_packed_int(&annotateBuf[pos], tid);
84 pos += gator_write_packed_int64(&annotateBuf[pos], 0); // time
85 pos += gator_write_packed_int(&annotateBuf[pos], 0); // cpuid
86 pos += gator_write_packed_int(&annotateBuf[pos], 0); // size
87 annotatePos = pos;
88 }
89 spin_unlock(&annotate_lock);
91 return 0;
92 }
94 static const struct file_operations annotate_fops = {
95 .write = annotate_write,
96 .release = annotate_release
97 };
99 static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
100 {
101 annotateBuf = NULL;
102 return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
103 }
105 static int gator_annotate_init(void)
106 {
107 annotateBuf0 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
108 annotateBuf1 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
109 if (!annotateBuf0 || !annotateBuf1)
110 return -1;
111 return 0;
112 }
114 static int gator_annotate_start(void)
115 {
116 annotateSel = 0;
117 annotatePos = 1;
118 annotateBuf = annotateBuf0;
119 annotateBuf[0] = FRAME_ANNOTATE;
120 collect_annotations = true;
121 return 0;
122 }
124 static void gator_annotate_stop(void)
125 {
126 collect_annotations = false;
127 }
129 static void gator_annotate_shutdown(void)
130 {
131 spin_lock(&annotate_lock);
132 annotateBuf = NULL;
133 spin_unlock(&annotate_lock);
134 }
136 static void gator_annotate_exit(void)
137 {
138 spin_lock(&annotate_lock);
139 kfree(annotateBuf0);
140 kfree(annotateBuf1);
141 annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
142 spin_unlock(&annotate_lock);
143 }
145 static int gator_annotate_ready(void)
146 {
147 return annotatePos > 1 && annotateBuf;
148 }
150 static int gator_annotate_read(char **buffer)
151 {
152 int len;
154 if (!gator_annotate_ready())
155 return 0;
157 annotateSel = !annotateSel;
159 if (buffer)
160 *buffer = annotateBuf;
162 spin_lock(&annotate_lock);
163 len = annotatePos;
164 annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
165 annotateBuf[0] = FRAME_ANNOTATE;
166 annotatePos = 1;
167 spin_unlock(&annotate_lock);
169 return len;
170 }