chrt: add control struct

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2016-01-19 14:24:53 +01:00
parent 4ec6062678
commit 7a4ea5664e
1 changed files with 45 additions and 39 deletions

View File

@ -52,6 +52,16 @@
#define SCHED_RESET_ON_FORK 0x40000000 #define SCHED_RESET_ON_FORK 0x40000000
#endif #endif
/* control struct */
struct chrt_ctl {
pid_t pid;
int policy; /* SCHED_* */
int priority;
unsigned int all_tasks : 1, /* all threads of the PID */
reset_on_fork : 1, /* SCHED_RESET_ON_FORK */
verbose : 1; /* verbose output */
};
static void __attribute__((__noreturn__)) show_usage(int rc) static void __attribute__((__noreturn__)) show_usage(int rc)
{ {
@ -197,10 +207,9 @@ static void show_min_max(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, policy = SCHED_RR, priority = 0, verbose = 0, policy_flag = 0, struct chrt_ctl _ctl = { .pid = -1 }, *ctl = &_ctl;
all_tasks = 0;
struct sched_param sp; struct sched_param sp;
pid_t pid = -1; int i;
static const struct option longopts[] = { static const struct option longopts[] = {
{ "all-tasks", 0, NULL, 'a' }, { "all-tasks", 0, NULL, 'a' },
@ -229,41 +238,39 @@ int main(int argc, char **argv)
switch (i) { switch (i) {
case 'a': case 'a':
all_tasks = 1; ctl->all_tasks = 1;
break; break;
case 'b': case 'b':
#ifdef SCHED_BATCH #ifdef SCHED_BATCH
policy = SCHED_BATCH; ctl->policy = SCHED_BATCH;
#endif #endif
break; break;
case 'f': case 'f':
policy = SCHED_FIFO; ctl->policy = SCHED_FIFO;
break; break;
case 'R': case 'R':
#ifdef SCHED_RESET_ON_FORK ctl->reset_on_fork = 1;
policy_flag |= SCHED_RESET_ON_FORK;
#endif
break; break;
case 'i': case 'i':
#ifdef SCHED_IDLE #ifdef SCHED_IDLE
policy = SCHED_IDLE; ctl->policy = SCHED_IDLE;
#endif #endif
break; break;
case 'm': case 'm':
show_min_max(); show_min_max();
return EXIT_SUCCESS; return EXIT_SUCCESS;
case 'o': case 'o':
policy = SCHED_OTHER; ctl->policy = SCHED_OTHER;
break; break;
case 'p': case 'p':
errno = 0; errno = 0;
pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument")); ctl->pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument"));
break; break;
case 'r': case 'r':
policy = SCHED_RR; ctl->policy = SCHED_RR;
break; break;
case 'v': case 'v':
verbose = 1; ctl->verbose = 1;
break; break;
case 'V': case 'V':
printf(UTIL_LINUX_VERSION); printf(UTIL_LINUX_VERSION);
@ -276,14 +283,14 @@ int main(int argc, char **argv)
} }
} }
if (((pid > -1) && argc - optind < 1) || if (((ctl->pid > -1) && argc - optind < 1) ||
((pid == -1) && argc - optind < 2)) ((ctl->pid == -1) && argc - optind < 2))
show_usage(EXIT_FAILURE); show_usage(EXIT_FAILURE);
if ((pid > -1) && (verbose || argc - optind == 1)) { if ((ctl->pid > -1) && (ctl->verbose || argc - optind == 1)) {
if (all_tasks) { if (ctl->all_tasks) {
pid_t tid; pid_t tid;
struct proc_tasks *ts = proc_open_tasks(pid); struct proc_tasks *ts = proc_open_tasks(ctl->pid);
if (!ts) if (!ts)
err(EXIT_FAILURE, _("cannot obtain the list of tasks")); err(EXIT_FAILURE, _("cannot obtain the list of tasks"));
@ -291,46 +298,45 @@ int main(int argc, char **argv)
show_rt_info(tid, FALSE); show_rt_info(tid, FALSE);
proc_close_tasks(ts); proc_close_tasks(ts);
} else } else
show_rt_info(pid, FALSE); show_rt_info(ctl->pid, FALSE);
if (argc - optind == 1) if (argc - optind == 1)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
errno = 0; errno = 0;
priority = strtos32_or_err(argv[optind], _("invalid priority argument")); ctl->priority = strtos32_or_err(argv[optind], _("invalid priority argument"));
#ifdef SCHED_RESET_ON_FORK #ifdef SCHED_RESET_ON_FORK
/* sanity check */ if (ctl->reset_on_fork) {
if ((policy_flag & SCHED_RESET_ON_FORK) && if (ctl->policy != SCHED_FIFO && ctl->policy != SCHED_RR)
!(policy == SCHED_FIFO || policy == SCHED_RR))
errx(EXIT_FAILURE, _("SCHED_RESET_ON_FORK flag is supported for " errx(EXIT_FAILURE, _("SCHED_RESET_ON_FORK flag is supported for "
"SCHED_FIFO and SCHED_RR policies only")); "SCHED_FIFO and SCHED_RR policies only"));
ctl->policy |= SCHED_RESET_ON_FORK;
}
#endif #endif
policy |= policy_flag; if (ctl->pid == -1)
ctl->pid = 0;
sp.sched_priority = ctl->priority;
if (pid == -1) if (ctl->all_tasks) {
pid = 0;
sp.sched_priority = priority;
if (all_tasks) {
pid_t tid; pid_t tid;
struct proc_tasks *ts = proc_open_tasks(pid); struct proc_tasks *ts = proc_open_tasks(ctl->pid);
if (!ts) if (!ts)
err(EXIT_FAILURE, _("cannot obtain the list of tasks")); err(EXIT_FAILURE, _("cannot obtain the list of tasks"));
while (!proc_next_tid(ts, &tid)) while (!proc_next_tid(ts, &tid))
if (sched_setscheduler(tid, policy, &sp) == -1) if (sched_setscheduler(tid, ctl->policy, &sp) == -1)
err(EXIT_FAILURE, _("failed to set tid %d's policy"), tid); err(EXIT_FAILURE, _("failed to set tid %d's policy"), tid);
proc_close_tasks(ts); proc_close_tasks(ts);
} else if (sched_setscheduler(pid, policy, &sp) == -1) } else if (sched_setscheduler(ctl->pid, ctl->policy, &sp) == -1)
err(EXIT_FAILURE, _("failed to set pid %d's policy"), pid); err(EXIT_FAILURE, _("failed to set pid %d's policy"), ctl->pid);
if (verbose) if (ctl->verbose)
show_rt_info(pid, TRUE); show_rt_info(ctl->pid, TRUE);
if (!pid) { if (!ctl->pid) {
argv += optind + 1; argv += optind + 1;
execvp(argv[0], argv); execvp(argv[0], argv);
err(EXIT_FAILURE, _("failed to execute %s"), argv[0]); err(EXIT_FAILURE, _("failed to execute %s"), argv[0]);