Added new perf utility to access CPU counters from userspace
[akaros.git] / tools / profile / perf / akaros.c
1 /* Copyright (c) 2015 Google Inc
2  * Davide Libenzi <dlibenzi@google.com>
3  * See LICENSE for details.
4  */
5
6 #include <ros/arch/arch.h>
7 #include <ros/common.h>
8 #include <sys/types.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <limits.h>
13 #include <parlib/parlib.h>
14 #include "xlib.h"
15 #include "akaros.h"
16
17 static const unsigned int llcores[] = {
18         0
19 };
20
21 void ros_get_low_latency_core_set(struct core_set *cores)
22 {
23         for (size_t i = 0; i < COUNT_OF(llcores); i++)
24                 ros_set_bit(cores, llcores[i]);
25 }
26
27 size_t ros_get_low_latency_core_count(void)
28 {
29         return COUNT_OF(llcores);
30 }
31
32 size_t ros_total_cores(void)
33 {
34         return max_vcores() + ros_get_low_latency_core_count();
35 }
36
37 void ros_parse_cores(const char *str, struct core_set *cores)
38 {
39         unsigned int fcpu, ncpu;
40         char *dstr = xstrdup(str), *tok, *sptr, *sptr2;
41
42         ZERO_DATA(*cores);
43         for (tok = strtok_r(dstr, ":", &sptr); tok;
44                  tok = strtok_r(NULL, ":", &sptr)) {
45                 bool neg_core = FALSE;
46
47                 if (*tok == '!') {
48                         neg_core = TRUE;
49                         tok++;
50                 }
51                 if (!strcmp(tok, "all")) {
52                         size_t max_cores = ros_total_cores();
53
54                         if (max_cores > MAX_NUM_CORES) {
55                                 fprintf(stderr, "The number of system CPU exceeds the "
56                                                 "structure limits: num_cores=%u limits=%u\n", max_cores,
57                                                 CHAR_BIT * CORE_SET_SIZE);
58                                 exit(1);
59                         }
60                         if (neg_core)
61                                 memset(cores->core_set, 0,
62                                            DIV_ROUND_UP(max_cores, CHAR_BIT));
63                         else
64                                 memset(cores->core_set, 0xff,
65                                            DIV_ROUND_UP(max_cores, CHAR_BIT));
66                 } else if (!strcmp(tok, "llall")) {
67                         ros_get_low_latency_core_set(cores);
68                 } else if (strchr(tok, '-')) {
69                         if (sscanf(tok, "%u-%u", &fcpu, &ncpu) != 2) {
70                                 fprintf(stderr, "Invalid CPU range: %s\n", tok);
71                                 exit(1);
72                         }
73                         if ((fcpu >= MAX_NUM_CORES) ||
74                                 (ncpu >= MAX_NUM_CORES) || (fcpu > ncpu)) {
75                                 fprintf(stderr, "CPU number out of bound: %u\n",
76                                                 fcpu);
77                                 exit(1);
78                         }
79                         for (; fcpu <= ncpu; fcpu++) {
80                                 if (neg_core)
81                                         ros_clear_bit(cores->core_set, fcpu);
82                                 else
83                                         ros_set_bit(cores->core_set, fcpu);
84                         }
85                 } else {
86                         for (tok = strtok_r(tok, ".", &sptr2); tok;
87                                  tok = strtok_r(NULL, ".", &sptr2)) {
88                                 fcpu = atoi(tok);
89                                 if (fcpu >= MAX_NUM_CORES) {
90                                         fprintf(stderr, "CPU number out of bound: %u\n",
91                                                         fcpu);
92                                         exit(1);
93                                 }
94                                 if (neg_core)
95                                         ros_clear_bit(cores->core_set, fcpu);
96                                 else
97                                         ros_set_bit(cores->core_set, fcpu);
98                         }
99                 }
100         }
101         free(dstr);
102 }
103
104 void ros_get_all_cores_set(struct core_set *cores)
105 {
106         size_t max_cores = ros_total_cores();
107
108         memset(cores->core_set, 0xff, DIV_ROUND_UP(max_cores, CHAR_BIT));
109 }
110
111 void ros_not_core_set(struct core_set *dcs)
112 {
113         size_t max_cores = ros_total_cores();
114
115         for (size_t i = 0; (max_cores > 0) && (i < sizeof(dcs->core_set)); i++) {
116                 size_t nb = (max_cores >= CHAR_BIT) ? CHAR_BIT : max_cores;
117
118                 dcs->core_set[i] = (~dcs->core_set[i]) & ((1 << nb) - 1);
119                 max_cores -= nb;
120         }
121 }
122
123 void ros_and_core_sets(struct core_set *dcs, const struct core_set *scs)
124 {
125         for (size_t i = 0; i < sizeof(dcs->core_set); i++)
126                 dcs->core_set[i] &= scs->core_set[i];
127 }
128
129 void ros_or_core_sets(struct core_set *dcs, const struct core_set *scs)
130 {
131         for (size_t i = 0; i < sizeof(dcs->core_set); i++)
132                 dcs->core_set[i] |= scs->core_set[i];
133 }