Discussion:
new toy: taskset
(too old to reply)
Elie De Brauwer
2012-07-15 11:34:43 UTC
Permalink
Hello all,

In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.

I tested it (a.o.) with a yes > /dev/null and a top which shows the cpu
load per core, and then you can see yes jump around

edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x1 20941
pid 20941's current affinity mask: ff
pid 20941's new affinity mask: 1
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x2 20941
pid 20941's current affinity mask: 1
pid 20941's new affinity mask: 2
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x4 20941
pid 20941's current affinity mask: 2
pid 20941's new affinity mask: 4
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x8 20941
pid 20941's current affinity mask: 4
pid 20941's new affinity mask: 8
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x10 20941
pid 20941's current affinity mask: 8
pid 20941's new affinity mask: 10
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x20 20941
pid 20941's current affinity mask: 10
pid 20941's new affinity mask: 20
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x30 20941
pid 20941's current affinity mask: 20
pid 20941's new affinity mask: 30
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x40 20941
pid 20941's current affinity mask: 30
pid 20941's new affinity mask: 40
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x80 20941
pid 20941's current affinity mask: 40
pid 20941's new affinity mask: 80

One comment, I added sched.h into the toys.h include, but I also needed
a #define _GNU_SOURCE or I'd run into troubles because it failed to find
the CPU_SET* macro's. So this was added in taskset.c but I'm not sure if
this is the correct way to go.

my 2 cents
E.
--
Elie De Brauwer

-------------- next part --------------
A non-text attachment was scrubbed...
Name: taskset.patch
Type: text/x-patch
Size: 3691 bytes
Desc: not available
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20120715/f8dda953/attachment.bin>
Rob Landley
2012-07-18 02:06:32 UTC
Permalink
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Ok. In busybox, but not even in LSB. Huh. "other" then...
Post by Elie De Brauwer
I tested it (a.o.) with a yes > /dev/null and a top which shows the cpu
load per core, and then you can see yes jump around
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x1 20941
pid 20941's current affinity mask: ff
pid 20941's new affinity mask: 1
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x2 20941
pid 20941's current affinity mask: 1
pid 20941's new affinity mask: 2
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x4 20941
pid 20941's current affinity mask: 2
pid 20941's new affinity mask: 4
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x8 20941
pid 20941's current affinity mask: 4
pid 20941's new affinity mask: 8
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x10 20941
pid 20941's current affinity mask: 8
pid 20941's new affinity mask: 10
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x20 20941
pid 20941's current affinity mask: 10
pid 20941's new affinity mask: 20
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x30 20941
pid 20941's current affinity mask: 20
pid 20941's new affinity mask: 30
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x40 20941
pid 20941's current affinity mask: 30
pid 20941's new affinity mask: 40
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x80 20941
pid 20941's current affinity mask: 40
pid 20941's new affinity mask: 80
Cool.
Post by Elie De Brauwer
One comment, I added sched.h into the toys.h include, but I also needed
a #define _GNU_SOURCE or I'd run into troubles because it failed to find
the CPU_SET* macro's. So this was added in taskset.c but I'm not sure if
this is the correct way to go.
What an utterly horrible interface, which the glibc guys once again broke.

<rant>Hurd is a part of the gnu project. Linux is not. This is a
linux-specific system call, labeling it with "gnu" is like labeling it
"property of Sun Microsystems". They had nothing to do with it.</rant>

Your code is fine, but I'm gonna open code the darn system call anyway,
because I'm interpreting Android's "no GPL in userspace" as "No GNU is
good GNU".

Luckily, Linux system calls are binary backwards compatible forever
(modulo Documentation/feature-removal-schedule.txt), so if I just work
out what the ABI actually _is_, with appropriate word size and endianness...

