[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: