Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Code drop from //branches/cupcake/...@124589

  • Loading branch information...
commit 7984f7ab3e13cda0c3b04ffeb2608f232e57f93a 1 parent 48ae5fc
authored December 17, 2008

Showing 58 changed files with 2,506 additions and 532 deletions. Show diff stats Hide diff stats

  1. 6  daemon/Android.mk
  2. 117  daemon/init.c
  3. 45  daemon/opd_anon.c
  4. 4  daemon/opd_anon.h
  5. 14  daemon/opd_cookie.c
  6. 5  daemon/opd_events.c
  7. 4  daemon/opd_events.h
  8. 25  daemon/opd_interface.h
  9. 41  daemon/opd_kernel.c
  10. 5  daemon/opd_kernel.h
  11. 13  daemon/opd_mangling.c
  12. 32  daemon/opd_perfmon.c
  13. 96  daemon/opd_pipe.c
  14. 45  daemon/opd_pipe.h
  15. 49  daemon/opd_sfile.c
  16. 9  daemon/opd_sfile.h
  17. 176  daemon/opd_spu.c
  18. 16  daemon/opd_stats.c
  19. 72  daemon/opd_trans.c
  20. 25  daemon/opd_trans.h
  21. 78  daemon/oprofiled.c
  22. 7  daemon/oprofiled.h
  23. 4  {libabic → libabi}/Android.mk
  24. 75  libabi/abi.cpp
  25. 42  libabi/abi.h
  26. 94  libabi/op_abi.c
  27. 13  {libabic → libabi}/op_abi.h
  28. 225  libabi/opimport.cpp
  29. 84  libabic/op_abi.cpp
  30. 14  libdb/db_debug.c
  31. 86  libdb/db_insert.c
  32. 104  libdb/db_manage.c
  33. 5  libdb/db_stat.c
  34. 52  libdb/odb.h
  35. 1  libop/Android.mk
  36. 50  libop/op_alloc_counter.c
  37. 77  libop/op_config.c
  38. 44  libop/op_config.h
  39. 30  libop/op_config_24.h
  40. 24  libop/op_cpu_type.c
  41. 23  libop/op_cpu_type.h
  42. 85  libop/op_events.c
  43. 16  libop/op_events.h
  44. 5  libop/op_get_interface.c
  45. 23  libop/op_mangle.c
  46. 1  libop/op_mangle.h
  47. 4  libop/op_sample_file.h
  48. 114  libutil/op_file.c
  49. 45  libutil/op_file.h
  50. 46  libutil/op_growable_buffer.c
  51. 45  libutil/op_growable_buffer.h
  52. 25  libutil/op_libiberty.c
  53. 9  libutil/op_libiberty.h
  54. 2  libutil/op_list.h
  55. 3  libutil/op_types.h
  56. 2  opcontrol/Android.mk
  57. 612  opcontrol/opcontrol.cpp
  58. 70  opimport_pull
6  daemon/Android.mk
@@ -9,20 +9,22 @@ LOCAL_SRC_FILES:= \
9 9
 	opd_kernel.c \
10 10
 	opd_mangling.c \
11 11
 	opd_perfmon.c \
  12
+	opd_pipe.c \
12 13
 	opd_sfile.c \
  14
+	opd_spu.c \
13 15
 	opd_stats.c \
14 16
 	opd_trans.c \
15 17
 	oprofiled.c
16 18
 
17 19
 LOCAL_STATIC_LIBRARIES := \
18  
-	libpopt libutil libdb libabic libop
  20
+	libpopt libutil libdb libabi libop
19 21
 
20 22
 LOCAL_C_INCLUDES := \
21 23
 	$(LOCAL_PATH)/.. \
22 24
 	$(LOCAL_PATH)/../libdb \
23 25
 	$(LOCAL_PATH)/../libutil \
24 26
 	$(LOCAL_PATH)/../libop \
25  
-	$(LOCAL_PATH)/../libabic
  27
+	$(LOCAL_PATH)/../libabi
26 28
 
27 29
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
28 30
 LOCAL_MODULE_TAGS := debug
117  daemon/init.c
@@ -7,6 +7,10 @@
7 7
  *
8 8
  * @author John Levon
9 9
  * @author Philippe Elie
  10
+ * @Modifications Daniel Hansel
  11
+ * Modified by Aravind Menon for Xen
  12
+ * These modifications are:
  13
+ * Copyright (C) 2005 Hewlett-Packard Co.
10 14
  */
11 15
 
12 16
 #include "config.h"
@@ -14,6 +18,7 @@
14 18
 #include "oprofiled.h"
15 19
 #include "opd_stats.h"
16 20
 #include "opd_sfile.h"
  21
+#include "opd_pipe.h"
17 22
 #include "opd_kernel.h"
18 23
 #include "opd_trans.h"
19 24
 #include "opd_anon.h"
@@ -30,17 +35,30 @@
30 35
 #include <fcntl.h>
31 36
 #include <stdio.h>
32 37
 #include <errno.h>
  38
+#include <limits.h>
33 39
 #include <stdlib.h>
  40
+#include <sys/time.h>
  41
+#if ANDROID
  42
+#include <sys/wait.h>
  43
+#else
  44
+#include <wait.h>
  45
+#endif
  46
+#include <string.h>
34 47
 
35 48
 size_t kernel_pointer_size;
36 49
 
37 50
 static fd_t devfd;
38 51
 static char * sbuf;
39 52
 static size_t s_buf_bytesize;
  53
+extern char * session_dir;
  54
+static char start_time_str[32];
  55
+static int jit_conversion_running;
40 56
 
41 57
 static void opd_sighup(void);
42 58
 static void opd_alarm(void);
43 59
 static void opd_sigterm(void);
  60
+static void opd_sigchild(void);
  61
+static void opd_do_jitdumps(void);
44 62
 
45 63
 /**
46 64
  * opd_open_files - open necessary files
@@ -50,7 +68,7 @@ static void opd_sigterm(void);
50 68
  */
51 69
 static void opd_open_files(void)
