sched: Slightly fix up tests/prov
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 13 Dec 2017 21:23:10 +0000 (16:23 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 14 Dec 2017 18:42:20 +0000 (13:42 -0500)
prov now takes core lists (e.g. "1,3-5") instead of just a core at a time,
just like perf.

prov also can spawn processes, just like perf and strace.

Other than that, it's still in need of an overhaul.  It doesn't let you
provision multiple resource types to a process at a time, such as cores and
memory.  'show' mode still uses the kernel hack.  Stylistically, it could
use some work too.

For now, since we only provision cores, it's OK.  When we update the kernel
interface, we'll update prov too.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/prov.c

index cc2cc4f..ef2ee64 100644 (file)
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <argp.h>
@@ -5,9 +7,6 @@
 #include <parlib/parlib.h>
 #include <parlib/vcore.h>
 
-const char *argp_program_version = "prov v0.1475263";
-const char *argp_program_bug_address = "<akaros+subscribe@googlegroups.com>";
-
 static char doc[] = "prov -- control for provisioning resources";
 static char args_doc[] = "-p PID\n-c PROGRAM [ARGS]\nPROGRAM [ARGS]\n"
                          "-- PROGRAM [ARGS]\n-s";
@@ -31,9 +30,8 @@ static struct argp_option options[] = {
        {0, 0, 0, 0, "Call with exactly one of these when changing a provision:"},
        {"value",               'v', "VAL",     0, "Type-specific value, passed to the kernel"},
        {"max",                 'm', 0,         0, "Provision all resources of the given type"},
-       {0, 0, 0, OPTION_DOC, "Cores are provisioned to processes, so the value is "
-                             "a specific pcore id.  To undo a core's "
-                             "provisioning, pass in pid=0."},
+       {0, 0, 0, OPTION_DOC, "VAL for cores is a list, e.g. -v 1,3-5,9"},
+       {0, 0, 0, OPTION_DOC, "To undo a core's provisioning, pass in pid=0."},
        { 0 }
 };
 
@@ -42,13 +40,14 @@ static struct argp_option options[] = {
 #define PROV_MODE_SHOW                 3
 
 struct prog_args {
-       char                                            *cmd;
-       char                                            **cmd_args;
+       char                                            **cmd_argv;
+       int                                                     cmd_argc;
        int                                                     mode;           /* PROV_MODE_ETC */
        pid_t                                           pid;
        char                                            res_type;       /* cores (c), ram (m), etc */
-       long                                            res_val;        /* type-specific value */
-       int                                                     max;
+       char                                            *res_val;       /* type-specific value, unparsed */
+       struct core_set                         cores;
+       bool                                            max;
        int                                                     dummy_val_flag;
 };
 
@@ -83,11 +82,14 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
                                argp_usage(state);
                        }
                        pargs->mode = PROV_MODE_CMD;
-                       pargs->cmd = arg;
-                       /* Point to the next arg.  We can also check state->arg_num, which
-                        * is how many non-arpg arguments there are */
-                       pargs->cmd_args = &state->argv[state->next];
-                       /* Consume all args (it's done when next == argc) */
+
+                       pargs->cmd_argc = state->argc - state->next + 1;
+                       pargs->cmd_argv = malloc(sizeof(char*) * (pargs->cmd_argc + 1));
+                       assert(pargs->cmd_argv);
+                       pargs->cmd_argv[0] = arg;
+                       memcpy(&pargs->cmd_argv[1], &state->argv[state->next],
+                              sizeof(char*) * (pargs->cmd_argc - 1));
+                       pargs->cmd_argv[pargs->cmd_argc] = NULL;
                        state->next = state->argc;
                        break;
                case 'v':
@@ -97,7 +99,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
                                argp_usage(state);
                        }
                        pargs->dummy_val_flag = 1;
-                       pargs->res_val = atol(arg);
+                       pargs->res_val = arg;
                        break;
                case 'm':
                        if (pargs->dummy_val_flag) {
@@ -105,7 +107,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
                                argp_usage(state);
                        }
                        pargs->dummy_val_flag = 1;
-                       pargs->max = 1;
+                       pargs->max = true;
                        break;
                case ARGP_KEY_END:
                        /* Make sure we selected a mode */
