Re: [PATCH v2 0/1] coresched: Manage core scheduling cookies for tasks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Thijs,

On Wed, Mar 27, 2024 at 01:43:20PM +0100 Thijs Raymakers wrote:
> Hi Phil,
> 
> Op 26-03-2024 om 19:13 schreef Phil Auld:
> > On Tue, Mar 26, 2024 at 06:49:07PM +0100 Thijs Raymakers wrote:
> >> Op 26-03-2024 om 15:41 schreef Phil Auld:
> >>> On Sat, Mar 16, 2024 at 06:10:03PM +0100, Thijs Raymakers wrote:
> >>>> - How should the program behave if the prctl core scheduling API is not
> >>>>   available? It has been in Linus' tree since november 2021
> >>>>   (commit a41b74451b35f7a6529689760eb8c05241feecbc) but it can be
> >>>>   disabled with CONFIG_SCHED_CORE=n
> >>> This one is tricky. If I recall the error you get is ambiguous in this case
> >>> (EINVAL, which can be returned for other reasons). It would be nice to be
> >>> able to report that specifically. 
> >> In general, `prctl` does indeed return EINVAL if the operation is not
> >> recognized, or not supported on the system. The `PR_SCHED_CORE`
> >> operation itself only returns EINVAL if it is called with
> >>   - an invalid operation
> >>   - an invalid type
> >>   - a negative PID
> >>   - an invalid cookie store address (for PR_SCHED_CORE_GET)
> >> Assuming that all these cases are prevented by the util, we could
> >> interpret a EINVAL as a sign that PR_SCHED_CORE is not supported on
> >> the system.
> > Fair enough. Could say something like "got EINVAL. Does your kernel
> > support CONFIG_SCHED_CORE?". 
> 
> I've added this as a warning in case a prctl call returns EINVAL. I
> haven't tested it on a kernel with CONFIG_SCHED_CORE=n yet but I will do
> that later.

Thanks. I'll refresh and try it again. My build machine does not have
CONFIG_CORE_SCHED so that's easy for me to test :)

> 
> > There is also
> >        err_exclusive_options(c, longopts, excl, excl_st);
> > 
> > in the optuils.h code which can handle the tests for mutually exclusive
> > arguments.
> > 
> > Thomas pointed me to that. It works nicely and can remove some of the extra
> > checks (once you get it setup). And the error then looks the same as other
> > util-linux progs. 
> 
> Good suggestion, I replaced some of the earlier mutually exclusive
> checks with a call to err_exclusive_options.
> 
> > You might consider "errtryhelp(EXIT_FAILURE);"  in usage failures. A lot of
> > the progs (incl taskset which is my model for this) do that. Then you only
> > do the full usage when given -h/--help.
> 
> This does indeed feel a slightly nicer to use. I've added this in case a
> of a usage failure. In case no options are given, it defaults to
> printing the --help page. This matches the behavior of some other utils like
> uclampset, and saves some time.
> 
> 
> Op 26-03-2024 om 21:16 schreef Phil Auld:
> > So "-n/--new" creates a new cookie and so does "". Just one on an existing task
> > and one on the exec'd task.  Seems inconsistent, no?
> 
> Hmmm, I didn't intially see this as inconsistent behavior but I get why
> you say this. I've modified this now to have -n/--new deal both with
> assigning cookies to existing processes and to spawn new processes.
> 
> 
> Op 26-03-2024 om 21:17 schreef Phil Auld:
> > Btw, did you try coreset to see if it does what you need?
> 
> I did take a look at it. Thanks for adding the functionality of copying
> a cookie from/to an existing PID. The commands take a bit of getting
> used to for me, so I guess it is just a matter of preference of what feels
> natural to use.

Yeah, fair enough.  I wrote it so it makes sense to me ;)

> Some things that weren't directly clear to me:
> - Both `coreset ls` and `coreset -n ls` spawn a new program. If I
>   understood it correctly, the former spawns the program without
>   a cookie, and the latter spawns it with a cookie. I'm not entirely
>   sure what the point of the former would be, as the cookie would either
>   be 0 or equal to the cookie of the `coreset` process itself since the
>   cookie in inherited across execs. It is not necessary to run the
>   provided program in that case.