Let's see, pid, size_t, and a pointer to... what? The size_t is bytes of
the blob of data the pointer points to, the problem is endianness.
(Since I don't personally have access to any machine with > 8
processors, let alone a big endian one, I kinda have to get this right
up front... or run strace on the existing code to see what it's passing
to the system call, but let's hold that in reserve...)

Digging into bits/sched.h it's treating it as an array of unsigned
longs, which on a big endian machine would be kind of disturbing. Ok,
forget what the headers are doing, what is the _kernel_ expecting?

kernel/sched/core.c:

SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long __user *, user_mask_ptr)
{
int ret;
cpumask_var_t mask;

if ((len * BITS_PER_BYTE) < nr_cpu_ids)
return -EINVAL;
if (len & (sizeof(unsigned long)-1))
return -EINVAL;

Yeah, that matches. The size is in bytes, but the kernel insists it must
be a multiple of sizeof(unsigned long). The glibc loonies of course
hardware a size of 1024. sigh: if I'm going to hardware something, I
might as well use toybuf which is already there and starts zeroed.

So it looks like:

long *blah = (long *)toybuf;
blah[cpu/sizeof(long)] |= 1<<(cpu&(sizeof(long)-1));

But that's just NUTS on a big endian system, so lemme confirm that. Dig
through the system call entry point into the kernel, the code is doing
cpumask_and() which lives in include/linux/cpumask.h and is a wrapper
around linux/bitmap.h which says I should look at lib/bitmap.c which says:

* The byte ordering of bitmaps is more natural on little
* endian architectures. See the big-endian headers
* include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
* for the best explanations of this ordering.

Except there isn't an asm-ppc64 anymore, it got merged into arch/power
(I should send a patch for that), so...

arch/powerpc/include/asm/bitops.h:

* The bitop functions are defined to work on unsigned longs, so for a
* ppc64 system the bits end up numbered:
*
|63..............0|127............64|191...........128|255...........196|
* and on ppc32:
*
|31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
*

And that's exactly what I wanted to know. So my guess at how to do it
was right, and it just plain IS a crazy layout on big endian.

*shrug* Ok.

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Rob Landley
2012-07-18 02:26:46 UTC
Permalink
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
man page:

http://linux.die.net/man/1/taskset

In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)

By the way: "taskset -p [mask] pid" is _crazy_. pid should be an
argument to -p, ala "taskset mask [-p pid | arg...].

I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...

Confused,

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-18 07:53:58 UTC
Permalink
Post by Rob Landley
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
Whatever version of util-linux linux.die.net might 've stolen the
manpage from, it for sure isn't a recent version. I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
Post by Rob Landley
http://linux.die.net/man/1/taskset
In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)
Indeed, except that if you use it with -p, the -a is not default (so it
will only look at the tid specified).
Post by Rob Landley
By the way: "taskset -p [mask] pid" is _crazy_. pid should be an
argument to -p, ala "taskset mask [-p pid | arg...].
I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...
Well, my submission matches (or at least was intended) to match

taskset [-a] mask-in-hex pid

Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
Post by Rob Landley
Confused,
Rob
--
Elie De Brauwer
Rob Landley
2012-07-19 01:41:21 UTC
Permalink
Post by Elie De Brauwer
Post by Rob Landley
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
Whatever version of util-linux linux.die.net might 've stolen the
manpage from, it for sure isn't a recent version.
I didn't mean to criticize, I'm just a bit frustrated trying to figure
out what the behavior should _be_ in the absence of a standard and with
implementations seeming to vary.

The man page I linked to matches the one on ubuntu 10.04, which is what
this netbook still has on it. (I'm being lazy about upgrading the LTS.
The new one has this horrible X11 behavior where clicks register twice a
lot of the time. They screwed up debouncing or something. _right_
clicking on things sometimes left-clicks what's underneath the mouse
cursor. Maybe it's an xfce thing, but I don't see how, and xubuntu 10.04
doesn't do it, so...)
Post by Elie De Brauwer
I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
So there's no standard for this command _and_ its changed significantly
in the past couple years. Lovely.

Ok, I happily defer to your superior knowledge in this area.
Post by Elie De Brauwer
Post by Rob Landley
http://linux.die.net/man/1/taskset
In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)
Indeed, except that if you use it with -p, the -a is not default (so it
will only look at the tid specified).
Upstream behavior is crazy, but in the absence of a standard we follow
upstream behavior. Got it.
Post by Elie De Brauwer
Post by Rob Landley
I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...
Well, my submission matches (or at least was intended) to match
taskset [-a] mask-in-hex pid
Ok.
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
Is there more to it than:

