[PATCH] Binding processes to selected CPUs

Avi Kivity (avik@altavista.net)
Sun, 03 Oct 1999 21:41:30 +0200


This patch, against 2.3.18ac8, allows a process to specify which CPUs it
may execute on. It provides functionality similar to NT's ``thread
affinity''.

(Not subscribed)

diff -ur linux-2.3.18ac8/include/linux/prctl.h
linux-2.3.18ac8-cpubind/include/linux/prctl.h
--- linux-2.3.18ac8/include/linux/prctl.h Sun Oct 3 20:59:05 1999
+++ linux-2.3.18ac8-cpubind/include/linux/prctl.h Wed Sep 29
21:25:14 1999
@@ -10,4 +10,10 @@
#define PR_GET_DUMPABLE 3
#define PR_SET_DUMPABLE 4

+/* Get/set CPU binding. The CPU binding is an (unsigned) bitmask
specifying
+ * which CPUs may run this process (i.e. ~0 == all, 0x5 == processors 0
and 2).
+ */
+#define PR_GET_CPUBINDING 5 /* Second arg is pointer to return bitmask
*/
+#define PR_SET_CPUBINDING 6 /* Second arg is cpu binding bitmask */
+
#endif /* _LINUX_PRCTL_H */
diff -ur linux-2.3.18ac8/include/linux/sched.h
linux-2.3.18ac8-cpubind/include/linux/sched.h
--- linux-2.3.18ac8/include/linux/sched.h Sun Oct 3 20:59:05 1999
+++ linux-2.3.18ac8-cpubind/include/linux/sched.h Wed Sep 29
20:17:18 1999
@@ -277,6 +277,7 @@
long priority;
cycles_t avg_slice;
/* SMP and runqueue state */
+ unsigned boundcpus;
int has_cpu;
int processor;
int last_processor;
@@ -391,7 +392,7 @@
#define INIT_TASK(name) \
/* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
/* counter */ DEF_PRIORITY,DEF_PRIORITY,0, \
-/* SMP */ 0,0,0,-1, \
+/* SMP */ ~0,0,0,0,-1, \
/* schedlink */ &init_task,&init_task,
LIST_HEAD_INIT(init_task.run_list), \
/* binfmt */ NULL, \
/* ec,brk... */ 0,0,0,0,0,0, \
diff -ur linux-2.3.18ac8/kernel/sched.c
linux-2.3.18ac8-cpubind/kernel/sched.c
--- linux-2.3.18ac8/kernel/sched.c Sun Oct 3 20:59:05 1999
+++ linux-2.3.18ac8-cpubind/kernel/sched.c Sun Oct 3 21:13:49 1999
@@ -141,6 +141,16 @@

void scheduling_functions_start_here(void) { }

+/* returns true iff a task is allowed to run on a particular cpu */
+static inline int bindable(struct task_struct *p, int cpu)
+{
+#ifndef __SMP__
+ return 1;
+#else
+ return p->boundcpus & (1 << cpu);
+#endif
+}
+
/*
* This is the function that decides how desirable a process is..
* You can weigh different processes against each other depending
@@ -158,6 +168,14 @@
static inline int goodness(struct task_struct * p, int this_cpu, struct
mm_struct *this_mm)
{
int weight;
+
+ /*
+ * If the process may not be bound to this_cpu, exit.
+ */
+ if (!bindable(p, this_cpu)) {
+ weight = -1000;
+ goto out;
+ }

/*
* Realtime process, select the first one on the
@@ -176,7 +194,16 @@
* Don't do any other calculations if the time slice is
* over..
*/
+
weight = p->counter;
+
+#ifdef __SMP__
+ /* Bonus if switching from an unbindable cpu. Should happen */
+ /* at most once per rebinding. */
+ if (p->has_cpu && !bindable(p, p->processor))
+ weight += PROC_CHANGE_PENALTY;
+#endif
+
if (!weight)
goto out;

@@ -239,14 +266,14 @@
*/
best_cpu = p->processor;
target_tsk = idle_task(best_cpu);
- if (cpu_curr(best_cpu) == target_tsk)
+ if (cpu_curr(best_cpu) == target_tsk && bindable(p, best_cpu))
goto send_now;

target_tsk = NULL;
for (i = 0; i < smp_num_cpus; i++) {
cpu = cpu_logical_map(i);
tsk = cpu_curr(cpu);
- if (tsk == idle_task(cpu))
+ if (tsk == idle_task(cpu) && bindable(p, cpu))
target_tsk = tsk;
}

@@ -740,7 +767,8 @@

still_running:
c = prev_goodness(prev, this_cpu, prev->active_mm);
- next = prev;
+ if (c > -1000)
+ next = prev;
goto still_running_back;

handle_bh:
diff -ur linux-2.3.18ac8/kernel/sys.c
linux-2.3.18ac8-cpubind/kernel/sys.c
--- linux-2.3.18ac8/kernel/sys.c Sun Oct 3 20:59:05 1999
+++ linux-2.3.18ac8-cpubind/kernel/sys.c Sun Oct 3 20:52:26 1999
@@ -1007,6 +1007,17 @@
break;
}
current->dumpable = arg2;
+ break;
+ case PR_SET_CPUBINDING:
+ if (!(arg2 & ((1 << smp_num_cpus) - 1))) {
+ error = -EINVAL;
+ break;
+ }
+ current->boundcpus = arg2;
+ current->counter = 0;
+ break;
+ case PR_GET_CPUBINDING:
+ error = put_user(current->boundcpus, (unsigned
*)arg2);
break;
default:
error = -EINVAL;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/