What you want to do is basically the same thing that /proc/cpuinfo
already does:
$ cat /proc/cpuinfo
processor : 0 <== you have this
...
core id : 0 <== you want to obtain this
...
We can therefore take a look at how /proc/cpuinfo
does this, in arch/x86/kernel/cpu/proc.c
. By analyzing the code a little bit, we see that the CPU information is obtained calling cpu_data()
:
static void *c_start(struct seq_file *m, loff_t *pos)
{
*pos = cpumask_next(*pos - 1, cpu_online_mask);
if ((*pos) < nr_cpu_ids)
return &cpu_data(*pos); // <=== HERE
return NULL;
}
The cpu_data()
macro returns a struct cpuinfo_x86
, which contains all the relevant information, and is then used here to print the core ID:
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
Therefore, in a kernel module, you can do the following:
#include <linux/smp.h> // get_cpu(), put_cpu()
#include <asm/processor.h> // cpu_data(), struct cpuinfo_x86
// ...
static int __init modinit(void)
{
unsigned cpu;
struct cpuinfo_x86 *info;
cpu = get_cpu();
info = &cpu_data(cpu);
pr_info("CPU: %u, core: %d\n", cpu, info->cpu_core_id);
put_cpu(); // Don't forget this!
return 0;
}
Dmesg output on my machine after inserting/removing the module three times:
[14038.937774] cpuinfo: CPU: 1, core: 1
[14041.084951] cpuinfo: CPU: 5, core: 1
[14087.329053] cpuinfo: CPU: 6, core: 2
Which is consistent with the content of my /proc/cpuinfo
:
$ cat /proc/cpuinfo | grep -e 'processor' -e 'core id'
processor : 0
core id : 0
processor : 1
core id : 1
processor : 2
core id : 2
processor : 3
core id : 3
processor : 4
core id : 0
processor : 5
core id : 1
processor : 6
core id : 2
processor : 7
core id : 3
Note that as Martin James rightfully pointed out, this information is not very useful since your process could be preempted and moved to a different core by the time your syscall finishes execution. If you want to avoid this you can use the sched_setaffinity()
syscall in your userspace program to set the affinity to a single CPU.