@@ -125,66 +127,18 @@ static struct argp argp = {options, parse_opt, args_doc, doc};
 /* Used by both -p and -c modes (-c will use it after creating pid) */
 static int prov_pid(pid_t pid, struct prog_args *pargs)
 {
-       unsigned int kernel_res_type;
-       int retval;
        switch (pargs->res_type) {
                case ('c'):
                        if (pargs->max) {
-                               /* TODO: don't guess the LL/CG layout and num pcores */
-                               #if 1
-                               for (int i = 1; i < max_vcores() + 1; i++) {
-                                       if ((retval = sys_provision(pid, RES_CORES, i))) {
-                                               perror("Failed max provisioning");
-                                               return retval;
-                                       }
-                               }
-                               #else
-                               /* To force a vcore shuffle / least optimal ordering, change
-                                * the if 1 to 0.  Normally, we provision out in a predictable,
-                                * VCn->PCn+1 ordering.  This splits the odd and even VCs
-                                * across sockets on a 32 PC machine (c89).  This is only for
-                                * perf debugging, when using the lockprov.sh script. */
-                               retval = 0;
-                               retval |= sys_provision(pid, RES_CORES,  1);
-                               retval |= sys_provision(pid, RES_CORES, 16);
-                               retval |= sys_provision(pid, RES_CORES,  2);
-                               retval |= sys_provision(pid, RES_CORES, 17);
-                               retval |= sys_provision(pid, RES_CORES,  3);
-                               retval |= sys_provision(pid, RES_CORES, 18);
-                               retval |= sys_provision(pid, RES_CORES,  4);
-                               retval |= sys_provision(pid, RES_CORES, 19);
-                               retval |= sys_provision(pid, RES_CORES,  5);
-                               retval |= sys_provision(pid, RES_CORES, 20);
-                               retval |= sys_provision(pid, RES_CORES,  6);
-                               retval |= sys_provision(pid, RES_CORES, 21);
-                               retval |= sys_provision(pid, RES_CORES,  7);
-                               retval |= sys_provision(pid, RES_CORES, 22);
-                               retval |= sys_provision(pid, RES_CORES,  8);
-                               retval |= sys_provision(pid, RES_CORES, 23);
-                               retval |= sys_provision(pid, RES_CORES,  9);
-                               retval |= sys_provision(pid, RES_CORES, 24);
-                               retval |= sys_provision(pid, RES_CORES, 10);
-                               retval |= sys_provision(pid, RES_CORES, 25);
-                               retval |= sys_provision(pid, RES_CORES, 11);
-                               retval |= sys_provision(pid, RES_CORES, 26);
-                               retval |= sys_provision(pid, RES_CORES, 12);
-                               retval |= sys_provision(pid, RES_CORES, 27);
-                               retval |= sys_provision(pid, RES_CORES, 13);
-                               retval |= sys_provision(pid, RES_CORES, 28);
-                               retval |= sys_provision(pid, RES_CORES, 14);
-                               retval |= sys_provision(pid, RES_CORES, 29);
-                               retval |= sys_provision(pid, RES_CORES, 15);
-                               retval |= sys_provision(pid, RES_CORES, 31);
-                               retval |= sys_provision(pid, RES_CORES, 30);
-                               return retval;
-                               #endif
+                               parlib_get_all_core_set(&pargs->cores);
                        } else {
-                               if ((retval = sys_provision(pid, RES_CORES, pargs->res_val))) {
-                                       perror("Failed single provision");
-                                       return retval;
+                               if (!pargs->res_val) {
+                                       printf("Need a list of cores to provision\n");
+                                       return -1;
                                }
+                               parlib_parse_cores(pargs->res_val, &pargs->cores);
                        }
-                       kernel_res_type = RES_CORES;
+                       provision_core_set(pid, &pargs->cores);
                        break;
                case ('m'):
                        printf("Provisioning memory is not supported yet\n");
@@ -197,14 +151,13 @@ static int prov_pid(pid_t pid, struct prog_args *pargs)
                                printf("Unsupported resource type %c\n", pargs->res_type);
                        return -1;
        }
-       sys_poke_ksched(pid, kernel_res_type);
        return 0;
 }
 
-int main(int argc, char **argv)
+int main(int argc, char **argv, char **envp)
 {
-
        struct prog_args pargs = {0};
+       pid_t pid;
 
        argp_parse(&argp, argc, argv, 0, 0, &pargs);
 
@@ -213,16 +166,23 @@ int main(int argc, char **argv)
                        return prov_pid(pargs.pid, &pargs);
                        break;
                case (PROV_MODE_CMD):
-                       printf("Launching programs not supported yet\n");
-                       printf("Would have launched %s with args:", pargs.cmd);
-                       if (pargs.cmd_args)
-                               for (int i = 0; pargs.cmd_args[i]; i++)
-                                       printf(" %s", pargs.cmd_args[i]);
-                       printf("\n");
+                       pid = create_child_with_stdfds(pargs.cmd_argv[0], pargs.cmd_argc,
+                                                      pargs.cmd_argv, envp);
+                       if (pid < 0) {
+                               perror("Unable to spawn child");
+                               exit(-1);
+                       }
+                       if (prov_pid(pid, &pargs)) {
+                               perror("Unable to provision to child");
+                               sys_proc_destroy(pid, -1);
+                               exit(-1);
+                       }
+                       sys_proc_run(pid);
+                       waitpid(pid, NULL, 0);
                        return 0;
-                       break;
                case (PROV_MODE_SHOW):
                        printf("Show mode not supported yet, using ghetto interface\n\n");
+                       printf("Check 'dmesg' if you aren't on the console\n\n");
                        sys_provision(-1, 0, 0);
                        return 0;
                        break;