It's more informational. Since "get" is essentially the default, coreset ls
would run ls and report its cookie. Not totally useful but more for
consistency and it tells you that your shell does or does not have a
cookie set.

> - Not entirely sure what the difference between --dest and --to is.
>   The names of these options are similar in meaning and do almost the
>   same thing.

That's the one I added to cover your use case. Dest is specifically only
used with --copy. It makes copy into a pull_then_push rather than a
 pull_then_exec. 

--to is just a push.  It will push the current task's cookie to
<pid>.  This is also useful to clear a tasks cookie if your current shell does
not have a cookie set.

With your coresched tool I think you have to pick a random pid that you
know does not have a cookie and use that to clear a different pid's cookie.

> - It is not clear in what cases --scope is ignored and in which
>   cases it is necessary.

Fair enough.  Also I have not yet cribbed your string version of scope.

> - What does `coreset -c -s 0 -d 2 -p 1 ls` do? Does it first copy the
>   cookie from PID 1 to PID 2, and then run `ls` with the same or
>   different cookie? Or the other way around?
>

It should copy pid 1's cookie to pid 2 and report that it's ignoring the
extra input.  It would not run ls in this case. 

-d is the destination pid in the case of copy.  So --pid is copy from (in
both exec and --dest cases). 

-s 0 is redundant since that's the default in coreset.

> Now I do see what you meant earlier with imitating the behavior of the
> `taskset` command. I don't think this is strictly necessary since it is
> a different utility program, but I can understand that it can be useful
> for people if the command behaves similar to a program that they already
> know and have certain expectations of.
> 
> I've modified the options of coresched to be more in line with these
> expectations, while also addressing the things I mentioned above.
> 
> Usage:
>  coresched [-p PID]
>  coresched --new [-t <TYPE>] -p <PID>
>  coresched --new [-t <TYPE>] -- PROGRAM [ARGS...]
>  coresched --copy -p <PID> [-t <TYPE>] -d <PID>
>  coresched --copy -p <PID> [-t <TYPE>] -- PROGRAM [ARGS...]
> 
> This follows the taskset's behavior (i.e. perform the same operation
> on either an existing PID or on a new program) and taskset's arguments
> (-p for PID instead of the -s I had earlier) more closely than before.
>

I think I like the above, nice.

> I've attached an interdiff of the util compared to the previous version
> that I sent yesterday. I think that this version encompases both our use
> cases quite nicely.

Let me give it a try. I may or may not have time to get to it today.
Other priorities arise. We'll see.

I do still prefer coreset as a name but I won't die on that hill :)


Cheers,
Phil