52 70
 {
53  
-	devfd = op_open_device(OP_DRIVER_BASE"/buffer");
  71
+	devfd = op_open_device("/dev/oprofile/buffer");
54 72
 	if (devfd == -1) {
55 73
 		if (errno == EINVAL)
56 74
 			fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n"
@@ -61,7 +79,7 @@ static void opd_open_files(void)
61 79
 	}
62 80
 
63 81
 	/* give output before re-opening stdout as the logfile */
64  
-	printf("Using log file " OP_LOG_FILE "\n");
  82
+	printf("Using log file %s\n", op_log_file);
65 83
 
66 84
 	/* set up logfile */
67 85
 	close(0);
@@ -73,6 +91,7 @@ static void opd_open_files(void)
73 91
 	}
74 92
 
75 93
 	opd_open_logfile();
  94
+	opd_create_pipe();
76 95
 
77 96
 	printf("oprofiled started %s", op_get_time());
78 97
 	printf("kernel pointer size: %lu\n",
@@ -87,12 +106,12 @@ static void complete_dump(void)
87 106
 	FILE * status_file;
88 107
 
89 108
 retry:
90  
-	status_file = fopen(OP_DUMP_STATUS, "w");
  109
+	status_file = fopen(op_dump_status, "w");
91 110
 
92 111
 	if (!status_file && errno == EMFILE) {
93 112
 		if (sfile_lru_clear()) {
94 113
 			printf("LRU cleared but file open fails for %s.\n",
95  
-			       OP_DUMP_STATUS);
  114
+			       op_dump_status);
96 115
 			abort();
97 116
 		}
98 117
 		goto retry;
@@ -130,6 +149,48 @@ static void opd_do_samples(char const * opd_buf, ssize_t count)
130 149
 	complete_dump();
131 150
 }
132 151
  
  152
+static void opd_do_jitdumps(void)
  153
+{ 
  154
+	pid_t childpid;
  155
+	int arg_num;
  156
+	unsigned long long end_time = 0ULL;
  157
+	struct timeval tv;
  158
+	char end_time_str[32];
  159
+	char opjitconv_path[PATH_MAX + 1];
  160
+	char * exec_args[6];
  161
+
  162
+	if (jit_conversion_running)
  163
+		return;
  164
+	jit_conversion_running = 1;
  165
+
  166
+	childpid = fork();
  167
+	switch (childpid) {
  168
+		case -1:
  169
+			perror("Error forking JIT dump process!");
  170
+			break;
  171
+		case 0:
  172
+			gettimeofday(&tv, NULL);
  173
+			end_time = tv.tv_sec;
  174
+			sprintf(end_time_str, "%llu", end_time);
  175
+			sprintf(opjitconv_path, "%s/%s", OP_BINDIR, "opjitconv");
  176
+			arg_num = 0;
  177
+			exec_args[arg_num++] = opjitconv_path;
  178
+			if (vmisc)
  179
+				exec_args[arg_num++] = "-d";
  180
+			exec_args[arg_num++] = session_dir;
  181
+			exec_args[arg_num++] = start_time_str;
  182
+			exec_args[arg_num++] = end_time_str;
  183
+			exec_args[arg_num] = (char *) NULL;
  184
+			execvp("opjitconv", exec_args);
  185
+			fprintf(stderr, "Failed to exec %s: %s\n",
  186
+			        exec_args[0], strerror(errno));
  187
+			/* We don't want any cleanup in the child */
  188
+			_exit(EXIT_FAILURE);
  189
+		default:
  190
+			break;
  191
+	} 
  192
+
  193
+} 
133 194
 
134 195
 /**
135 196
  * opd_do_read - enter processing loop
@@ -141,6 +202,8 @@ static void opd_do_samples(char const * opd_buf, ssize_t count)
141 202
  */
142 203
 static void opd_do_read(char * buf, size_t size)
143 204
 {
  205
+	opd_open_pipe();
  206
+
144 207
 	while (1) {
145 208
 		ssize_t count = -1;
146 209
 
@@ -164,6 +227,9 @@ static void opd_do_read(char * buf, size_t size)
164 227
 			if (signal_term)
165 228
 				opd_sigterm();
166 229
 
  230
+			if (signal_child)
  231
+				opd_sigchild();
  232
+
167 233
 			if (signal_usr1) {
168 234
 				signal_usr1 = 0;
169 235
 				perfmon_start();
@@ -173,10 +239,17 @@ static void opd_do_read(char * buf, size_t size)
173 239
 				signal_usr2 = 0;
174 240
 				perfmon_stop();
175 241
 			}
  242
+
  243
+			if (is_jitconv_requested()) {
  244
+				verbprintf(vmisc, "Start opjitconv was triggered\n");
  245
+				opd_do_jitdumps();
  246
+			}
176 247
 		}
177 248
 
178 249
 		opd_do_samples(buf, count);
179 250
 	}
  251
+	
  252
+	opd_close_pipe();
180 253
 }
181 254
 
182 255
 
@@ -204,27 +277,45 @@ static void opd_sighup(void)
204 277
 static void clean_exit(void)
205 278
 {
206 279
 	perfmon_exit();
207  
-	unlink(OP_LOCK_FILE);
  280
+	unlink(op_lock_file);
208 281
 }
209 282
 
210 283
 
211 284
 static void opd_sigterm(void)
212 285
 {
  286
+	opd_do_jitdumps();
213 287
 	opd_print_stats();
214 288
 	printf("oprofiled stopped %s", op_get_time());
215 289
 	exit(EXIT_FAILURE);
216 290
 }
217  
- 
218 291
 
  292
+/* SIGCHLD received from JIT dump child process. */
  293
+static void opd_sigchild(void)
  294
+{
  295
+	int child_status;
  296
+	wait(&child_status);
  297
+	jit_conversion_running = 0;
  298
+	if (WIFEXITED(child_status) && (!WEXITSTATUS(child_status))) {
  299
+		verbprintf(vmisc, "JIT dump processing complete.\n");
  300
+	} else {
  301
+		printf("JIT dump processing exited abnormally: %d\n",
  302
+		       WEXITSTATUS(child_status));
  303
+	}
  304
+
  305
+}
  306
+ 
219 307
 static void opd_26_init(void)
