Process pinning
PATCH 1/1 Process pinning
This patch applies cleanly to 2.4.3-ac3.
Changes to array.c expose cpus_allowed in proc/pid/stat.
PR_GET_RUNON and PR_SET_RUNON were done by Ingo and Dimitris. Added MUSTRUN_PID and RUNANY_PID.
Also attached is runon and it's manpage.
Nick
linux/fs/proc/array.c +3 -2
@@ -343,7 +343,7 @@read_unlock (&tasklist_lock); res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \ -%lu %lu %lu %lu %lu %lu %lu %lu %d %d\n", +%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu\n", task->pid, task->comm, state,
@@ -386,7 +386,8 @@ task->nswap, task->cnswap, task->exit_signal, - task->processor); + task->processor, + task->cpus_allowed);if (mm)mmput (mm);return res;
linux/include/linux/prctl.h +5 -0
@@ -20,4 +20,9 @@#define PR_GET_KEEPCAPS 7#define PR_SET_KEEPCAPS 8 +#define PR_GET_RUNON 9 +#define PR_SET_RUNON 10 +#define PR_MUSTRUN_PID 11 +#define PR_RUNANY_PID 12 +#endif /* _LINUX_PRCTL_H */
linux/kernel/sched.c +6 -1
@@ -112,6 +112,10 @@#ifdef CONFIG_SMP #define idle_task (cpu) (init_tasks[cpu_number_map(cpu)]) +#define can_schedule_goodness (p,cpu) ( (!(p)->has_cpu || \ + p->processor == cpu) && \ + ((p)->cpus_allowed & (1 << cpu))) +#define can_schedule (p,cpu) ((!(p)->has_cpu) && \ ((p)->cpus_allowed & (1 << cpu)))
@@ -119,6 +123,7 @@#define idle_task (cpu) (&init_task)#define can_schedule (p,cpu) (1) +#define can_schedule_goodness (p,cpu) (1)#endif
@@ -594,7 +599,7 @@ still_running_back:list_for_each (tmp, &runqueue_head) { p = list_entry(tmp, struct task_struct, run_list); -if (can_schedule (p, this_cpu)) { +if (can_schedule_goodness (p, this_cpu)) {int weight =goodness (p, this_cpu, prev->active_mm);if (weight > c) c = weight, next = p;
linux/kernel/sys.c +83 -0
95 lines not on this page · raw message
/*
* runon.c - assign a process to a named processor
*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <stdio.h>
#include <unistd.h>
#include <linux/prctl.h>
#define _POSIX_OPTION_ORDER
static void usage();
int main(argc, argv)
int argc;
char *argv[];
{
extern errno;
extern __const char *__const sys_errlist[];
int c, processor, pid;
int usepid = 0;
register char *p;
if (argc < 3) {
usage();
exit(1);
}
while ((c = getopt (argc, argv, "p:")) != -1) {
switch(c) {
case 'p':
usepid = 1;
pid = atoi(optarg);
break;
}
}
p = argv[optind];
while(*p) {
if(!isdigit(*p)) {
fprintf(stderr, "%s: cpu argument must be numeric.\n", argv[0]);
exit(2);
}
p++;
}
processor = atoi(&argv[optind][0]);
optind++;
if (usepid) {
if (prctl(PR_MUSTRUN_PID, processor, pid, 0, 0) < 0) {
fprintf(stderr, "%s: could not attach pid %d to processor %d\n",
argv[0], pid, processor);
exit(1);
}
}
else {
if (prctl(PR_SET_RUNON, processor, 0, 0, 0) < 0) {
fprintf(stderr,
"%s: could not attach to processor %d -- %s\n ",
argv[0], processor, sys_errlist[errno]);
exit(1);
}
execvp(argv[optind], &argv[optind]);
fprintf(stderr, "%s: %s\n", sys_errlist[errno], argv[optind]);
exit(1);
}
return(0);
}static void usage() {
fprintf(stderr, "usage: runon processor (-p pid | command [args...])\n");
}In message <[email protected]> you write:
Quoted 1 line
Changes to
array.cexposecpus_allowedin proc/pid/stat.
Call me old fashioned, but I prefer my bitmasks in hex.
Please also consider changing:
still_running:
c = goodness(prev, this_cpu, prev->active_mm); next = prev;
to:
still_running:
if (prev & (1 << this_cpu)) {
c = goodness(prev, this_cpu, prev->active_mm);
next = prev;
}Otherwise, you will keep scheduling a RT process forever on a disallowed CPU on which it is already running. And even a non-RT process will stick on its disallowed CPU as long as nothing else runs there.
Learnt this the hard way from the hotplug CPU patch... Rusty.
--
Premature optmztion is rt of all evl. --DK
Quoted 3 lines
disallowed CPU on which it is already running. And even a non-RT process will stick on its disallowed CPU as long as nothing else runs there.
are we going to keep the cpus_allowed API? If we want the (IMHO) more flexible sysmp() API - I'll finish the 2.4 port. If we are going to keep cpus_allowed - I'll just abandon pset and sysmp.
Personally, I like sysmp() and the pset tools better, perhaps with a /proc extension to it.
Quoted 11 lines · Tim Hockin
Quoted 4 lines
disallowed CPU on which it is already running. And even a non-RT process will stick on its disallowed CPU as long as nothing else runs there.
are we going to keep the
cpus_allowedAPI? If we want the (IMHO) more flexiblesysmp()API - I'll finish the 2.4 port. If we are going to keepcpus_allowed- I'll just abandon pset and sysmp.Personally, I like
sysmp()and the pset tools better, perhaps with a /proc extension to it.
Quoted 1 line · Nick Pollitt
Changes to
array.cexposecpus_allowedin proc/pid/stat.
...
Quoted 2 lines
-%lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu\n",
...
linux/fs/proc/array.c line 390
Quoted 3 lines
linux/fs/proc/array.c +2
-1- task->processor); + task->processor, + task->cpus_allowed);
This isn't good. While it might be reasonable to have an 8*sizeof(long) processor limit in the kernel, it is not OK to expose this in the API. The API's limit should be insanely high, like 256 or more.