Add a shared_ptr sanity check
[akaros.git] / tests / prov.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <argp.h>
4
5 #include <parlib/parlib.h>
6 #include <parlib/vcore.h>
7
8 const char *argp_program_version = "prov v0.1475263";
9 const char *argp_program_bug_address = "<akaros+subscribe@googlegroups.com>";
10
11 static char doc[] = "prov -- control for provisioning resources";
12 static char args_doc[] = "-p PID\n-c PROGRAM [ARGS]\nPROGRAM [ARGS]\n"
13                          "-- PROGRAM [ARGS]\n-s";
14
15 static struct argp_option options[] = {
16         {"type",                't', "TYPE",0, "Type of resource to provision"},
17         {"Possible types:", 0, 0, OPTION_DOC | OPTION_NO_USAGE, "c = cores\n"
18                                                                 "m = ram"},
19         {0, 0, 0, 0, "Call with exactly one of these, or with a program and args:"},
20         {"pid",                 'p', "PID",     OPTION_NO_USAGE, "Pid of process to provision "
21                                                      "resources to"},
22         {0, 0, 0, 0, ""},
23         {"command",             'c', "PROG",OPTION_NO_USAGE, "Launch a program and "
24                                                      "provision (alternate)"},
25         {0, 0, 0, 0, ""},
26         {"show",                's', 0,         OPTION_NO_USAGE, "Show current resource "
27                                                      "provisioning"},
28         {0, 0, 0, OPTION_DOC, "If your command has arguments that conflict with "
29                               "prov, then put them after -- to keep prov from "
30                               "interpretting them."},
31         {0, 0, 0, 0, "Call with exactly one of these when changing a provision:"},
32         {"value",               'v', "VAL",     0, "Type-specific value, passed to the kernel"},
33         {"max",                 'm', 0,         0, "Provision all resources of the given type"},
34         {0, 0, 0, OPTION_DOC, "Cores are provisioned to processes, so the value is "
35                               "a specific pcore id.  To undo a core's "
36                               "provisioning, pass in pid=0."},
37         { 0 }
38 };
39
40 #define PROV_MODE_PID                   1
41 #define PROV_MODE_CMD                   2
42 #define PROV_MODE_SHOW                  3
43
44 struct prog_args {
45         char                                            *cmd;
46         char                                            **cmd_args;
47         int                                                     mode;           /* PROV_MODE_ETC */
48         pid_t                                           pid;
49         char                                            res_type;       /* cores (c), ram (m), etc */
50         long                                            res_val;        /* type-specific value */
51         int                                                     max;
52         int                                                     dummy_val_flag;
53 };
54
55 static error_t parse_opt (int key, char *arg, struct argp_state *state)
56 {
57         struct prog_args *pargs = state->input;
58         switch (key) {
59                 case 't':
60                         pargs->res_type = arg[0];
61                         if (arg[1] != '\0')
62                                 printf("Warning, extra letters detected for -t's argument\n");
63                         break;
64                 case 'p':
65                         if (pargs->mode) {
66                                 printf("Too many modes given (-p, -s, COMMAND, etc)\n\n");
67                                 argp_usage(state);
68                         }
69                         pargs->mode = PROV_MODE_PID;
70                         pargs->pid = atoi(arg);
71                         break;
72                 case 's':
73                         if (pargs->mode) {
74                                 printf("Too many modes given (-p, -s, COMMAND, etc)\n\n");
75                                 argp_usage(state);
76                         }
77                         pargs->mode = PROV_MODE_SHOW;
78                         break;
79                 case 'c':
80                 case ARGP_KEY_ARG:
81                         if (pargs->mode) {
82                                 printf("Too many modes given (-p, -s, COMMAND, etc)\n\n");
83                                 argp_usage(state);
84                         }
85                         pargs->mode = PROV_MODE_CMD;
86                         pargs->cmd = arg;
87                         /* Point to the next arg.  We can also check state->arg_num, which
88                          * is how many non-arpg arguments there are */
89                         pargs->cmd_args = &state->argv[state->next];
90                         /* Consume all args (it's done when next == argc) */
91                         state->next = state->argc;
92                         break;
93                 case 'v':
94                         /* could also check to make sure we're not -s (and vice versa) */
95                         if (pargs->dummy_val_flag) {
96                                 printf("Provide only -v or -m, not both\n\n");
97                                 argp_usage(state);
98                         }
99                         pargs->dummy_val_flag = 1;
100                         pargs->res_val = atol(arg);
101                         break;
102                 case 'm':
103                         if (pargs->dummy_val_flag) {
104                                 printf("Provide only -v or -m, not both\n\n");
105                                 argp_usage(state);
106                         }
107                         pargs->dummy_val_flag = 1;
108                         pargs->max = 1;
109                         break;
110                 case ARGP_KEY_END:
111                         /* Make sure we selected a mode */
112                         if (!pargs->mode) {
113                                 printf("No mode selected (-p, -s, etc).\n\n");
114                                 argp_usage(state);
115                         }
116                         break;
117                 default:
118                         return ARGP_ERR_UNKNOWN;
119         }
120         return 0;
121 }
122
123 static struct argp argp = {options, parse_opt, args_doc, doc};
124
125 /* Used by both -p and -c modes (-c will use it after creating pid) */
126 static int prov_pid(pid_t pid, struct prog_args *pargs)
127 {
128         unsigned int kernel_res_type;
129         int retval;
130         switch (pargs->res_type) {
131                 case ('c'):
132                         if (pargs->max) {
133                                 /* TODO: don't guess the LL/CG layout and num pcores */
134                                 #if 1
135                                 for (int i = 1; i < max_vcores() + 1; i++) {
136                                         if ((retval = sys_provision(pid, RES_CORES, i))) {
137                                                 perror("Failed max provisioning");
138                                                 return retval;
139                                         }
140                                 }
141                                 #else
142                                 /* To force a vcore shuffle / least optimal ordering, change
143                                  * the if 1 to 0.  Normally, we provision out in a predictable,
144                                  * VCn->PCn+1 ordering.  This splits the odd and even VCs
145                                  * across sockets on a 32 PC machine (c89).  This is only for
146                                  * perf debugging, when using the lockprov.sh script. */
147                                 retval = 0;
148                                 retval |= sys_provision(pid, RES_CORES,  1);
149                                 retval |= sys_provision(pid, RES_CORES, 16);
150                                 retval |= sys_provision(pid, RES_CORES,  2);
151                                 retval |= sys_provision(pid, RES_CORES, 17);
152                                 retval |= sys_provision(pid, RES_CORES,  3);
153                                 retval |= sys_provision(pid, RES_CORES, 18);
154                                 retval |= sys_provision(pid, RES_CORES,  4);
155                                 retval |= sys_provision(pid, RES_CORES, 19);
156                                 retval |= sys_provision(pid, RES_CORES,  5);
157                                 retval |= sys_provision(pid, RES_CORES, 20);
158                                 retval |= sys_provision(pid, RES_CORES,  6);
159                                 retval |= sys_provision(pid, RES_CORES, 21);
160                                 retval |= sys_provision(pid, RES_CORES,  7);
161                                 retval |= sys_provision(pid, RES_CORES, 22);
162                                 retval |= sys_provision(pid, RES_CORES,  8);
163                                 retval |= sys_provision(pid, RES_CORES, 23);
164                                 retval |= sys_provision(pid, RES_CORES,  9);
165                                 retval |= sys_provision(pid, RES_CORES, 24);
166                                 retval |= sys_provision(pid, RES_CORES, 10);
167                                 retval |= sys_provision(pid, RES_CORES, 25);
168                                 retval |= sys_provision(pid, RES_CORES, 11);
169                                 retval |= sys_provision(pid, RES_CORES, 26);
170                                 retval |= sys_provision(pid, RES_CORES, 12);
171                                 retval |= sys_provision(pid, RES_CORES, 27);
172                                 retval |= sys_provision(pid, RES_CORES, 13);
173                                 retval |= sys_provision(pid, RES_CORES, 28);
174                                 retval |= sys_provision(pid, RES_CORES, 14);
175                                 retval |= sys_provision(pid, RES_CORES, 29);
176                                 retval |= sys_provision(pid, RES_CORES, 15);
177                                 retval |= sys_provision(pid, RES_CORES, 31);
178                                 retval |= sys_provision(pid, RES_CORES, 30);
179                                 return retval;
180                                 #endif
181                         } else {
182                                 if ((retval = sys_provision(pid, RES_CORES, pargs->res_val))) {
183                                         perror("Failed single provision");
184                                         return retval;
185                                 }
186                         }
187                         kernel_res_type = RES_CORES;
188                         break;
189                 case ('m'):
190                         printf("Provisioning memory is not supported yet\n");
191                         return -1;
192                         break;
193                 default:
194                         if (!pargs->res_type)
195                                 printf("No resource type selected.  Use -t\n");
196                         else
197                                 printf("Unsupported resource type %c\n", pargs->res_type);
198                         return -1;
199         }
200         sys_poke_ksched(pid, kernel_res_type);
201         return 0;
202 }
203
204 int main(int argc, char **argv)
205 {
206
207         struct prog_args pargs = {0};
208
209         argp_parse(&argp, argc, argv, 0, 0, &pargs);
210
211         switch (pargs.mode) {
212                 case (PROV_MODE_PID):
213                         return prov_pid(pargs.pid, &pargs);
214                         break;
215                 case (PROV_MODE_CMD):
216                         printf("Launching programs not supported yet\n");
217                         printf("Would have launched %s with args:", pargs.cmd);
218                         if (pargs.cmd_args)
219                                 for (int i = 0; pargs.cmd_args[i]; i++)
220                                         printf(" %s", pargs.cmd_args[i]);
221                         printf("\n");
222                         return 0;
223                         break;
224                 case (PROV_MODE_SHOW):
225                         printf("Show mode not supported yet, using ghetto interface\n\n");
226                         sys_provision(-1, 0, 0);
227                         return 0;
228                         break;
229                 default:
230                         return -1;
231         }
232 }