]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - driver/gator_annotate.c
gator: Version 5.13
[android-sdk/arm-ds5-gator.git] / driver / gator_annotate.c
1 /**
2  * Copyright (C) ARM Limited 2010-2012. 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 static DEFINE_SPINLOCK(annotate_lock);
19 static bool collect_annotations = false;
21 static int annotate_copy(struct file *file, char const __user *buf, size_t count)
22 {
23         int cpu = 0;
24         int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF];
26         if (file == NULL) {
27                 // copy from kernel
28                 memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count);
29         } else {
30                 // copy from user space
31                 if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0)
32                         return -1;
33         }
34         per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF] = (write + count) & gator_buffer_mask[ANNOTATE_BUF];
36         return 0;
37 }
39 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
40 {
41         int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
43         if (*offset) {
44                 return -EINVAL;
45         }
47         // Annotations are not supported in interrupt context
48         if (in_interrupt()) {
49                 printk(KERN_WARNING "gator: Annotations are not supported in interrupt context\n");
50                 return -EINVAL;
51         }
53         // synchronize between cores and with collect_annotations
54         spin_lock(&annotate_lock);
56         if (!collect_annotations) {
57                 // Not collecting annotations, tell the caller everything was written
58                 size = count_orig;
59                 goto annotate_write_out;
60         }
62         // Annotation only uses a single per-cpu buffer as the data must be in order to the engine
63         cpu = 0;
65         if (current == NULL) {
66                 pid = 0;
67         } else {
68                 pid = current->pid;
69         }
71         // determine total size of the payload
72         header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
73         available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
74         size = count < available ? count : available;
76         if (size <= 0) {
77                 // Buffer is full but don't return an error.  Instead return 0 so the
78                 // caller knows nothing was written and they can try again.
79                 size = 0;
80                 goto annotate_write_out;
81         }
83         // synchronize shared variables annotateBuf and annotatePos
84         if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
85                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
86                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
87                 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, gator_get_time());
88                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
90                 // determine the sizes to capture, length1 + length2 will equal size
91                 contiguous = contiguous_space_available(cpu, ANNOTATE_BUF);
92                 if (size < contiguous) {
93                         length1 = size;
94                         length2 = 0;
95                 } else {
96                         length1 = contiguous;
97                         length2 = size - contiguous;
98                 }
100                 if (annotate_copy(file, buf, length1) != 0) {
101                         size = -EINVAL;
102                         goto annotate_write_out;
103                 }
105                 if (length2 > 0 && annotate_copy(file, &buf[length1], length2) != 0) {
106                         size = -EINVAL;
107                         goto annotate_write_out;
108                 }
110                 // Check and commit; commit is set to occur once buffer is 3/4 full
111                 buffer_check(cpu, ANNOTATE_BUF);
112         }
114 annotate_write_out:
115         spin_unlock(&annotate_lock);
117         // return the number of bytes written
118         return size;
121 #include "gator_annotate_kernel.c"
123 static int annotate_release(struct inode *inode, struct file *file)
125         int cpu = 0;
127         // synchronize between cores
128         spin_lock(&annotate_lock);
130         if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
131                 uint32_t pid = current->pid;
132                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, smp_processor_id());
133                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
134                 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0);  // time
135                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0);    // size
136         }
138         // Check and commit; commit is set to occur once buffer is 3/4 full
139         buffer_check(cpu, ANNOTATE_BUF);
141         spin_unlock(&annotate_lock);
143         return 0;
146 static const struct file_operations annotate_fops = {
147         .write = annotate_write,
148         .release = annotate_release
149 };
151 static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
153         return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
156 static int gator_annotate_start(void)
158         collect_annotations = true;
159         return 0;
162 static void gator_annotate_stop(void)
164         // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation
165         spin_lock(&annotate_lock);
166         collect_annotations = false;
167         spin_unlock(&annotate_lock);