220 308
 {
221 309
 	size_t i;
222 310
 	size_t opd_buf_size;
  311
+	unsigned long long start_time = 0ULL;
  312
+	struct timeval tv;
223 313
 
224 314
 	opd_create_vmlinux(vmlinux, kernel_range);
  315
+	opd_create_xen(xenimage, xen_range);
225 316
 
226  
-	opd_buf_size = opd_read_fs_int(OP_DRIVER_BASE"/", "buffer_size", 1);
227  
-	kernel_pointer_size = opd_read_fs_int(OP_DRIVER_BASE"/", "pointer_size", 1);
  317
+	opd_buf_size = opd_read_fs_int("/dev/oprofile/", "buffer_size", 1);
  318
+	kernel_pointer_size = opd_read_fs_int("/dev/oprofile/", "pointer_size", 1);
228 319
 
229 320
 	s_buf_bytesize = opd_buf_size * kernel_pointer_size;
230 321
 
@@ -247,13 +338,19 @@ static void opd_26_init(void)
247 338
 		perror("oprofiled: couldn't set exit cleanup: ");
248 339
 		exit(EXIT_FAILURE);
249 340
 	}
  341
+
  342
+	/* trigger kernel module setup before returning control to opcontrol */
  343
+	opd_open_files();
  344
+	gettimeofday(&tv, NULL);
  345
+	start_time = 0ULL;
  346
+	start_time = tv.tv_sec;
  347
+	sprintf(start_time_str, "%llu", start_time);
  348
+		  
250 349
 }
251 350
 
252 351
 
253 352
 static void opd_26_start(void)
254 353
 {
255  
-	opd_open_files();
256  
-
257 354
 	/* simple sleep-then-process loop */
258 355
 	opd_do_read(sbuf, s_buf_bytesize);
259 356
 }
45  daemon/opd_anon.c
@@ -14,6 +14,7 @@
14 14
  * @remark Read the file COPYING
15 15
  *
16 16
  * @author John Levon
  17
+ * @Modifications Gisle Dankel
17 18
  */
18 19
 
19 20
 #include "opd_anon.h"
@@ -25,21 +26,24 @@
25 26
 #include <limits.h>
26 27
 #include <stdlib.h>
27 28
 #include <stdio.h>
  29
+#include <string.h>
28 30
 
29 31
 #define HASH_SIZE 1024
30 32
 #define HASH_BITS (HASH_SIZE - 1)
31 33
 
32  
-#define LRU_SIZE 1000
33  
-#define LRU_AMOUNT (LRU_SIZE/5)
  34
+/*
  35
+ * Note that this value is tempered by the fact that when we miss in the
  36
+ * anon cache, we'll tear down all the mappings for that tgid. Thus, LRU
  37
+ * of a mapping can potentially clear out a much larger number of
  38
+ * mappings.
  39
+ */
  40
+#define LRU_SIZE 8192
  41
+#define LRU_AMOUNT (LRU_SIZE/8)
34 42
 
35 43
 static struct list_head hashes[HASH_SIZE];
36 44
 static struct list_head lru;
37 45
 static size_t nr_lru;
38 46
 
39  
-/* never called in buffer-processing context, so we don't need
40  
- * to update struct transient. Note the 'U' of LRU is based on
41  
- * parsing time, not actual use.
42  
- */
43 47
 static void do_lru(struct transient * trans)
44 48
 {
45 49
 	size_t nr_to_kill = LRU_AMOUNT;
@@ -53,6 +57,7 @@ static void do_lru(struct transient * trans)
53 57
 			clear_trans_current(trans);
54 58
 		if (trans->last_anon == entry)
55 59
 			clear_trans_last(trans);
  60
+		sfile_clear_anon(entry);
56 61
 		list_del(&entry->list);
57 62
 		list_del(&entry->lru_list);
58 63
 		--nr_lru;
@@ -60,8 +65,6 @@ static void do_lru(struct transient * trans)
60 65
 		if (nr_to_kill-- == 0)
61 66
 			break;
62 67
 	}
63  
-
64  
-	sfile_clear_anon();
65 68
 }
66 69
 
67 70
 
@@ -87,6 +90,7 @@ static void clear_anon_maps(struct transient * trans)
87 90
 		if (entry->tgid == tgid && entry->app_cookie == app) {
88 91
 			if (trans->last_anon == entry)
89 92
 				clear_trans_last(trans);
  93
+			sfile_clear_anon(entry);
90 94
 			list_del(&entry->list);
91 95
 			list_del(&entry->lru_list);
92 96
 			--nr_lru;
@@ -94,7 +98,6 @@ static void clear_anon_maps(struct transient * trans)
94 98
 		}
95 99
 	}
96 100
 
