prov pokes the ksched after a successful provision
[akaros.git] / tests / prov.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <argp.h>
4
5 #include <parlib.h>
6 #include <vcore.h>
7
8 const char *argp_program_version = "prov v0.1475263";
9 const char *argp_program_bug_address = "<akaros@lists.eecs.berkeley.edu>";
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                                 for (int i = 1; i < max_vcores() + 1; i++) {
135                                         if ((retval = sys_provision(pid, RES_CORES, i))) {
136                                                 perror("Failed max provisioning");
137                                                 return retval;
138                                         }
139                                 }
140                         } else {
141                                 if ((retval = sys_provision(pid, RES_CORES, pargs->res_val))) {
142                                         perror("Failed single provision");
143                                         return retval;
144                                 }
145                         }
146                         kernel_res_type = RES_CORES;
147                         break;
148                 case ('m'):
149                         printf("Provisioning memory is not supported yet\n");
150                         return -1;
151                         break;
152                 default:
153                         if (!pargs->res_type)
154                                 printf("No resource type selected.  Use -t\n");
155                         else
156                                 printf("Unsupported resource type %c\n", pargs->res_type);
157                         return -1;
158         }
159         sys_poke_ksched(pid, kernel_res_type);
160         return 0;
161 }
162
163 int main(int argc, char **argv)
164 {
165
166         struct prog_args pargs = {0};
167
168         argp_parse(&argp, argc, argv, 0, 0, &pargs);
169
170         switch (pargs.mode) {
171                 case (PROV_MODE_PID):
172                         return prov_pid(pargs.pid, &pargs);
173                         break;
174                 case (PROV_MODE_CMD):
175                         printf("Launching programs not supported yet\n");
176                         printf("Would have launched %s with args:", pargs.cmd);
177                         if (pargs.cmd_args)
178                                 for (int i = 0; pargs.cmd_args[i]; i++)
179                                         printf(" %s", pargs.cmd_args[i]);
180                         printf("\n");
181                         return 0;
182                         break;
183                 case (PROV_MODE_SHOW):
184                         printf("Show mode not supported yet, using ghetto interface\n\n");
185                         sys_provision(-1, 0, 0);
186                         return 0;
187                         break;
188                 default:
189                         return -1;
190         }
191 }