Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does sched_setaffinity() work?

I am trying to understand how the linux syscall sched_setaffinity() works. This is a follow-on from my question here.

I have this guide, which explains how to use the syscall and has a pretty neat (working!) example.

So I downloaded the Linux 2.6.27.19 kernel sources.

I did a 'grep' for lines containing that syscall, and I got 91 results. Not promising.

Ultimately, I'm trying to understand how the kernel is able to set the instruction pointer for a specific core (or processor.)

I am familiar with how single-core-single-thread programs work. One might issue a 'jmp foo' instruction, and this basically sets the IP to the memory address of the 'foo' label. But when one has multiple cores, one has to say "fetch the next instruction at memory address foo, and set the instruction pointer for core number 2 to begin execution there."

Where, in the assembly code, are we specifying which core performs that operation?

Back to the kernel code: what is important here? The file 'kernel/sched.c' has a function called sched_setaffinity(), but returns type "long" - which is inconsistent with its manual page. So what is important here? Which of these modules shows the assembly instructions issued? What module is reading the 'task_struct', looking at the 'cpus_allowed' member, and then translating that into an instruction? (I've also thumbed through the glibc source - but I think it just makes a call to the kernel code to accomplish this task.)

like image 993
poundifdef Avatar asked Apr 19 '09 23:04

poundifdef


People also ask

What is Sched_setaffinity?

sched_setaffinity() sets the CPU affinity mask of the thread whose ID is pid to the value specified by mask. If pid is zero, then the calling thread is used. The argument cpusetsize is the length (in bytes) of the data pointed to by mask. Normally this argument would be specified as sizeof(cpu_set_t).

How do I check my CPU affinity?

CPU affinity enables binding a process or multiple processes to a specific CPU core in a way that the process(es) will run from that specific core only. When trying to perform performance testing on a host with many cores, it is wise to run multiple instances of a process, each one on different core.

How do you set an affinity mask?

To set an affinity mask for Processors 3 and 7, you would set the bits as follows: You create the bitmask by enabling the bits that correspond to your processors. For example, the following code snippet shows how to enable bits for Processors 7 and 3: DWORD_PTR mask = (1<< 7) + (1<< 3);


2 Answers

sched_setaffinity() simply tells the scheduler which CPUs is that process/thread allowed to run on, then calls for a re-schedule.

The scheduler actually runs on each one of the CPUs, so it gets a chance to decide what task to execute next on that particular CPU.

If you're interested in how you can actually call some code on other CPUs, I suggest you take a look at smp_call_function_single(). In case we want to call something on another CPU, this calls generic_exec_single(). The latter simply adds the function to the target CPU's call queue and forces a reschedule through some IPI stuff (if the queue was empty).

Bottom line is: there no actual SMP variant of the _jmp_ instruction. Instead, code running on other CPUs cooperates in order to accomplish the task.

like image 183
Eduard - Gabriel Munteanu Avatar answered Nov 13 '22 06:11

Eduard - Gabriel Munteanu


I think the thing you are not understanding is that the kernel is running on all the CPU cores. At every timer interrupt (~1000 per second), the scheduler runs on each CPU and chooses a process to run. There is no one CPU that somehow tells the others to start running a process. sched_setaffinity() works by just setting flags on the process. The scheduler reads these flags and will not run that process on its CPU if it is set not to.

like image 28
Zifre Avatar answered Nov 13 '22 04:11

Zifre