> 
> Thijs
> 
> Thijs Raymakers (1):
>   coresched: Manage core scheduling cookies for tasks
> 
>  .gitignore                  |   1 +
>  bash-completion/coresched   |   0
>  configure.ac                |  12 +-
>  meson.build                 |  16 +-
>  meson_options.txt           |   2 +-
>  schedutils/Makemodule.am    |   8 +
>  schedutils/coresched.1.adoc |  16 ++
>  schedutils/coresched.c      | 363 ++++++++++++++++++++++++++++++++++++
>  8 files changed, 412 insertions(+), 6 deletions(-)
>  create mode 100644 bash-completion/coresched
>  create mode 100644 schedutils/coresched.1.adoc
>  create mode 100644 schedutils/coresched.c
> 
> Interdiff against v1:
> diff --git a/schedutils/coresched.c b/schedutils/coresched.c
> index 17d775f2d..537281fdb 100644
> --- a/schedutils/coresched.c
> +++ b/schedutils/coresched.c
> @@ -12,10 +12,12 @@
>  #include <stdio.h>
>  #include <sys/prctl.h>
>  #include <sys/wait.h>
> +#include <unistd.h>
>  
>  #include "c.h"
>  #include "closestream.h"
>  #include "nls.h"
> +#include "optutils.h"
>  #include "strutils.h"
>  
>  // These definitions might not be defined, even if the
> @@ -26,32 +28,34 @@
>  #ifndef PR_SCHED_CORE_SCOPE_THREAD_GROUP
>  #define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1
>  #endif
> +
>  #ifndef PR_SCHED_CORE_SCOPE_PROCESS_GROUP
>  #define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2
>  #endif
>  
>  typedef int core_sched_type_t;
> +typedef unsigned long cookie_t;
>  typedef enum {
> -	SCHED_CORE_CMD_EXEC = 0,
> -	SCHED_CORE_CMD_GET = 1,
> -	SCHED_CORE_CMD_CREATE = 2,
> -	SCHED_CORE_CMD_COPY = 4,
> +	SCHED_CORE_CMD_GET,
> +	SCHED_CORE_CMD_NEW,
> +	SCHED_CORE_CMD_COPY,
>  } core_sched_cmd_t;
>  
>  struct args {
> -	pid_t from_pid;
> -	pid_t to_pid;
> +	pid_t pid;
> +	pid_t dest;
>  	core_sched_type_t type;
>  	core_sched_cmd_t cmd;
>  	int exec_argv_offset;
>  };
>  
> -unsigned long core_sched_get_cookie(struct args *args);
> -void core_sched_create_cookie(struct args *args);
> +cookie_t core_sched_get_cookie(pid_t pid);
> +void core_sched_create_cookie(pid_t pid, core_sched_type_t type);
>  void core_sched_pull_cookie(pid_t from);
>  void core_sched_push_cookie(pid_t to, core_sched_type_t type);
> -void core_sched_copy_cookie(struct args *args);
> +void core_sched_copy_cookie(pid_t from, pid_t to, core_sched_type_t to_type);
>  void core_sched_exec_with_cookie(struct args *args, char **argv);
> +void core_sched_get_and_print_cookie(pid_t pid);
>  
>  core_sched_type_t parse_core_sched_type(char *str);
>  bool verify_arguments(struct args *args);
> @@ -59,22 +63,31 @@ void parse_arguments(int argc, char **argv, struct args *args);
>  void set_pid_or_err(pid_t *dest, pid_t src, const char *err_msg);
>  static void __attribute__((__noreturn__)) usage(void);
>  
> -unsigned long core_sched_get_cookie(struct args *args)
> +#define bad_usage(FMT...) \
> +	warnx(FMT);       \
> +	errtryhelp(EINVAL);
> +
> +#define check_coresched_in_kernel(errno)                              \
> +	if (errno == EINVAL) {                                        \
> +		warnx("Does your kernel support CONFIG_SCHED_CORE?"); \
> +	}
> +
> +cookie_t core_sched_get_cookie(pid_t pid)
>  {
> -	unsigned long cookie = 0;
> -	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, args->from_pid,
> +	cookie_t cookie = 0;
> +	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, pid,
>  		  PR_SCHED_CORE_SCOPE_THREAD, &cookie)) {
> -		err(errno, "Failed to get cookie from PID %d", args->from_pid);
> +		check_coresched_in_kernel(errno);
> +		err(errno, "Failed to get cookie from PID %d", pid);
>  	}
>  	return cookie;
>  }
>  
> -void core_sched_create_cookie(struct args *args)
> +void core_sched_create_cookie(pid_t pid, core_sched_type_t type)
>  {
> -	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, args->to_pid, args->type,
> -		  0)) {
> -		err(errno, "Failed to create cookie for PID %d",
> -		    args->from_pid);
> +	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, pid, type, 0)) {
> +		check_coresched_in_kernel(errno);
> +		err(errno, "Failed to create cookie for PID %d", pid);
>  	}
>  }
>  
> @@ -82,6 +95,7 @@ void core_sched_pull_cookie(pid_t from)
>  {
>  	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_FROM, from,
>  		  PR_SCHED_CORE_SCOPE_THREAD, 0)) {
> +		check_coresched_in_kernel(errno);
>  		err(errno, "Failed to pull cookie from PID %d", from);
>  	}
>  }
> @@ -89,14 +103,18 @@ void core_sched_pull_cookie(pid_t from)
>  void core_sched_push_cookie(pid_t to, core_sched_type_t type)
>  {
>  	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, to, type, 0)) {
> +		check_coresched_in_kernel(errno);
>  		err(errno, "Failed to push cookie to PID %d", to);
>  	}
>  }
>  
> -void core_sched_copy_cookie(struct args *args)
> +void core_sched_copy_cookie(pid_t from, pid_t to, core_sched_type_t to_type)
>  {
> -	core_sched_pull_cookie(args->from_pid);
> -	core_sched_push_cookie(args->to_pid, args->type);
> +	core_sched_pull_cookie(from);
> +	cookie_t before = core_sched_get_cookie(from);
> +	core_sched_push_cookie(to, to_type);
> +	printf("%s: copied cookie 0x%lx from PID %d to PID %d\n",
> +	       program_invocation_short_name, before, from, to);
>  }
>  
>  void core_sched_exec_with_cookie(struct args *args, char **argv)
> @@ -111,11 +129,15 @@ void core_sched_exec_with_cookie(struct args *args, char **argv)
>  	// If a source PID is provided, try to copy the cookie from
>  	// that PID. Otherwise, create a brand new cookie with the
>  	// provided type.
> -	if (args->from_pid) {
> -		core_sched_pull_cookie(args->from_pid);
> +	if (args->pid) {
> +		core_sched_pull_cookie(args->pid);
> +		core_sched_get_and_print_cookie(args->pid);
>  	} else {
> -		args->to_pid = getpid();
> -		core_sched_create_cookie(args);
> +		pid_t pid = getpid();
> +		core_sched_create_cookie(pid, args->type);
> +		cookie_t after = core_sched_get_cookie(pid);
> +		printf("%s: set cookie of PID %d to 0x%lx\n",
> +		       program_invocation_short_name, pid, after);
>  	}
>  
>  	if (execvp(argv[0], argv)) {
> @@ -123,6 +145,13 @@ void core_sched_exec_with_cookie(struct args *args, char **argv)
>  	}
>  }
>  
> +void core_sched_get_and_print_cookie(pid_t pid)
> +{
> +	cookie_t after = core_sched_get_cookie(pid);
> +	printf("%s: set cookie of PID %d to 0x%lx\n",
> +	       program_invocation_short_name, pid, after);
> +}
> +
>  core_sched_type_t parse_core_sched_type(char *str)
>  {
>  	if (!strncmp(str, "pid\0", 4)) {
> @@ -133,156 +162,96 @@ core_sched_type_t parse_core_sched_type(char *str)
>  		return PR_SCHED_CORE_SCOPE_PROCESS_GROUP;
>  	}
>  
> -	errx(EINVAL, "'%s' is an invalid option. Must be one of pid/tgid/pgid",
> -	     str);
> +	bad_usage("'%s' is an invalid option. Must be one of pid/tgid/pgid",
> +		  str);
>  	__builtin_unreachable();
>  }
>  
>  static void __attribute__((__noreturn__)) usage(void)
>  {
>  	fputs(USAGE_HEADER, stdout);
> -	fprintf(stdout, _(" %s --get <PID>\n"), program_invocation_short_name);
> -	fprintf(stdout, _(" %s --new <PID> [-t <TYPE>]\n"),
> +	fprintf(stdout, _(" %s [-p PID]\n"), program_invocation_short_name);
> +	fprintf(stdout, _(" %s --new [-t <TYPE>] -p <PID>\n"),
>  		program_invocation_short_name);
> -	fprintf(stdout, _(" %s --copy -s <PID> -d <PID> [-t <TYPE>]\n"),
> +	fprintf(stdout, _(" %s --new [-t <TYPE>] -- PROGRAM [ARGS...]\n"),
>  		program_invocation_short_name);
> -	fprintf(stdout, _(" %s [-s <PID>] -- PROGRAM ARGS... \n"),
> +	fprintf(stdout, _(" %s --copy -p <PID> [-t <TYPE>] -d <PID>\n"),
> +		program_invocation_short_name);
> +	fprintf(stdout,
> +		_(" %s --copy -p <PID> [-t <TYPE>] -- PROGRAM [ARGS...]\n"),
>  		program_invocation_short_name);
>  
>  	fputs(USAGE_SEPARATOR, stdout);
>  	fputsln(_("Manage core scheduling cookies for tasks."), stdout);
>  
>  	fputs(USAGE_FUNCTIONS, stdout);
> -	fputsln(_(" -g, --get <PID>         get the core scheduling cookie of a PID"),
> +	fputsln(_(" -n, --new          assign a new core scheduling cookie to an existing PID or\n"
> +		  "                      execute a program with a new cookie."),
>  		stdout);
> -	fputsln(_(" -n, --new <PID>         assign a new core scheduling cookie to PID"),
> +	fputsln(_(" -c, --copy         copy the core scheduling cookie from an existing PID to\n"
> +		  "                      either another PID, or copy it to a new program"),
>  		stdout);
> -	fputsln(_(" -c, --copy              copy the core scheduling cookie from PID to\n"
> -		  "                           another PID, requires the --source and --dest option"),
> +	fputsln(_("\n If no function is provided, it will retrieve and print the cookie from\n"
> +		  "   the PID provided via --pid.\n"),
>  		stdout);
>  
>  	fputs(USAGE_OPTIONS, stdout);
> -	fputsln(_(" -s, --source <PID>      where to copy the core scheduling cookie from."),
> -		stdout);
> -	fputsln(_(" -d, --dest <PID>        where to copy the core scheduling cookie to."),
> +	fputsln(_(" -p, --pid <PID>    operate on an existing PID"), stdout);
> +	fputsln(_(" -d, --dest <PID>   when copying a cookie from an existing PID, --dest is\n"
> +		  "                      the destination PID where to copy the cookie to."),
>  		stdout);
> -	fputsln(_(" -t, --type              type of the destination PID, or the type of\n"
> -		  "                           the PID when a new core scheduling cookie\n"
> -		  "                           is created. Can be one of the following:\n"
> -		  "                           pid, tgid or pgid. Defaults to tgid."),
> +	fputsln(_(" -t, --type <TYPE>  type of the destination PID, or the type of the PID\n"
> +		  "                      when a new core scheduling cookie is created.\n"
> +		  "                      Can be one of the following: pid, tgid or pgid.\n"
> +		  "                      The default is tgid."),
>  		stdout);
>  	fputs(USAGE_SEPARATOR, stdout);
>  	fprintf(stdout,
>  		USAGE_HELP_OPTIONS(
> -			25)); /* char offset to align option descriptions */
> +			20)); /* char offset to align option descriptions */
>  	fprintf(stdout, USAGE_MAN_TAIL("coresched(1)"));
>  	exit(EXIT_SUCCESS);
>  }
>  
> -bool verify_arguments(struct args *args)
> -{
> -	// Check if the value of args->cmd is a power of 2
> -	// In that case, only a single function option was set.
> -	if (args->cmd & (args->cmd - 1)) {
> -		errx(EINVAL,
> -		     "Cannot do more than one function at a time. See %s --help",
> -		     program_invocation_short_name);
> -	}
> -
> -	switch (args->cmd) {
> -	case SCHED_CORE_CMD_GET:
> -		if (args->to_pid) {
> -			errx(EINVAL,
> -			     "Cannot use -d/--dest with this -g/--get. See %s --help",
> -			     program_invocation_short_name);
> -		}
> -		break;
> -	case SCHED_CORE_CMD_CREATE:
> -		if (args->from_pid) {
> -			errx(EINVAL,
> -			     "Cannot use -s/--source with this -n/--new. See %s --help",
> -			     program_invocation_short_name);
> -		}
> -		break;
> -	case SCHED_CORE_CMD_COPY:
> -		if (!args->from_pid) {
> -			errx(EINVAL,
> -			     "-s/--source PID is required when copying");
> -		}
> -		if (!args->to_pid) {
> -			errx(EINVAL, "-d/--dest PID is required when copying");
> -		}
> -		break;
> -	case SCHED_CORE_CMD_EXEC:
> -		if (args->to_pid) {
> -			errx(EINVAL,
> -			     "Cannot use -d/--dest when spawning a program. See %s --help",
> -			     program_invocation_short_name);
> -		}
> -		break;
> -	}
> -	return true;
> -}
> -
> -void set_pid_or_err(pid_t *dest, pid_t src, const char *err_msg)
> -{
> -	if (*dest) {
> -		errx(EINVAL, "Ambigious usage: %s", err_msg);
> -	} else {
> -		*dest = src;
> -	}
> -}
> -
> -static const char *ERR_MSG_MULTIPLE_SOURCE_PIDS =
> -	"Multiple source PIDs defined";
>  void parse_arguments(int argc, char **argv, struct args *args)
>  {
>  	int c;
> -	pid_t tmp;
>  
>  	static const struct option longopts[] = {
> -		{ "get", required_argument, NULL, 'g' },
> -		{ "new", required_argument, NULL, 'n' },
> +		{ "new", no_argument, NULL, 'n' },
>  		{ "copy", no_argument, NULL, 'c' },
> -		{ "source", required_argument, NULL, 's' },
> -		{ "destination", required_argument, NULL, 'd' },
> +		{ "pid", required_argument, NULL, 'p' },
> +		{ "dest", required_argument, NULL, 'd' },
>  		{ "type", required_argument, NULL, 't' },
>  		{ "version", no_argument, NULL, 'V' },
>  		{ "help", no_argument, NULL, 'h' },
>  		{ NULL, 0, NULL, 0 }
>  	};
> +	static const ul_excl_t excl[] = {
> +		{ 'c', 'n' }, // Cannot do both --new and --copy
> +		{ 'd', 'n' }, // Cannot have both --new and --dest
> +		{ 0 }
> +	};
>  
> -	while ((c = getopt_long(argc, argv, "g:n:cs:d:t:Vh", longopts, NULL)) !=
> -	       -1)
> +	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
> +
> +	while ((c = getopt_long(argc, argv, "ncp:d:t:Vh", longopts, NULL)) !=
> +	       -1) {
> +		err_exclusive_options(c, longopts, excl, excl_st);
>  		switch (c) {
> -		case 'g':
> -			args->cmd |= SCHED_CORE_CMD_GET;
> -			tmp = strtopid_or_err(
> -				optarg, "Failed to parse PID for -g/--get");
> -			set_pid_or_err(&args->from_pid, tmp,
> -				       ERR_MSG_MULTIPLE_SOURCE_PIDS);
> -			break;
>  		case 'n':
> -			args->cmd |= SCHED_CORE_CMD_CREATE;
> -			tmp = strtopid_or_err(
> -				optarg, "Failed to parse PID for -n/--new");
> -			set_pid_or_err(&args->to_pid, tmp,
> -				       ERR_MSG_MULTIPLE_SOURCE_PIDS);
> +			args->cmd = SCHED_CORE_CMD_NEW;
>  			break;
>  		case 'c':
> -			args->cmd |= SCHED_CORE_CMD_COPY;
> +			args->cmd = SCHED_CORE_CMD_COPY;
>  			break;
> -		case 's':
> -			tmp = strtopid_or_err(
> -				optarg, "Failed to parse PID for -s/--source");
> -			set_pid_or_err(&args->from_pid, tmp,
> -				       ERR_MSG_MULTIPLE_SOURCE_PIDS);
> +		case 'p':
> +			args->pid = strtopid_or_err(
> +				optarg, "Failed to parse PID for -p/--pid");
>  			break;
>  		case 'd':
> -			tmp = strtopid_or_err(
> +			args->dest = strtopid_or_err(
>  				optarg, "Failed to parse PID for -d/--dest");
> -			set_pid_or_err(&args->to_pid, tmp,
> -				       "Multiple destination PIDs defined");
>  			break;
>  		case 't':
>  			args->type = parse_core_sched_type(optarg);
> @@ -294,57 +263,98 @@ void parse_arguments(int argc, char **argv, struct args *args)
>  		default:
>  			errtryhelp(EXIT_FAILURE);
>  		}
> +	}
>  
> +	if (args->cmd == SCHED_CORE_CMD_COPY && !args->pid) {
> +		bad_usage("--copy: requires a -p/--pid");
> +	}
> +
> +	// More arguments have been passed, which means that the user wants to run
> +	// another program with a core scheduling cookie.
>  	if (argc > optind) {
> -		if (args->cmd == SCHED_CORE_CMD_EXEC) {
> -			args->exec_argv_offset = optind;
> -		} else {
> -			// -g, -n or -c AND a program to run is provided
> -			errx(EINVAL, "bad usage, see %s --help",
> -			     program_invocation_short_name);
> +		switch (args->cmd) {
> +		case SCHED_CORE_CMD_GET:
> +			bad_usage("Unknown command");
> +			break;
> +		case SCHED_CORE_CMD_NEW:
> +			if (args->pid) {
> +				bad_usage(
> +					"--new: cannot accept both a -p/--pid and a command");
> +			} else {
> +				args->exec_argv_offset = optind;
> +			}
> +			break;
> +		case SCHED_CORE_CMD_COPY:
> +			if (args->dest) {
> +				bad_usage(
> +					"--copy: cannot accept both a destination PID "
> +					"-d/--dest and a command")
> +			} else {
> +				args->exec_argv_offset = optind;
> +			}
> +			break;
>  		}
> -	} else if (argc == optind && args->from_pid) {
> -		// Neither a function (-g, -n, or -c), nor a program to
> -		// run is given
> -		args->cmd = SCHED_CORE_CMD_GET;
>  	}
>  
> -	verify_arguments(args);
> +	if (argc <= optind) {
> +		if (args->cmd == SCHED_CORE_CMD_NEW && !args->pid) {
> +			bad_usage(
> +				"--new: requires either a -p/--pid or a command");
> +		}
> +		if (args->cmd == SCHED_CORE_CMD_COPY && !args->dest) {
> +			bad_usage(
> +				"--copy: requires either a -d/--dest or a command");
> +		}
> +	}
>  }
>  
>  int main(int argc, char **argv)
>  {
> -	struct args arguments = { 0 };
> -	arguments.type = PR_SCHED_CORE_SCOPE_THREAD_GROUP;
> +	struct args args = { 0 };
> +	args.cmd = SCHED_CORE_CMD_GET;
> +	args.type = PR_SCHED_CORE_SCOPE_THREAD_GROUP;
>  
>  	setlocale(LC_ALL, "");
>  	bindtextdomain(PACKAGE, LOCALEDIR);
>  	textdomain(PACKAGE);
>  	close_stdout_atexit();
>  
> -	parse_arguments(argc, argv, &arguments);
> +	parse_arguments(argc, argv, &args);
> +
> +	cookie_t cookie = 0;
>  
> -	unsigned long cookie = 0;
> -	switch (arguments.cmd) {
> +	switch (args.cmd) {
>  	case SCHED_CORE_CMD_GET:
> -		cookie = core_sched_get_cookie(&arguments);
> -		if (cookie) {
> -			printf("core scheduling cookie of pid %d is 0x%lx\n",
> -			       arguments.from_pid, cookie);
> +		if (args.pid) {
> +			cookie = core_sched_get_cookie(args.pid);
> +			if (cookie) {
> +				printf("%s: cookie of pid %d is 0x%lx\n",
> +				       program_invocation_short_name, args.pid,
> +				       cookie);
> +			} else {
> +				errx(ENODATA,
> +				     "pid %d doesn't have a core scheduling cookie",
> +				     args.pid);
> +			}
>  		} else {
> -			printf("pid %d doesn't have a core scheduling cookie\n",
> -			       arguments.from_pid);
> -			exit(1);
> +			usage();
> +			exit(0);
>  		}
>  		break;
> -	case SCHED_CORE_CMD_CREATE:
> -		core_sched_create_cookie(&arguments);
> +	case SCHED_CORE_CMD_NEW:
> +		if (args.pid) {
> +			core_sched_create_cookie(args.pid, args.type);
> +			core_sched_get_and_print_cookie(args.pid);
> +		} else {
> +			core_sched_exec_with_cookie(&args, argv);
> +		}
>  		break;
>  	case SCHED_CORE_CMD_COPY:
> -		core_sched_copy_cookie(&arguments);
> -		break;
> -	case SCHED_CORE_CMD_EXEC:
> -		core_sched_exec_with_cookie(&arguments, argv);
> +		if (args.dest) {
> +			core_sched_copy_cookie(args.pid, args.dest, args.type);
> +		} else {
> +			core_sched_exec_with_cookie(&args, argv);
> +		}
>  		break;
>  	default:
>  		usage();
> -- 
> 2.44.0
> 

-- 





[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux