libc sched_setaffinity problem
Hi,
the libc binding for sched_setaffinity is broken on my machine. I
would like to ask here if other people see the same odd behaviour
before I file a bug report.
When I run
strace -e trace=sched_setaffinity,sched_getaffinity taskset -p 2 22420
I get the following:
sched_getaffinity(22420, 128, { 3 }) = 8
pid 22420's current affinity mask: 3
sched_getaffinity(22827, 128, { 3 }) = 8
everything fine up to here: taskset calls getaffinity and libc
calls it to find out the size of the kernel cpumask.
sched_setaffinity(22420, 128, { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }) = 0
This is the strange line: In the system call the cpumask is 3
although I specified 2. (Its always 3, regardless of the taskset
argument.)
sched_getaffinity(22420, 128, { 3 }) = 8
pid 22420's new affinity mask: 3
This way the kernel does not change the cpumask, of course.
This is not a problem of taskset. I append a short program that
calls sched_setaffinity twice: First via libc and then as a
direct system call:
The command line
strace -e trace=sched_setaffinity,sched_getaffinity ./otaskset 2 22420
produces
sched_getaffinity(22420, 128, { 3 }) = 8
procmask for pid 22420: 00000003|00000000
current procmask is 3.
procmask to set: 00000002|00000000
the procmask I pass to libc
sched_getaffinity(22847, 128, { 3 }) = 8
sched_setaffinity(22420, 128, { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }) = 0
However, the syscall uses procmask 3.
argument after libc: 00000003|00000000
libc/sched_setaffinity is even changing my argument !!!
sched_setaffinity(22420, 128, { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }) = 0
o_sched_set ret 0
perform the syscall myself
sched_getaffinity(22420, 128, { 2 }) = 8
procmask after set: 00000002|00000000
which takes effect as expected.
I observe these effects with
ii libc6 2.3.2.ds1-22 GNU C Library: Shared libraries and Timezone
ii libdb1-compat 2.1.3-7 The Berkeley database routines [glibc 2.0/2.
Bye,
Hendrik
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sched.h>
void usage(void){
printf("usage: otaskset <cpumask> <pid>\n");
}
void print_mask(char * text, cpu_set_t * cpuset){
printf("%s%08lx", text, cpuset->__bits[0]);
printf("|%08lx", cpuset->__bits[1]);
/*
* // uncomment this to get all trailing zeros ...
* unsigned i;
* for (i = 2; i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++i)
* printf("|%08lx", cpuset->__bits[i]);
*/
printf("\n");
}
int error;
int o_sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)
{
return (
{
unsigned long resultvar = (
{
unsigned long resultvar;
register long int _a3 asm ("rdx") = (long) (cpuset);
register long int _a2 asm ("rsi") = (long) (cpusetsize);
register long int _a1 asm ("rdi") = (long) (pid);
asm volatile (
"movq %1, %%rax\n\t"
"syscall\n\t" :
"=a" (resultvar) : "i" (203) ,
"r" (_a1),
"r" (_a2),
"r" (_a3) :
"memory", "cc", "r11", "cx");
(long) resultvar;
});
printf("o_sched_set ret %ld\n", resultvar);
if ((unsigned long) (resultvar) >= -4095L)
{
// (__libc_errno = ((-(resultvar))));
error = -resultvar;
resultvar = (unsigned long) -1;
}
(long) resultvar;
});
}
int main(int argc, char *argv[]){
pid_t pid;
unsigned mask, shift, i;
cpu_set_t cpuset, setarg;
if(argc != 3){
usage();
return 1;
}
mask = atoi(argv[1]);
pid = atoi(argv[2]);
if(sched_getaffinity(pid, sizeof(cpuset), &cpuset)){
perror("sched_getaffinity");
return 1;
}
char pbuf[100];
snprintf(pbuf, 100, "procmask for pid %d: ", pid);
print_mask(pbuf, &cpuset);
CPU_ZERO(&cpuset);
shift = 1;
i = 0;
while(shift)
{
if(mask & shift)
CPU_SET(i, &cpuset);
shift = shift << 1;
i++;
}
setarg = cpuset;
print_mask("procmask to set: ", &setarg);
if(sched_setaffinity(pid, sizeof(cpuset), &setarg)){
perror("sched_set");
return 1;
}
print_mask("argument after libc: ", &setarg);
setarg=cpuset;
if(o_sched_setaffinity(pid, sizeof(cpuset), &setarg)){
fprintf(stderr, "my_sched_set: %s\n", strerror(error));
return 1;
}
if(sched_getaffinity(pid, sizeof(cpuset), &cpuset)){
perror("sched_getaffinity");
return 1;
}
print_mask("procmask after set: ", &cpuset);
return 0;
}
/*** Local Variables: ***/
/*** compile-command: "gcc -Wall otaskset.c -o otaskset" ***/
/*** End: ***/
Reply to: