parlib: Use a relative timer for abort_sysc
[akaros.git] / user / parlib / core_set.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 <sys/stat.h>
10 #include <fcntl.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <limits.h>
16 #include <unistd.h>
17 #include <parlib/parlib.h>
18 #include <parlib/core_set.h>
19
20 static const unsigned int llcores[] = {
21         0
22 };
23
24 void parlib_get_ll_core_set(struct core_set *cores)
25 {
26         parlib_get_none_core_set(cores);
27         for (size_t i = 0; i < COUNT_OF(llcores); i++)
28                 parlib_set_core(cores, llcores[i]);
29 }
30
31 size_t parlib_nr_ll_cores(void)
32 {
33         return COUNT_OF(llcores);
34 }
35
36 static int guess_nr_cores(void)
37 {
38         return max_vcores() + parlib_nr_ll_cores();
39 }
40
41 static int get_vars_nr_cores(void)
42 {
43         int fd, ret;
44         char buf[10];
45
46         fd = open("#vars/num_cores!dw", O_READ);
47         if (fd < 0)
48                 return -1;
49         if (read(fd, buf, sizeof(buf)) <= 0) {
50                 close(fd);
51                 return -1;
52         }
53         ret = atoi(buf);
54         return ret;
55 }
56
57 static int nr_cores;
58
59 static void set_nr_cores(void *arg)
60 {
61         nr_cores = get_vars_nr_cores();
62         if (nr_cores == -1)
63                 nr_cores = guess_nr_cores();
64 }
65
66 size_t parlib_nr_total_cores(void)
67 {
68         static parlib_once_t once = PARLIB_ONCE_INIT;
69
70         parlib_run_once(&once, set_nr_cores, NULL);
71         return nr_cores;
72 }
73
74 void parlib_parse_cores(const char *str, struct core_set *cores)
75 {
76         unsigned int fcpu, ncpu;
77         char *dstr = strdup(str);
78         char *sptr = NULL;
79         char *tok, *sptr2;
80
81         if (!dstr) {
82                 perror("Duplicating a string");
83                 exit(1);
84         }
85         ZERO_DATA(*cores);
86         for (tok = strtok_r(dstr, ",", &sptr); tok;
87                  tok = strtok_r(NULL, ",", &sptr)) {
88
89                 if (strchr(tok, '-')) {
90                         if (sscanf(tok, "%u-%u", &fcpu, &ncpu) != 2) {
91                                 fprintf(stderr, "Invalid CPU range: %s\n", tok);
92                                 exit(1);
93                         }
94                         if (fcpu >= parlib_nr_total_cores()) {
95                                 fprintf(stderr, "CPU number out of bound: %u\n", fcpu);
96                                 exit(1);
97                         }
98                         if (ncpu >= parlib_nr_total_cores()) {
99                                 fprintf(stderr, "CPU number out of bound: %u\n", ncpu);
100                                 exit(1);
101                         }
102                         if (fcpu > ncpu) {
103                                 fprintf(stderr, "CPU range is backwards: %u-%u\n", fcpu, ncpu);
104                                 exit(1);
105                         }
106                         for (; fcpu <= ncpu; fcpu++)
107                                 parlib_set_core(cores, fcpu);
108                 } else {
109                         fcpu = atoi(tok);
110                         if (fcpu >= parlib_nr_total_cores()) {
111                                 fprintf(stderr, "CPU number out of bound: %u\n",
112                                                 fcpu);
113                                 exit(1);
114                         }
115                         parlib_set_core(cores, fcpu);
116                 }
117         }
118         free(dstr);
119 }
120
121 void parlib_get_all_core_set(struct core_set *cores)
122 {
123         size_t max_cores = parlib_nr_total_cores();
124
125         memset(cores->core_set, 0xff, DIV_ROUND_UP(max_cores, CHAR_BIT));
126 }
127
128 void parlib_get_none_core_set(struct core_set *cores)
129 {
130         size_t max_cores = parlib_nr_total_cores();
131
132         memset(cores->core_set, 0, DIV_ROUND_UP(max_cores, CHAR_BIT));
133 }
134
135 void parlib_not_core_set(struct core_set *dcs)
136 {
137         size_t max_cores = parlib_nr_total_cores();
138
139         for (size_t i = 0; (max_cores > 0) && (i < sizeof(dcs->core_set)); i++) {
140                 size_t nb = (max_cores >= CHAR_BIT) ? CHAR_BIT : max_cores;
141
142                 dcs->core_set[i] = (~dcs->core_set[i]) & ((1 << nb) - 1);
143                 max_cores -= nb;
144         }
145 }
146
147 void parlib_and_core_sets(struct core_set *dcs, const struct core_set *scs)
148 {
149         for (size_t i = 0; i < sizeof(dcs->core_set); i++)
150                 dcs->core_set[i] &= scs->core_set[i];
151 }
152
153 void parlib_or_core_sets(struct core_set *dcs, const struct core_set *scs)
154 {
155         for (size_t i = 0; i < sizeof(dcs->core_set); i++)
156                 dcs->core_set[i] |= scs->core_set[i];
157 }