if (opt.argc>2) xexec(toys.optargs+2);

Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.

I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?

Thanks,

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-19 11:08:54 UTC
Permalink
Post by Rob Landley
I didn't mean to criticize, I'm just a bit frustrated trying to figure
out what the behavior should _be_ in the absence of a standard and with
implementations seeming to vary.
The man page I linked to matches the one on ubuntu 10.04, which is what
this netbook still has on it. (I'm being lazy about upgrading the LTS.
The new one has this horrible X11 behavior where clicks register twice a
lot of the time. They screwed up debouncing or something. _right_
clicking on things sometimes left-clicks what's underneath the mouse
cursor. Maybe it's an xfce thing, but I don't see how, and xubuntu 10.04
doesn't do it, so...)
No criticism taken, just wanted to state I was not under any influence
of exotic things while implementing that command ;).
Post by Rob Landley
Post by Elie De Brauwer
I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
So there's no standard for this command _and_ its changed significantly
in the past couple years. Lovely.
Ok, I happily defer to your superior knowledge in this area.
My knowledge is limited to the manpage and what google spat out, not
much superior there.
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
Sounds like a deal, expect a patch with the nice-like behavior (but it
won't be much more work than wat you already stated) in the coming days.

gr
E.
--
Elie De Brauwer
Elie De Brauwer
2012-07-20 07:51:26 UTC
Permalink
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
In attach a patch which makes taskset work as both nice (and renice, the
existing behavior).

The following example which spawns four loops:

#include <pthread.h>

void * loop(void * ptr)
{
while(1){}
}

int main()
{
int i = 0;
for (i=0; i< 4; i++)
{
pthread_t tid;
pthread_create(&tid, NULL, loop, NULL);
}
sleep(100);
return 0;
}

executed as follows:

edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 55 ./a.out

on my poor little quad-core with hyperthreading gives the following top
output:

top - 09:50:37 up 1:23, 14 users, load average: 3.52, 1.49, 0.79
Tasks: 195 total, 1 running, 193 sleeping, 0 stopped, 1 zombie
%Cpu0 : 99.7 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.3
%Cpu1 : 7.3 us, 2.7 sy, 0.0 ni, 90.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu3 : 6.0 us, 4.0 sy, 0.0 ni, 90.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu4 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu6 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu7 : 0.7 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0

my 2 cents
E.
--
Elie De Brauwer

-------------- next part --------------
A non-text attachment was scrubbed...
Name: taskset_work_as_nice.patch
Type: text/x-patch
Size: 2868 bytes
Desc: not available
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20120720/01676a5e/attachment.bin>
Rob Landley
2012-07-20 22:44:50 UTC
Permalink
Post by Elie De Brauwer
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
In attach a patch which makes taskset work as both nice (and renice, the
existing behavior).
Applied.
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.

Hmmm... I suppose that's easy enough to test for:

if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi

Or similar...

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-21 18:11:36 UTC
Permalink
On 07/21/2012 12:44 AM, Rob Landley wrote:>>
Post by Rob Landley
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.
if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi
Or similar...
Pure testing wise, there are other tools which might deserve some more
attention, testing now mainly focuses on the i/o-based blackbox testing
(focusing on the toys which do simple i/o handling). Mainly splitting
tests in two parts, one being more blackbox tests (the test which we
have in place now, but also focusing more on the system-toys iso the
text-toys) but next to this also unittests which can more focus on
testing libraries/internal functions(eventually working with
input/output redirection to test the main functions). However my
preference to touch all of this, would be to touch this after toybox is
self-contained, a chroot (or even a container) and toysh is ideally all
you need to have working tests on a system instead of the hybrid
approach which is now in place.

my 2 cents
E.
--
Elie De Brauwer
Rob Landley
2012-07-21 20:42:24 UTC
Permalink
Post by Elie De Brauwer
On 07/21/2012 12:44 AM, Rob Landley wrote:>>
Post by Rob Landley
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.
if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi
Or similar...
Pure testing wise, there are other tools which might deserve some more
attention, testing now mainly focuses on the i/o-based blackbox testing
(focusing on the toys which do simple i/o handling). Mainly splitting
tests in two parts, one being more blackbox tests (the test which we
have in place now, but also focusing more on the system-toys iso the
text-toys) but next to this also unittests which can more focus on
testing libraries/internal functions(eventually working with
input/output redirection to test the main functions). However my
preference to touch all of this, would be to touch this after toybox is
self-contained, a chroot (or even a container) and toysh is ideally all
you need to have working tests on a system instead of the hybrid
approach which is now in place.
What I vaguely had in mind was making an aboriginal linux control-image
that could run the test suite in a system image under qemu.

Meanwhile you can check if you're running as root [ "$(id -u)" -ne 0 ]
and skip categories of tests that only work as root.

In a previous life I wrote test infrastructure that automatically set up
a chroot through recursive use of "ldd":

http://git.busybox.net/busybox/commit/?id=4bb1b04f

And a wrapper script that ran user mode linux copying the host's root
filesystem, with a given shell script as the init script:

http://git.busybox.net/busybox/commit/?id=dcb2122e853ab4b82e0baf44f7110

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Rob Landley
2012-07-21 20:42:24 UTC
Permalink
Post by Elie De Brauwer
On 07/21/2012 12:44 AM, Rob Landley wrote:>>
Post by Rob Landley
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.
if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi
Or similar...
Pure testing wise, there are other tools which might deserve some more
attention, testing now mainly focuses on the i/o-based blackbox testing
(focusing on the toys which do simple i/o handling). Mainly splitting
tests in two parts, one being more blackbox tests (the test which we
have in place now, but also focusing more on the system-toys iso the
text-toys) but next to this also unittests which can more focus on
testing libraries/internal functions(eventually working with
input/output redirection to test the main functions). However my
preference to touch all of this, would be to touch this after toybox is
self-contained, a chroot (or even a container) and toysh is ideally all
you need to have working tests on a system instead of the hybrid
approach which is now in place.
What I vaguely had in mind was making an aboriginal linux control-image
that could run the test suite in a system image under qemu.

Meanwhile you can check if you're running as root [ "$(id -u)" -ne 0 ]
and skip categories of tests that only work as root.

In a previous life I wrote test infrastructure that automatically set up
a chroot through recursive use of "ldd":

http://git.busybox.net/busybox/commit/?id=4bb1b04f

And a wrapper script that ran user mode linux copying the host's root
filesystem, with a given shell script as the init script:

http://git.busybox.net/busybox/commit/?id=dcb2122e853ab4b82e0baf44f7110

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-21 18:11:36 UTC
Permalink
On 07/21/2012 12:44 AM, Rob Landley wrote:>>
Post by Rob Landley
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.
if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi
Or similar...
Pure testing wise, there are other tools which might deserve some more
attention, testing now mainly focuses on the i/o-based blackbox testing
(focusing on the toys which do simple i/o handling). Mainly splitting
tests in two parts, one being more blackbox tests (the test which we
have in place now, but also focusing more on the system-toys iso the
text-toys) but next to this also unittests which can more focus on
testing libraries/internal functions(eventually working with
input/output redirection to test the main functions). However my
preference to touch all of this, would be to touch this after toybox is
self-contained, a chroot (or even a container) and toysh is ideally all
you need to have working tests on a system instead of the hybrid
approach which is now in place.

my 2 cents
E.
--
Elie De Brauwer
Rob Landley
2012-07-20 22:44:50 UTC
Permalink
Post by Elie De Brauwer
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
In attach a patch which makes taskset work as both nice (and renice, the
existing behavior).
Applied.
It'd be nice if there was a way to add a test to scripts/test, but that
assumes at least a 2-processor machine.

Hmmm... I suppose that's easy enough to test for:

if [ "$(echo /sys/devices/system/cpu/cpu[0-9] | wc -w" -lt 2 ]
then
exit 0
fi

Or similar...

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-19 11:08:54 UTC
Permalink
Post by Rob Landley
I didn't mean to criticize, I'm just a bit frustrated trying to figure
out what the behavior should _be_ in the absence of a standard and with
implementations seeming to vary.
The man page I linked to matches the one on ubuntu 10.04, which is what
this netbook still has on it. (I'm being lazy about upgrading the LTS.
The new one has this horrible X11 behavior where clicks register twice a
lot of the time. They screwed up debouncing or something. _right_
clicking on things sometimes left-clicks what's underneath the mouse
cursor. Maybe it's an xfce thing, but I don't see how, and xubuntu 10.04
doesn't do it, so...)
No criticism taken, just wanted to state I was not under any influence
of exotic things while implementing that command ;).
Post by Rob Landley
Post by Elie De Brauwer
I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
So there's no standard for this command _and_ its changed significantly
in the past couple years. Lovely.
Ok, I happily defer to your superior knowledge in this area.
My knowledge is limited to the manpage and what google spat out, not
much superior there.
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
Sounds like a deal, expect a patch with the nice-like behavior (but it
won't be much more work than wat you already stated) in the coming days.

gr
E.
--
Elie De Brauwer
Elie De Brauwer
2012-07-20 07:51:26 UTC
Permalink
Post by Rob Landley
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
if (opt.argc>2) xexec(toys.optargs+2);
Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.
I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?
In attach a patch which makes taskset work as both nice (and renice, the
existing behavior).

The following example which spawns four loops:

#include <pthread.h>

void * loop(void * ptr)
{
while(1){}
}

int main()
{
int i = 0;
for (i=0; i< 4; i++)
{
pthread_t tid;
pthread_create(&tid, NULL, loop, NULL);
}
sleep(100);
return 0;
}

executed as follows:

edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 55 ./a.out

on my poor little quad-core with hyperthreading gives the following top
output:

top - 09:50:37 up 1:23, 14 users, load average: 3.52, 1.49, 0.79
Tasks: 195 total, 1 running, 193 sleeping, 0 stopped, 1 zombie
%Cpu0 : 99.7 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.3
%Cpu1 : 7.3 us, 2.7 sy, 0.0 ni, 90.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu3 : 6.0 us, 4.0 sy, 0.0 ni, 90.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu4 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu6 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0
%Cpu7 : 0.7 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0

my 2 cents
E.
--
Elie De Brauwer

-------------- next part --------------
A non-text attachment was scrubbed...
Name: taskset_work_as_nice.patch
Type: text/x-patch
Size: 2868 bytes
Desc: not available
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20120720/01676a5e/attachment-0002.bin>
Rob Landley
2012-07-19 01:41:21 UTC
Permalink
Post by Elie De Brauwer
Post by Rob Landley
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
Whatever version of util-linux linux.die.net might 've stolen the
manpage from, it for sure isn't a recent version.
I didn't mean to criticize, I'm just a bit frustrated trying to figure
out what the behavior should _be_ in the absence of a standard and with
implementations seeming to vary.

The man page I linked to matches the one on ubuntu 10.04, which is what
this netbook still has on it. (I'm being lazy about upgrading the LTS.
The new one has this horrible X11 behavior where clicks register twice a
lot of the time. They screwed up debouncing or something. _right_
clicking on things sometimes left-clicks what's underneath the mouse
cursor. Maybe it's an xfce thing, but I don't see how, and xubuntu 10.04
doesn't do it, so...)
Post by Elie De Brauwer
I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
So there's no standard for this command _and_ its changed significantly
in the past couple years. Lovely.

Ok, I happily defer to your superior knowledge in this area.
Post by Elie De Brauwer
Post by Rob Landley
http://linux.die.net/man/1/taskset
In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)
Indeed, except that if you use it with -p, the -a is not default (so it
will only look at the tid specified).
Upstream behavior is crazy, but in the absence of a standard we follow
upstream behavior. Got it.
Post by Elie De Brauwer
Post by Rob Landley
I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...
Well, my submission matches (or at least was intended) to match
taskset [-a] mask-in-hex pid
Ok.
Post by Elie De Brauwer
Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
Is there more to it than:

if (opt.argc>2) xexec(toys.optargs+2);

Well, taskset getpid() and then exec. And detect -p... ok there's a bit
of work.

I'd prefer if you could add the new work-as-nice stuff since you know
what the UI should be like, and I'll hold off converting to the raw
syscall until then. Sound good?

Thanks,

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Elie De Brauwer
2012-07-18 07:53:58 UTC
Permalink
Post by Rob Landley
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
Whatever version of util-linux linux.die.net might 've stolen the
manpage from, it for sure isn't a recent version. I just looked at the
manpage on my debian system (util-linux-2.20.1) and it resembles this
http://manpages.ubuntu.com/manpages/precise/man1/taskset.1.html (you
need to scroll down to see the options.
(I think this patch http://www.digipedia.pl/usenet/thread/19513/138/
more or less shows the -a specific changes).
Post by Rob Landley
http://linux.die.net/man/1/taskset
In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)
Indeed, except that if you use it with -p, the -a is not default (so it
will only look at the tid specified).
Post by Rob Landley
By the way: "taskset -p [mask] pid" is _crazy_. pid should be an
argument to -p, ala "taskset mask [-p pid | arg...].
I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...
Well, my submission matches (or at least was intended) to match

taskset [-a] mask-in-hex pid

Meaning to works as renice, rather than nice. I'm open to suggestions, I
can as well the 'work-as-nice' functionality,
Post by Rob Landley
Confused,
Rob
--
Elie De Brauwer
Elie De Brauwer
2012-07-15 11:34:43 UTC
Permalink
Hello all,

In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.

I tested it (a.o.) with a yes > /dev/null and a top which shows the cpu
load per core, and then you can see yes jump around

edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x1 20941
pid 20941's current affinity mask: ff
pid 20941's new affinity mask: 1
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x2 20941
pid 20941's current affinity mask: 1
pid 20941's new affinity mask: 2
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x4 20941
pid 20941's current affinity mask: 2
pid 20941's new affinity mask: 4
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x8 20941
pid 20941's current affinity mask: 4
pid 20941's new affinity mask: 8
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x10 20941
pid 20941's current affinity mask: 8
pid 20941's new affinity mask: 10
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x20 20941
pid 20941's current affinity mask: 10
pid 20941's new affinity mask: 20
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x30 20941
pid 20941's current affinity mask: 20
pid 20941's new affinity mask: 30
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x40 20941
pid 20941's current affinity mask: 30
pid 20941's new affinity mask: 40
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x80 20941
pid 20941's current affinity mask: 40
pid 20941's new affinity mask: 80

One comment, I added sched.h into the toys.h include, but I also needed
a #define _GNU_SOURCE or I'd run into troubles because it failed to find
the CPU_SET* macro's. So this was added in taskset.c but I'm not sure if
this is the correct way to go.

my 2 cents
E.
--
Elie De Brauwer

-------------- next part --------------
A non-text attachment was scrubbed...
Name: taskset.patch
Type: text/x-patch
Size: 3691 bytes
Desc: not available
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20120715/f8dda953/attachment-0002.bin>
Rob Landley
2012-07-18 02:06:32 UTC
Permalink
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Ok. In busybox, but not even in LSB. Huh. "other" then...
Post by Elie De Brauwer
I tested it (a.o.) with a yes > /dev/null and a top which shows the cpu
load per core, and then you can see yes jump around
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x1 20941
pid 20941's current affinity mask: ff
pid 20941's new affinity mask: 1
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x2 20941
pid 20941's current affinity mask: 1
pid 20941's new affinity mask: 2
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x4 20941
pid 20941's current affinity mask: 2
pid 20941's new affinity mask: 4
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x8 20941
pid 20941's current affinity mask: 4
pid 20941's new affinity mask: 8
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x10 20941
pid 20941's current affinity mask: 8
pid 20941's new affinity mask: 10
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x20 20941
pid 20941's current affinity mask: 10
pid 20941's new affinity mask: 20
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x30 20941
pid 20941's current affinity mask: 20
pid 20941's new affinity mask: 30
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x40 20941
pid 20941's current affinity mask: 30
pid 20941's new affinity mask: 40
edb at lapedb:~/edb-stuff/toybox/toybox$ sudo ./toybox taskset 0x80 20941
pid 20941's current affinity mask: 40
pid 20941's new affinity mask: 80
Cool.
Post by Elie De Brauwer
One comment, I added sched.h into the toys.h include, but I also needed
a #define _GNU_SOURCE or I'd run into troubles because it failed to find
the CPU_SET* macro's. So this was added in taskset.c but I'm not sure if
this is the correct way to go.
What an utterly horrible interface, which the glibc guys once again broke.

<rant>Hurd is a part of the gnu project. Linux is not. This is a
linux-specific system call, labeling it with "gnu" is like labeling it
"property of Sun Microsystems". They had nothing to do with it.</rant>

Your code is fine, but I'm gonna open code the darn system call anyway,
because I'm interpreting Android's "no GPL in userspace" as "No GNU is
good GNU".

Luckily, Linux system calls are binary backwards compatible forever
(modulo Documentation/feature-removal-schedule.txt), so if I just work
out what the ABI actually _is_, with appropriate word size and endianness...

Let's see, pid, size_t, and a pointer to... what? The size_t is bytes of
the blob of data the pointer points to, the problem is endianness.
(Since I don't personally have access to any machine with > 8
processors, let alone a big endian one, I kinda have to get this right
up front... or run strace on the existing code to see what it's passing
to the system call, but let's hold that in reserve...)

Digging into bits/sched.h it's treating it as an array of unsigned
longs, which on a big endian machine would be kind of disturbing. Ok,
forget what the headers are doing, what is the _kernel_ expecting?

kernel/sched/core.c:

SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long __user *, user_mask_ptr)
{
int ret;
cpumask_var_t mask;

if ((len * BITS_PER_BYTE) < nr_cpu_ids)
return -EINVAL;
if (len & (sizeof(unsigned long)-1))
return -EINVAL;

Yeah, that matches. The size is in bytes, but the kernel insists it must
be a multiple of sizeof(unsigned long). The glibc loonies of course
hardware a size of 1024. sigh: if I'm going to hardware something, I
might as well use toybuf which is already there and starts zeroed.

So it looks like:

long *blah = (long *)toybuf;
blah[cpu/sizeof(long)] |= 1<<(cpu&(sizeof(long)-1));

But that's just NUTS on a big endian system, so lemme confirm that. Dig
through the system call entry point into the kernel, the code is doing
cpumask_and() which lives in include/linux/cpumask.h and is a wrapper
around linux/bitmap.h which says I should look at lib/bitmap.c which says:

* The byte ordering of bitmaps is more natural on little
* endian architectures. See the big-endian headers
* include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
* for the best explanations of this ordering.

Except there isn't an asm-ppc64 anymore, it got merged into arch/power
(I should send a patch for that), so...

arch/powerpc/include/asm/bitops.h:

* The bitop functions are defined to work on unsigned longs, so for a
* ppc64 system the bits end up numbered:
*
|63..............0|127............64|191...........128|255...........196|
* and on ppc32:
*
|31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
*

And that's exactly what I wanted to know. So my guess at how to do it
was right, and it just plain IS a crazy layout on big endian.

*shrug* Ok.

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Rob Landley
2012-07-18 02:26:46 UTC
Permalink
Post by Elie De Brauwer
Hello all,
In attach you can find an initial version of 'taskset'. It allows
setting the cpu affinity of a given PID (or all tasks related with a
given PID/TID). cpu affinity should be entered in hex, when no affinity
is given the affinity for the process or the group of tasks is displayed.
Where did the -a flag come from? The taskset on my system matches this
man page:

http://linux.die.net/man/1/taskset

In which taskset is a filter like nice, and -p says work on an existing
pid instead of launching a new one. I'd guess -a is the behavior it
always has, since "tasks" basically means "threads". (Unless containers
use that too...)

By the way: "taskset -p [mask] pid" is _crazy_. pid should be an
argument to -p, ala "taskset mask [-p pid | arg...].

I'm not sure whether to consider the man page's command line
grandfathered in (otherwise "taskset -p mask pid" won't work) or just go
ahead and make the pid an argument to -p. I _can_ implement either but
the current behavior makes no sense and there's no standard and your
submission didn't even match what was there so it's not like that's
_less_ compatible...

Confused,

Rob
--
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation. Pick one.
Continue reading on narkive:
Loading...