From: Rusty Russell <rusty@rustcorp.com.au>
To: Robert Love <rml@tech9.net>
Cc: Linus Torvalds <torvalds@transmeta.com>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: latest linus-2.5 BK broken
Date: Wed, 19 Jun 2002 23:31:14 +1000 [thread overview]
Message-ID: <E17KfZg-0000Fg-00@wagner.rustcorp.com.au> (raw)
In-Reply-To: Your message of "18 Jun 2002 13:55:38 MST." <1024433739.922.236.camel@sinai>
In message <1024433739.922.236.camel@sinai> you write:
> On Tue, 2002-06-18 at 13:31, Rusty Russell wrote:
>
> > No, you have accepted a non-portable userspace interface and put it in
> > generic code. THAT is idiotic.
> >
> > So any program that doesn't use the following is broken:
>
> On top of what Linus replied, there is the issue that if your task does
> not know how many CPUs can be in the system then setting its affinity is
> worthless in 90% of the cases.
No. You can read the cpus out of /proc/cpuinfo, and say "I want to be
on <some cpu I found>" or "I want one copy for each processor", or
even "I want every processor but the one the other task just bound
to". This is 99% of actual usage.
But I can see the man page now:
The third arg to set/getaffinity is the size of a kernel data
structure. There is no way to know this size: it is dependent
on architecture and kernel configuration. You can pass a
larger datastructure and the higher bits are ignored: try
1024?
> I.e., everyone today can write code like
>
> sched_setaffinity(0, sizeof(unsigned long), &mask)
NO THEY CAN'T. How will ia64 deal with this in ia32 binaries? How
will Sparc64 deal with this in 32-bit binaries? How will PPC64 deal
with this in PPC32 binaries? How will x86_64 deal with this in x86
binaries?
They'll have to either break compatibility, or guess and fill
accordingly.
And when new CPUS come online? At the moment you effectively
zero-fill, because you can't tell what you're supposed to do here. So
you can never truly reset your affinity once it's set.
> Summarily, setting CPU affinity is something that is naturally low-level
> enough it only makes sense when you know what you are setting and not
> setting. While a mask of -1 may always make sense, random bitmaps
> (think RT stuff here) are explicit for the number of CPUs given.
You've designed an interface where the easiest thing to do is the
wrong thing (as per your example). This is the hallmark of bad
design.
*If* there had been a way to tell the bitmask size which was
introduced at the same time, it might have been acceptable. But there
isn't at the moment, so people are writing bugs right now.
Untested patch below, seems to compile (hard to tell since PPC is
v. broken right now)
Summary:
1) Easy to write portable "set this cpu" code.
2) Both system calls now handle NR_CPUS > sizeof(long)*8.
3) Things which have set affinity once can now get back on new cpus as
they come up.
4) Trivial to extent for hyperthreading on a per-arch basis.
Linus, think and apply,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
--- linux-2.5.22/include/linux/affinity.h Thu Jan 1 10:00:00 1970
+++ working-2.5.22-linus/include/linux/affinity.h Wed Jun 19 22:09:47 2002
@@ -0,0 +1,9 @@
+#ifndef _LINUX_AFFINITY_H
+#define _LINUX_AFFINITY_H
+enum {
+ /* Set affinity to these processors */
+ LINUX_AFFINITY_INCLUDE,
+ /* Set affinity to all *but* these processors */
+ LINUX_AFFINITY_EXCLUDE,
+};
+#endif
--- working-2.5.22-linus/kernel/sched.c.~1~ Tue Jun 18 23:48:03 2002
+++ working-2.5.22-linus/kernel/sched.c Wed Jun 19 23:28:32 2002
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/kernel_stat.h>
+#include <linux/affinity.h>
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
@@ -1309,25 +1310,57 @@
/**
* sys_sched_setaffinity - set the cpu affinity of a process
* @pid: pid of the process
+ * @include: is this include or exclude?
* @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to the new cpu mask
+ * @user_mask_ptr: user-space pointer to bitmask of cpus to include/exclude
*/
-asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
- unsigned long *user_mask_ptr)
+asmlinkage int sys_sched_setaffinity(pid_t pid,
+ int include,
+ unsigned int len,
+ unsigned char *user_mask_ptr)
{
- unsigned long new_mask;
+ bitmap_member(new_mask, NR_CPUS);
task_t *p;
int retval;
+ unsigned int i;
- if (len < sizeof(new_mask))
- return -EINVAL;
-
- if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+ memset(new_mask, 0x00, sizeof(new_mask));
+ if (copy_from_user(new_mask, user_mask_ptr,
+ min((size_t)len, sizeof(new_mask))))
return -EFAULT;
- new_mask &= cpu_online_map;
- if (!new_mask)
+ /* longer is OK, as long as they don't actually set any of the bits. */
+ if (len > sizeof(new_mask)) {
+ unsigned char c;
+ for (i = sizeof(new_mask); i < len; i++) {
+ if (get_user(c, user_mask_ptr+i))
+ return -EFAULT;
+ if (c != 0)
+ return -ENOENT;
+ }
+ }
+
+ /* Check for cpus that aren't online/don't exist */
+ for (i = 0; i < ARRAY_SIZE(new_mask) * i; i++) {
+ if (i >= NR_CPUS || !cpu_online(i)) {
+ if (test_bit(i, new_mask))
+ return -ENOENT;
+ }
+ }
+
+ /* Invert the mask in the exclude case. */
+ if (include == LINUX_AFFINITY_EXCLUDE) {
+ for (i = 0; i < ARRAY_SIZE(new_mask); i++)
+ new_mask[i] = ~new_mask[i];
+ } else if (include != LINUX_AFFINITY_INCLUDE) {
return -EINVAL;
+ }
+
+ /* The new mask must mention some online cpus */
+ for (i = 0; !cpu_online(i) || !test_bit(i, new_mask); i++)
+ if (i == NR_CPUS-1)
+ /* This is kinda true... */
+ return -EWOULDBLOCK;
read_lock(&tasklist_lock);
@@ -1351,7 +1384,8 @@
goto out_unlock;
retval = 0;
- set_cpus_allowed(p, new_mask);
+ /* FIXME: set_cpus_allowed should take an array... */
+ set_cpus_allowed(p, new_mask[0]);
out_unlock:
put_task_struct(p);
@@ -1363,37 +1397,27 @@
* @pid: pid of the process
* @len: length in bytes of the bitmask pointed to by user_mask_ptr
* @user_mask_ptr: user-space pointer to hold the current cpu mask
+ * Returns the size that required to hold the complete cpu mask.
*/
asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
- unsigned long *user_mask_ptr)
+ void *user_mask_ptr)
{
- unsigned long mask;
- unsigned int real_len;
+ bitmap_member(mask, NR_CPUS) = { 0 };
task_t *p;
- int retval;
-
- real_len = sizeof(mask);
-
- if (len < real_len)
- return -EINVAL;
read_lock(&tasklist_lock);
-
- retval = -ESRCH;
p = find_process_by_pid(pid);
- if (!p)
- goto out_unlock;
-
- retval = 0;
- mask = p->cpus_allowed & cpu_online_map;
-
-out_unlock:
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ return -ESRCH;
+ }
+ memcpy(mask, &p->cpus_allowed, sizeof(p->cpus_allowed));
read_unlock(&tasklist_lock);
- if (retval)
- return retval;
- if (copy_to_user(user_mask_ptr, &mask, real_len))
+
+ if (copy_to_user(user_mask_ptr, &mask,
+ min((unsigned)sizeof(p->cpus_allowed), len)))
return -EFAULT;
- return real_len;
+ return sizeof(p->cpus_allowed);
}
asmlinkage long sys_sched_yield(void)
@@ -1727,9 +1751,11 @@
migration_req_t req;
runqueue_t *rq;
+#if 0 /* This is checked for userspace, and kernel shouldn't do this */
new_mask &= cpu_online_map;
if (!new_mask)
BUG();
+#endif
preempt_disable();
rq = task_rq_lock(p, &flags);
next prev parent reply other threads:[~2002-06-19 13:44 UTC|newest]
Thread overview: 97+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-06-18 17:18 James Simmons
2002-06-18 17:46 ` Robert Love
2002-06-18 18:51 ` Rusty Russell
2002-06-18 18:43 ` Zwane Mwaikambo
2002-06-18 18:56 ` Linus Torvalds
2002-06-18 18:59 ` Robert Love
2002-06-18 20:05 ` Rusty Russell
2002-06-18 20:05 ` Linus Torvalds
2002-06-18 20:31 ` Rusty Russell
2002-06-18 20:41 ` Linus Torvalds
2002-06-18 21:12 ` Benjamin LaHaise
2002-06-18 21:08 ` Cort Dougan
2002-06-18 21:47 ` Linus Torvalds
2002-06-19 12:29 ` Eric W. Biederman
2002-06-19 17:27 ` Linus Torvalds
2002-06-20 3:57 ` Eric W. Biederman
2002-06-20 5:24 ` Larry McVoy
2002-06-20 7:26 ` Andreas Dilger
2002-06-20 14:54 ` Eric W. Biederman
2002-06-20 15:41 ` McVoy's Clusters (was Re: latest linus-2.5 BK broken) Sandy Harris
2002-06-20 17:10 ` William Lee Irwin III
2002-06-20 20:42 ` Timothy D. Witham
2002-06-21 5:16 ` Eric W. Biederman
2002-06-22 14:14 ` Kai Henningsen
2002-06-20 16:30 ` latest linus-2.5 BK broken Cort Dougan
2002-06-20 17:15 ` Linus Torvalds
2002-06-21 6:15 ` Eric W. Biederman
2002-06-21 17:50 ` Larry McVoy
2002-06-21 17:55 ` Robert Love
2002-06-21 18:09 ` Linux, the microkernel (was Re: latest linus-2.5 BK broken) Jeff Garzik
2002-06-21 18:46 ` Cort Dougan
2002-06-21 20:25 ` Daniel Phillips
2002-06-22 1:07 ` Horst von Brand
2002-06-22 1:23 ` Larry McVoy
2002-06-22 12:41 ` Roman Zippel
2002-06-23 15:15 ` Sandy Harris
2002-06-23 17:29 ` Jakob Oestergaard
2002-06-24 6:27 ` Craig I. Hagan
2002-06-24 13:06 ` J.A. Magallon
2002-06-24 10:59 ` Eric W. Biederman
2002-06-21 19:34 ` Rob Landley
2002-06-22 15:31 ` Alan Cox
2002-06-22 12:24 ` Rob Landley
2002-06-22 19:00 ` Ruth Ivimey-Cook
2002-06-22 21:09 ` jdow
2002-06-23 17:56 ` John Alvord
2002-06-23 20:48 ` jdow
2002-06-23 21:40 ` [OT] " Xavier Bestel
2002-06-22 18:25 ` latest linus-2.5 BK broken Eric W. Biederman
2002-06-22 19:26 ` Larry McVoy
2002-06-22 22:25 ` Eric W. Biederman
2002-06-22 23:10 ` Larry McVoy
2002-06-23 6:34 ` William Lee Irwin III
2002-06-23 22:56 ` Kai Henningsen
2002-06-20 17:16 ` RW Hawkins
2002-06-20 17:23 ` Cort Dougan
2002-06-20 20:40 ` Martin Dalecki
2002-06-20 20:53 ` Linus Torvalds
2002-06-20 21:27 ` Martin Dalecki
2002-06-20 21:37 ` Linus Torvalds
2002-06-20 21:59 ` Martin Dalecki
2002-06-20 22:18 ` Linus Torvalds
2002-06-20 22:41 ` Martin Dalecki
2002-06-21 0:09 ` Allen Campbell
2002-06-21 7:43 ` Zwane Mwaikambo
2002-06-21 21:02 ` Rob Landley
2002-06-22 3:57 ` (RFC)i386 arch autodetect( was Re: latest linus-2.5 BK broken ) Matthew D. Pitts
2002-06-22 4:54 ` William Lee Irwin III
2002-06-21 16:01 ` Re: latest linus-2.5 BK broken Sandy Harris
2002-06-21 20:38 ` Rob Landley
2002-06-20 21:13 ` Timothy D. Witham
2002-06-21 19:53 ` Rob Landley
2002-06-21 5:34 ` Eric W. Biederman
2002-06-19 10:21 ` Padraig Brady
2002-06-18 21:45 ` Bill Huey
2002-06-18 20:55 ` Robert Love
2002-06-19 13:31 ` Rusty Russell [this message]
2002-06-18 19:29 ` Benjamin LaHaise
2002-06-18 19:19 ` Zwane Mwaikambo
2002-06-18 19:49 ` Benjamin LaHaise
2002-06-18 19:27 ` Zwane Mwaikambo
2002-06-18 20:13 ` Rusty Russell
2002-06-18 20:21 ` Linus Torvalds
2002-06-18 22:03 ` Ingo Molnar
2002-06-18 23:38 Michael Hohnbaum
2002-06-18 23:57 ` Ingo Molnar
2002-06-19 0:08 ` Ingo Molnar
2002-06-19 1:00 ` Matthew Dobson
2002-06-19 23:48 ` Michael Hohnbaum
[not found] <E17KSLb-0007Dj-00@wagner.rustcorp.com.au>
2002-06-19 0:12 ` Linus Torvalds
2002-06-19 15:23 ` Rusty Russell
2002-06-19 16:28 ` Linus Torvalds
2002-06-19 20:57 ` Rusty Russell
2002-06-20 23:48 Miles Lane
2002-06-21 7:31 Martin Knoblauch
2002-06-21 12:59 Jesse Pollard
2002-06-24 21:28 Paul McKenney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=E17KfZg-0000Fg-00@wagner.rustcorp.com.au \
--to=rusty@rustcorp.com.au \
--cc=linux-kernel@vger.kernel.org \
--cc=rml@tech9.net \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®