Skip to contentSkip to conversation

Process pinning

PATCH In review Nick Pollitt 5 participants 5 messages Apr 10, 2001 – Apr 18, 2001

lore
Share & tools
lore
#0 lore raw

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
diff -X /home/npollitt/dontdiff -Nur 243-ac3/linux/fs/proc/array.c mine/linux/fs/proc/array.c
@@ -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
diff -X /home/npollitt/dontdiff -Nur 243-ac3/linux/include/linux/prctl.h mine/linux/include/linux/prctl.h
@@ -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
diff -X /home/npollitt/dontdiff -Nur 243-ac3/linux/kernel/sched.c mine/linux/kernel/sched.c
@@ -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");
}
#1 lore raw

In message <[email protected]> you write:

Quoted 1 line

Changes to array.c expose cpus_allowed in 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

#2 lore raw
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.

#3 lore raw
In reply to Rusty Russell
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_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.

http://www.uow.edu.au/~andrewm/linux/cpus_allowed.patch

#4 lore raw
In reply to Nick Pollitt
Quoted 1 line · Nick Pollitt

Changes to array.c expose cpus_allowed in 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.