From e4404b6e02b1d17b2ba8d1afa2c79b25cb24dac7 Mon Sep 17 00:00:00 2001 From: "g@localhost.localdomain" Date: Tue, 22 May 2007 22:28:57 +0200 Subject: [PATCH] Allow changing the scheduling policy and its priority --- NEWS | 1 + cmdline.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmdline.h | 8 +++++++ untie.8 | 6 +++++ untie.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ untie.ggo | 2 ++ 6 files changed, 163 insertions(+) diff --git a/NEWS b/NEWS index bc26fba..9be084a 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ o Add the possibility to run a program as a daemon o Add the setting of an alarm timer o Add nice level setting +o Allow changing the scheduling policy and its priority 0.2 diff --git a/cmdline.c b/cmdline.c index 2b684ca..5004de8 100644 --- a/cmdline.c +++ b/cmdline.c @@ -42,6 +42,8 @@ const char *gengetopt_args_info_help[] = { " --daemonize Run as daemon (default=off)", " --alarm=SECONDS Set an alarm after the specified delay", " --nice=NICE Run as the specified nice level", + " --sched=SCHED Use the specified (possibly RT) scheduling policy", + " --schedprio=PRIO Set the priority according to the given scheduler", 0 }; @@ -90,6 +92,8 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->daemonize_given = 0 ; args_info->alarm_given = 0 ; args_info->nice_given = 0 ; + args_info->sched_given = 0 ; + args_info->schedprio_given = 0 ; } static @@ -112,6 +116,9 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->daemonize_flag = 0; args_info->alarm_orig = NULL; args_info->nice_orig = NULL; + args_info->sched_arg = NULL; + args_info->sched_orig = NULL; + args_info->schedprio_orig = NULL; } @@ -138,6 +145,8 @@ void init_args_info(struct gengetopt_args_info *args_info) args_info->daemonize_help = gengetopt_args_info_help[11] ; args_info->alarm_help = gengetopt_args_info_help[12] ; args_info->nice_help = gengetopt_args_info_help[13] ; + args_info->sched_help = gengetopt_args_info_help[14] ; + args_info->schedprio_help = gengetopt_args_info_help[15] ; } @@ -268,6 +277,21 @@ cmdline_parser_release (struct gengetopt_args_info *args_info) free (args_info->nice_orig); /* free previous argument */ args_info->nice_orig = 0; } + if (args_info->sched_arg) + { + free (args_info->sched_arg); /* free previous argument */ + args_info->sched_arg = 0; + } + if (args_info->sched_orig) + { + free (args_info->sched_orig); /* free previous argument */ + args_info->sched_orig = 0; + } + if (args_info->schedprio_orig) + { + free (args_info->schedprio_orig); /* free previous argument */ + args_info->schedprio_orig = 0; + } for (i = 0; i < args_info->inputs_num; ++i) free (args_info->inputs [i]); @@ -375,6 +399,20 @@ cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_ fprintf(outfile, "%s\n", "nice"); } } + if (args_info->sched_given) { + if (args_info->sched_orig) { + fprintf(outfile, "%s=\"%s\"\n", "sched", args_info->sched_orig); + } else { + fprintf(outfile, "%s\n", "sched"); + } + } + if (args_info->schedprio_given) { + if (args_info->schedprio_orig) { + fprintf(outfile, "%s=\"%s\"\n", "schedprio", args_info->schedprio_orig); + } else { + fprintf(outfile, "%s\n", "schedprio"); + } + } fclose (outfile); @@ -642,6 +680,8 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf { "daemonize", 0, NULL, 0 }, { "alarm", 1, NULL, 0 }, { "nice", 1, NULL, 0 }, + { "sched", 1, NULL, 0 }, + { "schedprio", 1, NULL, 0 }, { NULL, 0, NULL, 0 } }; @@ -910,6 +950,46 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf free (args_info->nice_orig); /* free previous string */ args_info->nice_orig = gengetopt_strdup (optarg); } + /* Use the specified (possibly RT) scheduling policy. */ + else if (strcmp (long_options[option_index].name, "sched") == 0) + { + if (local_args_info.sched_given) + { + fprintf (stderr, "%s: `--sched' option given more than once%s\n", argv[0], (additional_error ? additional_error : "")); + goto failure; + } + if (args_info->sched_given && ! override) + continue; + local_args_info.sched_given = 1; + args_info->sched_given = 1; + if (args_info->sched_arg) + free (args_info->sched_arg); /* free previous string */ + args_info->sched_arg = gengetopt_strdup (optarg); + if (args_info->sched_orig) + free (args_info->sched_orig); /* free previous string */ + args_info->sched_orig = gengetopt_strdup (optarg); + } + /* Set the priority according to the given scheduler. */ + else if (strcmp (long_options[option_index].name, "schedprio") == 0) + { + if (local_args_info.schedprio_given) + { + fprintf (stderr, "%s: `--schedprio' option given more than once%s\n", argv[0], (additional_error ? additional_error : "")); + goto failure; + } + if (args_info->schedprio_given && ! override) + continue; + local_args_info.schedprio_given = 1; + args_info->schedprio_given = 1; + args_info->schedprio_arg = strtol (optarg, &stop_char, 0); + if (!(stop_char && *stop_char == '\0')) { + fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg); + goto failure; + } + if (args_info->schedprio_orig) + free (args_info->schedprio_orig); /* free previous string */ + args_info->schedprio_orig = gengetopt_strdup (optarg); + } break; case '?': /* Invalid option. */ diff --git a/cmdline.h b/cmdline.h index 5ab9f5e..746e457 100644 --- a/cmdline.h +++ b/cmdline.h @@ -64,6 +64,12 @@ struct gengetopt_args_info int nice_arg; /* Run as the specified nice level. */ char * nice_orig; /* Run as the specified nice level original value given at command line. */ const char *nice_help; /* Run as the specified nice level help description. */ + char * sched_arg; /* Use the specified (possibly RT) scheduling policy. */ + char * sched_orig; /* Use the specified (possibly RT) scheduling policy original value given at command line. */ + const char *sched_help; /* Use the specified (possibly RT) scheduling policy help description. */ + int schedprio_arg; /* Set the priority according to the given scheduler. */ + char * schedprio_orig; /* Set the priority according to the given scheduler original value given at command line. */ + const char *schedprio_help; /* Set the priority according to the given scheduler help description. */ int help_given ; /* Whether help was given. */ int version_given ; /* Whether version was given. */ @@ -79,6 +85,8 @@ struct gengetopt_args_info int daemonize_given ; /* Whether daemonize was given. */ int alarm_given ; /* Whether alarm was given. */ int nice_given ; /* Whether nice was given. */ + int sched_given ; /* Whether sched was given. */ + int schedprio_given ; /* Whether schedprio was given. */ char **inputs ; /* unamed options */ unsigned inputs_num ; /* unamed options number */ diff --git a/untie.8 b/untie.8 index bfb0200..dc5facb 100644 --- a/untie.8 +++ b/untie.8 @@ -49,6 +49,12 @@ Set an alarm after the specified delay. This option uses the alarm(2) facility t .TP \fB\-\-nice=NICE\fR Run as the specified nice level. This sets the nice(1) value of the child process, levels typically range from -20 (highest priority) to 19 (lowest priority). +.TP +\fB\-\-sched=SCHED\fR +Use the specified (possibly RT) scheduling policy. Accepted values are 'rr', 'fifo', 'normal', 'other' case insensitive. The policy can also be given in numerical form. +.TP +\fB\-\-schedprio=PRIO\fR +Set the priority according to the given scheduler. This is typically used to set the priority between 1 and 100 when an RT scheduling policy is choosen. .SH "AUTHOR" Guillaume Chazarain .br diff --git a/untie.c b/untie.c index 29d8aac..ecd6e8c 100644 --- a/untie.c +++ b/untie.c @@ -273,6 +273,70 @@ static void daemonize(void) } /* + * Configure a (posssibly RT) scheduling policy + */ +static void set_scheduler(struct gengetopt_args_info *ggo) +{ + static struct { + const char *name; + int value; + } policies[] = { + /* *INDENT-OFF* */ + {"fifo", SCHED_FIFO}, + {"rr", SCHED_RR}, + {"other", SCHED_OTHER}, + {"normal", SCHED_OTHER} + /* *INDENT-ON* */ + }; + struct sched_param param; + + if (ggo->sched_given) { + int policy; + int policy_found = 0; + int i; + + for (i = 0; i < sizeof(policies) / sizeof(policies[0]); i++) + if (!strcasecmp(ggo->sched_arg, policies[i].name)) { + policy = policies[i].value; + policy_found = 1; + break; + } + + if (!policy_found) { + char *end; + policy = strtol(ggo->sched_arg, &end, 0); + if (ggo->sched_arg[0] == '\0' || end[0] != '\0') { + fprintf(stderr, + "Unknown scheduling policy: %s\n", + ggo->sched_arg); + exit(EXIT_FAILURE); + } + } + + if (ggo->schedprio_given) + param.sched_priority = ggo->schedprio_arg; + else { + param.sched_priority = sched_get_priority_min(policy); + if (param.sched_priority < 0) { + perror("sched_get_priority_min"); + exit(EXIT_FAILURE); + } + } + + if (sched_setscheduler(0, policy, ¶m) < 0) { + perror("sched_setscheduler"); + exit(EXIT_FAILURE); + } + } else if (ggo->schedprio_given) { + param.sched_priority = ggo->schedprio_arg; + if (sched_setparam(0, ¶m) < 0) { + perror("sched_setparam"); + exit(EXIT_FAILURE); + } + } +} + +/* * The new process in its own namespace can now execute the command passed as * argument or a shell */ @@ -281,6 +345,8 @@ static int child_process(void *ggo_arg) struct gengetopt_args_info *ggo = ggo_arg; struct user_info user; + set_scheduler(ggo); + if (ggo->nice_given) if (setpriority(PRIO_PROCESS, 0, ggo->nice_arg) < 0) { perror("setpriority"); diff --git a/untie.ggo b/untie.ggo index 2d94b50..c255216 100644 --- a/untie.ggo +++ b/untie.ggo @@ -12,3 +12,5 @@ option "groupname" - "Add the specified group" string typestr="GROUP" no multipl option "daemonize" - "Run as daemon" flag off option "alarm" - "Set an alarm after the specified delay" int typestr="SECONDS" no option "nice" - "Run as the specified nice level" int typestr="NICE" no +option "sched" - "Use the specified (possibly RT) scheduling policy" string typestr="SCHED" no +option "schedprio" - "Set the priority according to the given scheduler" int typestr="PRIO" no -- 2.11.4.GIT