97  
-	sfile_clear_anon();
98 101
 	if (vmisc) {
99 102
 		char const * name = verbose_cookie(app);
100 103
 		printf("Cleared anon maps for tgid %u (%s).\n", tgid, name);
@@ -103,7 +106,7 @@ static void clear_anon_maps(struct transient * trans)
103 106
 
104 107
 
105 108
 static void
106  
-add_anon_mapping(struct transient * trans, vma_t start, vma_t end)
  109
+add_anon_mapping(struct transient * trans, vma_t start, vma_t end, char * name)
107 110
 {
108 111
 	unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
109 112
 	struct anon_mapping * m = xmalloc(sizeof(struct anon_mapping));
@@ -111,6 +114,7 @@ add_anon_mapping(struct transient * trans, vma_t start, vma_t end)
111 114
 	m->app_cookie = trans->app_cookie;
112 115
 	m->start = start;
113 116
 	m->end = end;
  117
+	strncpy(m->name, name, MAX_IMAGE_NAME_SIZE + 1);
114 118
 	list_add_tail(&m->list, &hashes[hash]);
115 119
 	list_add_tail(&m->lru_list, &lru);
116 120
 	if (++nr_lru == LRU_SIZE)
@@ -128,8 +132,7 @@ static void get_anon_maps(struct transient * trans)
128 132
 {
129 133
 	FILE * fp = NULL;
130 134
 	char buf[PATH_MAX];
131  
-	unsigned long start;
132  
-	unsigned long end;
  135
+	vma_t start, end;
133 136
 	int ret;
134 137
 
135 138
 	snprintf(buf, PATH_MAX, "/proc/%d/maps", trans->tgid);
@@ -138,16 +141,20 @@ static void get_anon_maps(struct transient * trans)
138 141
 		return;
139 142
 
140 143
 	while (fgets(buf, PATH_MAX, fp) != NULL) {
141  
-		char tmp[20];
142  
-		/* Note that this actually includes all mappings,
143  
-		 * since we want stuff like [heap]
  144
+		char tmp[MAX_IMAGE_NAME_SIZE + 1];
  145
+		char name[MAX_IMAGE_NAME_SIZE + 1];
  146
+		/* Some anon maps have labels like
  147
+		 * [heap], [stack], [vdso], [vsyscall] ...
  148
+		 * Keep track of these labels. If a map has no name, call it "anon".
  149
+		 * Ignore all mappings starting with "/" (file or shared memory object)
144 150
 		 */
145  
-		ret = sscanf(buf, "%lx-%lx %19s %19s %19s %19s %19s",
146  
-		             &start, &end, tmp, tmp, tmp, tmp, tmp);
147  
-		if (ret < 6)
  151
+		strcpy(name, "anon");
  152
+		ret = sscanf(buf, "%llx-%llx %20s %20s %20s %20s %20s",
  153
+		             &start, &end, tmp, tmp, tmp, tmp, name);
  154
+		if (ret < 6 || name[0] == '/')
148 155
 			continue;
149 156
 
150  
-		add_anon_mapping(trans, start, end);
  157
+		add_anon_mapping(trans, start, end, name);
151 158
 	}
152 159
 
153 160
 	fclose(fp);
4  daemon/opd_anon.h
@@ -25,6 +25,9 @@ struct transient;
25 25
  */
26 26
 #define VMA_SHIFT 13 
27 27
 
  28
+/* Maximum size of the image name considered */
  29
+#define MAX_IMAGE_NAME_SIZE 20
  30
+
28 31
 struct anon_mapping {
29 32
 	/** start of the mapping */
30 33
 	vma_t start;
@@ -38,6 +41,7 @@ struct anon_mapping {
38 41
 	struct list_head list;
39 42
 	/** lru list */
40 43
 	struct list_head lru_list;
  44
+	char name[MAX_IMAGE_NAME_SIZE+1];
41 45
 };
42 46
 
43 47
 /**
14  daemon/opd_cookie.c
@@ -60,12 +60,24 @@
5  daemon/opd_events.c
@@ -142,7 +142,8 @@ struct opd_event * find_counter_event(unsigned long counter)
142 142
 
143 143
 void fill_header(struct opd_header * header, unsigned long counter,
144 144
                  vma_t anon_start, vma_t cg_to_anon_start,
145  
-                 int is_kernel, int cg_to_is_kernel, time_t mtime)
  145
+                 int is_kernel, int cg_to_is_kernel,
  146
+                 int spu_samples, uint64_t embed_offset, time_t mtime)
146 147
 {
147 148
 	struct opd_event * event = find_counter_event(counter);
148 149
 
@@ -158,5 +159,7 @@ void fill_header(struct opd_header * header, unsigned long counter,
158 159
 	header->cpu_speed = cpu_speed;
159 160
 	header->mtime = mtime;
160 161
 	header->anon_start = anon_start;
  162
+	header->spu_profile = spu_samples;
  163
+	header->embedded_offset = embed_offset;
161 164
 	header->cg_to_anon_start = cg_to_anon_start;
162 165
 }
4  daemon/opd_events.h
@@ -13,6 +13,7 @@
13 13
 
14 14
 #include "op_types.h"
15 15
 
  16
+#include <stdint.h>
16 17
 #include <time.h>
17 18
 
18 19
 /** event description for setup (perfmon) and mangling */
@@ -40,6 +41,7 @@ struct opd_header;
40 41
 /** fill the sample file header with event info etc. */
41 42
 void fill_header(struct opd_header * header, unsigned long counter,
42 43
                  vma_t anon_start, vma_t anon_end,
43  
-                 int is_kernel, int cg_to_is_kernel, time_t mtime);
  44
+                 int is_kernel, int cg_to_is_kernel,
  45
+                 int spu_samples, uint64_t embed_offset, time_t mtime);
44 46
 
45 47
 #endif /* OPD_EVENTS_H */
25  daemon/opd_interface.h
@@ -8,6 +8,9 @@
8 8
  *
9 9
  * @author John Levon
10 10
  * @author Philippe Elie
  11
+ * Modified by Aravind Menon for Xen
  12
+ * These modifications are:
  13
+ * Copyright (C) 2005 Hewlett-Packard Co.
11 14
  */
12 15
 
13 16
 #ifndef OPD_INTERFACE_H
@@ -17,10 +20,26 @@
17 20
 #define CPU_SWITCH_CODE			2
18 21
 #define COOKIE_SWITCH_CODE		3
19 22
 #define KERNEL_ENTER_SWITCH_CODE	4
20  
-#define KERNEL_EXIT_SWITCH_CODE		5
21  
-#define MODULE_LOADED_CODE              6
  23
+#define USER_ENTER_SWITCH_CODE		5
  24
+#define MODULE_LOADED_CODE		6
22 25
 #define CTX_TGID_CODE			7
23 26
 #define TRACE_BEGIN_CODE		8
24  
-#define LAST_CODE			9
  27
+/* Code 9 used to be TRACE_END_CODE which is not used anymore  */
  28
+/* Code 9 is now considered an unknown escape code             */
  29
+#define XEN_ENTER_SWITCH_CODE		10
  30
+/*
  31
+ * Ugly work-around for the unfortunate collision between Xenoprof's
  32
+ * DOMAIN_SWITCH_CODE (in use on x86) and Cell's SPU_PROFILING_CODE
  33
+ * (in use with Power):
  34
+ */
  35
+#if defined(__powerpc__)
  36
+#define SPU_PROFILING_CODE		11
  37
+#define SPU_CTX_SWITCH_CODE		12
  38
+#define DOMAIN_SWITCH_CODE		13
  39
+#define LAST_CODE			14
  40
+#else
  41
+#define DOMAIN_SWITCH_CODE		11
  42
+#define LAST_CODE			12
  43
+#endif
25 44
  
26 45
 #endif /* OPD_INTERFACE_H */
41  daemon/opd_kernel.c
@@ -7,6 +7,9 @@
7 7
  *
8 8
  * @author John Levon
9 9
  * @author Philippe Elie
  10
+ * Modified by Aravind Menon for Xen
  11
+ * These modifications are:
  12
+ * Copyright (C) 2005 Hewlett-Packard Co.
10 13
  */
11 14
 
12 15
 #include "opd_kernel.h"
@@ -29,6 +32,8 @@ static LIST_HEAD(modules);
29 32
 
30 33
 static struct kernel_image vmlinux_image;
31 34
 
  35
+static struct kernel_image xen_image;
  36
+
32 37
 void opd_create_vmlinux(char const * name, char const * arg)
33 38
 {
34 39
 	/* vmlinux is *not* on the list of modules */
@@ -54,6 +59,31 @@ void opd_create_vmlinux(char const * name, char const * arg)
54 59
 	}
55 60
 }
56 61
 
  62
+void opd_create_xen(char const * name, char const * arg)
  63
+{
  64
+	/* xen is *not* on the list of modules */
  65
+	list_init(&xen_image.list);
  66
+
  67
+	/* for no xen */
  68
+	if (no_xen) {
  69
+		xen_image.name = "no-xen";
  70
+		return;
  71
+	}
  72
+
  73
+	xen_image.name = xstrdup(name);
  74
+
  75
+	sscanf(arg, "%llx,%llx", &xen_image.start, &xen_image.end);
  76
+
  77
+	verbprintf(vmisc, "xen_start = %llx, xen_end = %llx\n",
  78
+	           xen_image.start, xen_image.end);
  79
+
  80
+	if (!xen_image.start && !xen_image.end) {
  81
+		fprintf(stderr, "error: mis-parsed xen range: %llx-%llx\n",
  82
+		        xen_image.start, xen_image.end);
  83
+		exit(EXIT_FAILURE);
  84
+	}
  85
+}
  86
+
57 87
 
58 88
 /**
59 89
  * Allocate and initialise a kernel image description
@@ -112,11 +142,11 @@ void opd_reread_module_info(void)
112 142
 	char * line;
113 143
 	struct kernel_image * image;
114 144
 	int module_size;
115  
-	char ref_count[32];
  145
+	char ref_count[32+1];
116 146
 	int ret;
117 147
 	char module_name[256+1];
118  
-	char live_info[32];
119  
-	char dependencies[4096];
  148
+	char live_info[32+1];
  149
+	char dependencies[4096+1];
120 150
 	unsigned long long start_address;
121 151
 
122 152
 	if (no_vmlinux)
@@ -145,7 +175,7 @@ void opd_reread_module_info(void)
145 175
 			continue;
146 176
 		}
147 177
 
148  
-		ret = sscanf(line, "%256s %u %31s %4095s %31s %llx",
  178
+		ret = sscanf(line, "%256s %u %32s %4096s %32s %llx",
149 179
 			     module_name, &module_size, ref_count,
150 180
 			     dependencies, live_info, &start_address);
151 181
 		if (ret != 6) {
@@ -192,5 +222,8 @@ struct kernel_image * find_kernel_image(struct transient const * trans)
192 222
 			return image;
193 223
 	}
194 224
 
  225
+	if (xen_image.start <= trans->pc && xen_image.end > trans->pc)
  226
+		return &xen_image;
  227
+
195 228
 	return NULL;
196 229
 }
5  daemon/opd_kernel.h
@@ -7,6 +7,9 @@
7 7
  *
8 8
  * @author John Levon
9 9
  * @author Philippe Elie
  10
+ * Modified by Aravind Menon for Xen
  11
+ * These modifications are:
  12
+ * Copyright (C) 2005 Hewlett-Packard Co.
10 13
  */
11 14
 
12 15
 #ifndef OPD_KERNEL_H
@@ -20,6 +23,8 @@ struct transient;
20 23
 /** create the kernel image */
21 24
 void opd_create_vmlinux(char const * name, char const * arg);
22 25
 
  26
+void opd_create_xen(char const * name, char const * arg);
  27
+
23 28
 /** opd_reread_module_info - parse /proc/modules for kernel modules */
24 29
 void opd_reread_module_info(void);
25 30
 
13  daemon/opd_mangling.c
@@ -57,8 +57,10 @@ static char const * get_dep_name(struct sfile const * sf)
57 57
 static char * mangle_anon(struct anon_mapping const * anon)
58 58
 {
59 59
 	char * name = xmalloc(PATH_MAX);
  60
+
60 61
 	snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid,
61  
-	         anon->start, anon->end);
  62
+	       anon->start, anon->end);
  63
+
62 64
 	return name;
63 65
 }
64 66
 
@@ -78,6 +80,7 @@ mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int c
78 80
 	} else if (sf->anon) {
79 81
 		values.flags |= MANGLE_ANON;
80 82
 		values.image_name = mangle_anon(sf->anon);
  83
+		values.anon_name = sf->anon->name;
81 84
 	} else {
82 85
 		values.image_name = find_cookie(sf->cookie);
83 86
 	}
@@ -108,6 +111,7 @@ mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int c
108 111
 		} else if (last->anon) {
109 112
 			values.flags |= MANGLE_CG_ANON;
110 113
 			values.cg_image_name = mangle_anon(last->anon);
  114
+			values.anon_name = last->anon->name;
111 115
 		} else {
112 116
 			values.cg_image_name = find_cookie(last->cookie);
113 117
 		}
@@ -139,6 +143,7 @@ int opd_open_sample_file(odb_t * file, struct sfile * last,
139 143
 {
140 144
 	char * mangled;
141 145
 	char const * binary;
  146
+	int spu_profile = 0;
142 147
 	vma_t last_start = 0;
143 148
 	int err;
144 149
 
@@ -182,10 +187,14 @@ int opd_open_sample_file(odb_t * file, struct sfile * last,
182 187
 	if (last && last->anon)
183 188
 		last_start = last->anon->start;
184 189
 
  190
+	if (sf->embedded_offset != UNUSED_EMBEDDED_OFFSET)
  191
+		spu_profile = 1;
  192
+
185 193
 	fill_header(odb_get_data(file), counter,
186 194
 		    sf->anon ? sf->anon->start : 0, last_start,
187 195
 		    !!sf->kernel, last ? !!last->kernel : 0,
188  
-	            binary ? op_get_mtime(binary) : 0);
  196
+		    spu_profile, sf->embedded_offset,
  197
+		    binary ? op_get_mtime(binary) : 0);
189 198
 
190 199
 out:
191 200
 	sfile_put(sf);
32  daemon/opd_perfmon.c
@@ -380,6 +380,7 @@ static void wait_for_child(struct child * child)
380 380
 	close(child->up_pipe[1]);
381 381
 }
382 382
 
  383
+static struct child* xen_ctx;
383 384
 
384 385
 void perfmon_init(void)
385 386
 {
@@ -389,6 +390,24 @@ void perfmon_init(void)
389 390
 	if (cpu_type == CPU_TIMER_INT)
390 391
 		return;
391 392
 
  393
+	if (!no_xen) {
  394
+		xen_ctx = xmalloc(sizeof(struct child));
  395
+		xen_ctx->pid = getpid();
  396
+		xen_ctx->up_pipe[0] = -1;
  397
+		xen_ctx->up_pipe[1] = -1;
  398
+		xen_ctx->sigusr1 = 0;
  399
+		xen_ctx->sigusr2 = 0;
  400
+		xen_ctx->sigterm = 0;
  401
+
  402
+		create_context(xen_ctx);
  403
+
  404
+		write_pmu(xen_ctx);
  405
+		
  406
+		load_context(xen_ctx);
  407
+		return;
  408
+	}
  409
+	
  410
+
392 411
 	nr = sysconf(_SC_NPROCESSORS_ONLN);
393 412
 	if (nr == -1) {
394 413
 		fprintf(stderr, "Couldn't determine number of CPUs.\n");
@@ -431,6 +450,9 @@ void perfmon_exit(void)
431 450
 	if (cpu_type == CPU_TIMER_INT)
432 451
 		return;
433 452
 
  453
+	if (!no_xen)
  454
+		return;
  455
+
434 456
 	for (i = 0; i < nr_cpus; ++i) {
435 457
 		kill(children[i].pid, SIGKILL);
436 458
 		waitpid(children[i].pid, NULL, 0);
@@ -445,6 +467,11 @@ void perfmon_start(void)
445 467
 	if (cpu_type == CPU_TIMER_INT)
446 468
 		return;
447 469
 
  470
+	if (!no_xen) {
  471
+		perfmon_start_child(xen_ctx->ctx_fd);
  472
+		return;
  473
+	}
  474
+
448 475
 	for (i = 0; i < nr_cpus; ++i)
449 476
 		kill(children[i].pid, SIGUSR1);
450 477
 }
@@ -457,6 +484,11 @@ void perfmon_stop(void)
457 484
 	if (cpu_type == CPU_TIMER_INT)
458 485
 		return;
459 486
 
  487
+	if (!no_xen) {
  488
+		perfmon_stop_child(xen_ctx->ctx_fd);
  489
+		return;
  490
+	}
  491
+	
460 492
 	for (i = 0; i < nr_cpus; ++i)
461 493
 		kill(children[i].pid, SIGUSR2);
462 494
 }
96  daemon/opd_pipe.c
... ...
@@ -0,0 +1,96 @@
  1
+/**
  2
+ * @file daemon/opd_pipe.c
  3
+ * Functions handling the $SESSIONDIR/opd_pipe FIFO special file.
  4
+ * NOTE: This code is dealing with potentially insecure input.
  5
+ *
  6
+ * @remark Copyright 2008 OProfile authors
  7
+ * @remark Read the file COPYING
  8
+ *
  9
+ * @author Daniel Hansel
  10
+ */
  11
+
  12
+#include "opd_pipe.h"
  13
+#include "opd_printf.h"
  14
+#include "op_config.h"
  15
+
  16
+#include <stdio.h>
  17
+#include <stdlib.h>
  18
+#include <string.h>
  19
+#include <fcntl.h>
  20
+#include <unistd.h>
  21
+#include <errno.h>
  22
+#include <sys/stat.h>
  23
+
  24
+static int fifo;
  25
+
  26
+void opd_create_pipe(void)
  27
+{
  28
+	mode_t orig_umask = umask(0111);
  29
+	if (mkfifo(op_pipe_file, 0666) == -1) {
  30
+		if (errno != EEXIST) {
  31
+			perror("oprofiled: couldn't create pipe: ");
  32
+			exit(EXIT_FAILURE);
  33
+		}
  34
+	}
  35
+	umask(orig_umask);
  36
+}
  37
+
  38
+
  39
+void opd_open_pipe(void)
  40
+{
  41
+	fifo = open(op_pipe_file, O_RDONLY | O_NONBLOCK);
  42
+	if (fifo == -1) {
  43
+		perror("oprofiled: couldn't open pipe: ");
  44
+		exit(EXIT_FAILURE);
  45
+	}
  46
+}
  47
+
  48
+
  49
+void opd_close_pipe(void)
  50
+{
  51
+	close(fifo);
  52
+}
  53
+
  54
+
  55
+int is_jitconv_requested(void)
  56
+{
  57
+	/* number of dropped (unknown) requests */
  58
+	static long nr_drops = 0;
  59
+	/* modulus to output only a few warnings to avoid flooding oprofiled.log */
  60
+	static int mod_cnt_drops = 1;
  61
+	FILE * fd;
  62
+	char line[256];
  63
+	int i, ret = 0;
  64
+
  65
+	/* get a file descriptor to the pipe */
  66
+	fd = fdopen(fifo, "r");
  67
+
  68
+	if (fd == NULL) {
  69
+		perror("oprofiled: couldn't create file descriptor: ");
  70
+		exit(EXIT_FAILURE);
  71
+	}
  72
+
  73
+	/* read up to 99 lines to check for 'do_jitconv' */
  74
+	for (i = 0; i < 99; i++) {
  75
+		/* just break if no new line is found */
  76
+		if (fgets(line, 256, fd) == NULL)
  77
+			break;
  78
+		line[strlen(line) - 1] = '\0';
  79
+
  80
+		if (strstr(line, "do_jitconv") != NULL) {
  81
+			ret = 1;
  82
+		} else {
  83
+			nr_drops++;
  84
+
  85
+			if (nr_drops % mod_cnt_drops == 0) {
  86
+				printf(
  87
+				       "Warning: invalid pipe request received (dropped request(s): %ld)\n",
  88
+				       nr_drops);
  89
+				/* increase modulus to avoid flooding log file */
  90
+				mod_cnt_drops *= 5;
  91
+			}
  92
+		}
  93
+	}
  94
+
  95
+	return ret;
  96
+}
45  daemon/opd_pipe.h
... ...
@@ -0,0 +1,45 @@
  1
+/**
  2
+ * @file daemon/opd_pipe.h
  3
+ * Functions handling the $SESSIONDIR/opd_pipe FIFO special file.
  4
+ * NOTE: This code is dealing with potencially insecure input.
  5
+ *
  6
+ * @remark Copyright 2008 OProfile authors
  7
+ * @remark Read the file COPYING
  8
+ *
  9
+ * @author Daniel Hansel
  10
+ */
  11
+
  12
+#ifndef OPD_PIPE_H_
  13
+#define OPD_PIPE_H_
  14
+ 
  15
+/**
  16
+ * opd_create_pipe - creates the oprofiled fifo file
  17
+ *
  18
+ * Creates the Oprofile daemon fifo pipe to enable communication between
  19
+ * the daemon and the 'opcontrol --dump' command. Failure to create the pipe
  20
+ * is a fatal error.
  21
+ */
  22
+void opd_create_pipe(void);
  23
+
  24
+/**
  25
+ * opd_open_pipe - opens the oprofiled fifo file
  26
+ */
  27
+void opd_open_pipe(void);
  28
+
  29
+/**
  30
+ * opd_close_pipe - closes the oprofiled fifo file
  31
+ *
  32
+ * Closes the Oprofile daemon fifo pipe.
  33
+ */
  34
+void opd_close_pipe(void);
  35
+
  36
+/**
  37
+ * is_jitconv_requested - check for request to jit conversion
  38
+ *
  39
+ * Checks the Oprofile daemon fifo pipe for do_jitconv request.
  40
+ * If jit conversion is requested ('do_jitconv' is sent) the check returns 1.
  41
+ * Otherwise it returns 0.
  42
+ */
  43
+int is_jitconv_requested(void);
  44
+
  45
+#endif /*OPD_PIPE_H_*/
49  daemon/opd_sfile.c
@@ -199,6 +199,14 @@ create_sfile(unsigned long hash, struct transient const * trans,
199 199
 
200 200
 	sf->ignored = is_sf_ignored(sf);
201 201
 
  202
+	sf->embedded_offset = trans->embedded_offset;
  203
+
  204
+	/* If embedded_offset is a valid value, it means we're
  205
+	 * processing a Cell BE SPU profile; in which case, we
  206
+	 * want sf->app_cookie to hold trans->app_cookie.
  207
+	 */
  208
+	if (trans->embedded_offset != UNUSED_EMBEDDED_OFFSET)
  209
+		sf->app_cookie = trans->app_cookie;
202 210
 	return sf;
203 211
 }
204 212
 
@@ -399,7 +407,7 @@ static void sfile_log_arc(struct transient const * trans)
399 407
 	key = to & (0xffffffff);
400 408
 	key |= ((uint64_t)from) << 32;
401 409
 
402  
-	err = odb_insert(file, key, 1);
  410
+	err = odb_update_node(file, key);
403 411
 	if (err) {
404 412
 		fprintf(stderr, "%s: %s\n", __FUNCTION__, strerror(err));
405 413
 		abort();
@@ -438,7 +446,7 @@ void sfile_log_sample(struct transient const * trans)
438 446
 		return;
439 447
 	}
440 448
 
441  
-	err = odb_insert(file, (uint64_t)pc, 1);
  449
+	err = odb_update_node(file, (uint64_t)pc);
442 450
 	if (err) {
443 451
 		fprintf(stderr, "%s: %s\n", __FUNCTION__, strerror(err));
444 452
 		abort();
@@ -446,7 +454,7 @@ void sfile_log_sample(struct transient const * trans)
446 454
 }
447 455
 
448 456
 
449  
-static int close_sfile(struct sfile * sf)
  457
+static int close_sfile(struct sfile * sf, void * data __attribute__((unused)))
450 458
 {
451 459
 	size_t i;
452 460
 
@@ -460,13 +468,13 @@ static int close_sfile(struct sfile * sf)
460 468
 
461 469
 static void kill_sfile(struct sfile * sf)
462 470
 {
463  
-	close_sfile(sf);
  471
+	close_sfile(sf, NULL);
464 472
 	list_del(&sf->hash);
465 473
 	list_del(&sf->lru);
466 474
 }
467 475
 
468 476
 
469  
-static int sync_sfile(struct sfile * sf)
  477
+static int sync_sfile(struct sfile * sf, void * data __attribute__((unused)))
470 478
 {
471 479
 	size_t i;
472 480
 
@@ -477,22 +485,25 @@ static int sync_sfile(struct sfile * sf)
477 485
 }
478 486
 
479 487
 
480  
-static int is_sfile_kernel(struct sfile * sf)
  488
+static int is_sfile_kernel(struct sfile * sf, void * data __attribute__((unused)))
481 489
 {
482 490
 	return !!sf->kernel;
483 491
 }
484 492
 
485 493
 
486  
-static int is_sfile_anon(struct sfile * sf)
  494
+static int is_sfile_anon(struct sfile * sf, void * data)
487 495
 {
488  
-	return !!sf->anon;
  496
+	return sf->anon == data;
489 497
 }
490 498
 
491 499
 
492  
-static void for_one_sfile(struct sfile * sf, int (*func)(struct sfile *))
  500
+typedef int (*sfile_func)(struct sfile *, void *);
  501
+
  502
+static void
  503
+for_one_sfile(struct sfile * sf, sfile_func func, void * data)
493 504
 {
494 505
 	size_t i;
495  
-	int free_sf = func(sf);
  506
+	int free_sf = func(sf, data);
496 507
 
497 508
 	for (i = 0; i < CG_HASH_SIZE; ++i) {
498 509
 		struct list_head * pos;
@@ -500,7 +511,7 @@ static void for_one_sfile(struct sfile * sf, int (*func)(struct sfile *))
500 511
 		list_for_each_safe(pos, pos2, &sf->cg_hash[i]) {
501 512
 			struct cg_entry * cg =
502 513
 				list_entry(pos, struct cg_entry, hash);
503  
-			if (free_sf || func(&cg->to)) {
  514
+			if (free_sf || func(&cg->to, data)) {
504 515
 				kill_sfile(&cg->to);
505 516
 				list_del(&cg->hash);
506 517
 				free(cg);
@@ -515,39 +526,39 @@ static void for_one_sfile(struct sfile * sf, int (*func)(struct sfile *))
515 526
 }
516 527
 
517 528
 
518  
-static void for_each_sfile(int (*func)(struct sfile *))
  529
+static void for_each_sfile(sfile_func func, void * data)
519 530
 {
520 531
 	struct list_head * pos;
521 532
 	struct list_head * pos2;
522 533
 
523 534
 	list_for_each_safe(pos, pos2, &lru_list) {
524 535
 		struct sfile * sf = list_entry(pos, struct sfile, lru);
525  
-		for_one_sfile(sf, func);
  536
+		for_one_sfile(sf, func, data);
526 537
 	}
527 538
 }
528 539
 
529 540
 
530 541
 void sfile_clear_kernel(void)
531 542
 {
532  
-	for_each_sfile(is_sfile_kernel);
  543
+	for_each_sfile(is_sfile_kernel, NULL);
533 544
 }
534 545
 
535 546
 
536  
-void sfile_clear_anon(void)
  547
+void sfile_clear_anon(struct anon_mapping * anon)
537 548
 {
538  
-	for_each_sfile(is_sfile_anon);
  549
+	for_each_sfile(is_sfile_anon, anon);
539 550
 }
540 551
 
541 552
 
542 553
 void sfile_sync_files(void)
543 554
 {
544  
-	for_each_sfile(sync_sfile);
  555
+	for_each_sfile(sync_sfile, NULL);
545 556
 }
546 557
 
547 558
 
548 559
 void sfile_close_files(void)
549 560
 {
550  
-	for_each_sfile(close_sfile);
  561
+	for_each_sfile(close_sfile, NULL);
551 562
 }
552 563
 
553 564
 
@@ -578,7 +589,7 @@ int sfile_lru_clear(void)
578 589
 		if (!--amount)
579 590
 			break;
580 591
 		sf = list_entry(pos, struct sfile, lru);
581  
-		for_one_sfile(sf, (int (*)(struct sfile *))always_true);
  592
+		for_one_sfile(sf, (sfile_func)always_true, NULL);
582 593
 	}
583 594
 
584 595
 	return 0;
9  daemon/opd_sfile.h
@@ -25,6 +25,7 @@ struct kernel_image;
25 25
 struct transient;
26 26
 
27 27
 #define CG_HASH_SIZE 16
  28
+#define UNUSED_EMBEDDED_OFFSET ~0LLU
28 29
 
29 30
 /**
30 31
  * Each set of sample files (where a set is over the physical counter
@@ -50,6 +51,8 @@ struct sfile {
50 51
 	struct kernel_image * kernel;
51 52
 	/** anonymous mapping */
52 53
 	struct anon_mapping * anon;
  54
+	/** embedded offset for Cell BE SPU */
  55
+	uint64_t embedded_offset;
53 56
 
54 57
 	/** hash table link */
55 58
 	struct list_head hash;
@@ -74,8 +77,10 @@ struct cg_entry {
74 77
 /** clear any sfiles that are for the kernel */
75 78
 void sfile_clear_kernel(void);
76 79
 
77  
-/** clear any sfiles that are for anon mappings */
78  
-void sfile_clear_anon(void);
  80
+struct anon_mapping;
  81
+
  82
+/** clear any sfiles for the given anon mapping */
  83
+void sfile_clear_anon(struct anon_mapping *);
79 84
 
80 85
 /** sync sample files */
81 86
 void sfile_sync_files(void);
176  daemon/opd_spu.c
... ...
@@ -0,0 +1,176 @@
  1
+/**
  2
+ * @file daemon/opd_spu.c
  3
+ * Processing the sample buffer for Cell BE SPU profile
  4
+ *
  5
+ * @remark Copyright 2007 OProfile authors
  6
+ * @remark Read the file COPYING
  7
+ *
  8
+ * @author Maynard Johnson
  9
+ * (C) Copyright IBM Corporation 2007
  10
+ */
  11
+
  12
+#include "opd_interface.h"
  13
+#include "opd_printf.h"
  14
+#include "opd_sfile.h"
  15
+#include "opd_stats.h"
  16
+#include "opd_trans.h"
  17
+#include "op_libiberty.h"
  18
+
  19
+#include <stdlib.h>
  20
+#include <stdio.h>
  21
+
  22
+struct spu_context_info {
  23
+	pid_t tid;
  24
+	pid_t tgid;
  25
+	cookie_t app_cookie;
  26
+	uint64_t embedded_offset;
  27
+	cookie_t spu_cookie;
  28
+};
  29
+
  30
+static struct spu_context_info * spu_context_cache;
  31
+
  32
+/* Forward declaration */
  33
+static void process_spu_samples(struct transient * trans);
  34
+
  35
+void (*special_processor)(struct transient *);
  36
+
  37
+/*
  38
+ * This function is called when the first value found in the
  39
+ * buffer (after the beginning ESCAPE_CODE) is SPU_PROFILING_CODE.
  40
+ * Once we get here, the rest of the processing of the buffer is
  41
+ * Cell-SPU-specific, so we do not need to return until the
  42
+ * trans.buffer is empty.
  43
+ */
  44
+void code_spu_profiling(struct transient * trans)
  45
+{
  46
+	/* Next value in buffer is the number of SPUs. */
  47
+	unsigned long long num_spus = pop_buffer_value(trans);