On Fri, 9 Dec 2005, Paul H. Hargrove wrote:
If one looks though enough kernel versions,
In the meantime, I've gotten a copy of kernel/sched.c from a SGI Prism
kernel - I assume that it is the same used on Altix; this one has in
the Makefile EXTRAVERSION = -sgi306rp31. So again, all prototypes of
the sys_sched_setaffinity function that I've seen so far have 3
args... which means that no compiler tricks are needed to keep 3
different copies of the function.
one finds that some of them differ in what they will accept for the
len.
OK, so this is a different problem...
Some produce EINVAL if len!=sizeof(long),
I beg to disagree. All the codes that I looked at test for
len < sizeof(new_mask)
and copy user data based on the size of new_mask, so if "len" is
larger than sizeof(new_mask), no error occurs.
others (especially Altix) produce EINVAL if len is too short to
cover all the machine's CPUs.
...so IMHO this test should be used instead to separate a long from a
(larger) cpumask_t.
In the message that described your implementation you also wrote:
while on other kernels I find that a too-short mask is padded w/
zeros and no error results. So, we want a big value for len
Indeed some (more recent) kernels pad with zeros if "len" is too
short. But a "big value for len" is again wrong.
I can see 4 cases, again by looking at the kernel code and not dealing
with 2 vs. 3 args:
1. tests for len < sizeof(long) and copies only sizeof(len) if larger
(backported 2.4 in RHEL3); this can be identified by passing "len"
smaller than sizeof(long) which returns -EINVAL and then passing "len"
of (or larger than) sizeof(long) which should not return error.
2. tests for len < sizeof(cpumask_t) and copies only sizeof(len) if
larger (backported 2.4 from SGI, 2.6.3 from Mandrake 10.0); this can
be identified by passing "len" shorter than sizeof(cpumask_t) which
returns -EINVAL and then passing "len" of (or larger than)
sizeof(cpu_size_t) which should not return error.
3. tests for len < sizeof(cpumask_t) and pads with zeros if true,
otherwise copies only sizeof(cpumask_t) (2.6.9 in RHEL4 and 2.6.14).
This can't really be identified as it doesn't return -EINVAL in any
situation.
As you can see your suggestion to set "big value for len" would
successfully pass _all_ of the above conditions and would therefore
not offer any separation between the cases.
The stuff above applies to the _set function; the _get function is a
bit different:
1. tests for len < sizeof(long) and returns -EINVAL if true.
(backported 2.4 in RHEL3). This can be identified by passing "len"
smaller than sizeof(long) which returns -EINVAL and then passing "len"
of (or larger than) sizeof(long) which should not return error.
2. tests for len < sizeof(cpumask_t) and returns -EINVAL if true.
(backported 2.4 from SGI, 2.6.3 from Mandraks 10.0, 2.6.9 from RHEL4,
2.6.14). This can be identified by passing "len" smaller than
sizeof(cpumask_t) which returns -EINVAL and then passing "len" of (or
larger than) sizeof(cpumask_t) which should not return error.
Case 1. of _set is associated to case 1. of _get.
Cases 2. and 3. of _set are both associated to case 2. of _get.
So IMHO the test should be made with the _get function (as explained
in a previous message), by setting len=sizeof(long) which would allow
the case 1. to work fine, while case 2. would return -EINVAL, exactly
opposite from the code that you proposed.
--
Bogdan Costescu
IWR - Interdisziplinaeres Zentrum fuer Wissenschaftliches Rechnen
Universitaet Heidelberg, INF 368, D-69120 Heidelberg, GERMANY
Telephone: +49 6221 54 8869, Telefax: +49 6221 54 8868
E-mail: bogdan.coste...@iwr.uni-heidelberg.de