Xenomai隔离cpu
Xenomai隔离cpu
Xenomai源码解析第一章-xenomai_init(一)
前文提到多核状态下,会设置xenomai的cpu亲和性。
【原创】有利于提高xenomai 实时性的一些配置建议一文中提到了提高xenomai实时性的一些建议。其中有一条cpu隔离。笔者在raspberry4下的应用会设置xenomai.supported_cpus=0x3,即将cpu的第一个和第二个核孤立。拒绝linux内核对这两个核心的调度,然后仅由xenomai来调度。本文从xenomai的源码角度补充之前的文章,并分析xenomai是如何实现这一机制的
初始化实时调度cpu
cpumask_clear(&xnsched_realtime_cpus);
/**
* cpumask_clear - clear all cpus (< nr_cpu_ids) in a cpumask
* @dstp: the cpumask pointer
*/
static inline void cpumask_clear(struct cpumask *dstp)
{
bitmap_zero(cpumask_bits(dstp), nr_cpumask_bits);
}
#define cpumask_bits(maskp) ((maskp)->bits)
#define nr_cpumask_bits NR_CPUS
关于cpu掩码设置可以看文章CPU masks,这里会建立一个对用户机器cpus数目的位图,该函数会将每一个有效位都清除.
这里的xnsched_realtime_cpus如下
cpumask_t supported_cpus;
#define xnsched_realtime_cpus cobalt_pipeline.supported_cpus
关于cpumask_t 的定义:
typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
//此处不再展开直接给出结果,具体可以查看上面的文章.
typedef struct cpumask
{
unsigned long bits[1];
} cpumask_t;
static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
{
if (small_const_nbits(nbits))
*dst = 0UL;
else {
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, 0, len);
}
}
···
上述会将xenomai支持的cpu位图都清零进行初始化.
读取用户设置的参数并设置位置
for_each_online_cpu(cpu) {
if (supported_cpus_arg & (1UL << cpu))
cpumask_set_cpu(cpu, &xnsched_realtime_cpus);
}
#define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask)
#define for_each_cpu(cpu, mask) \
for ((cpu) = -1; \
(cpu) = cpumask_next((cpu), (mask)), \
(cpu) < nr_cpu_ids;)
#define cpu_online_mask ((const struct cpumask *)&__cpu_online_mask)
这里的for_each_online_cpu(cpu)其实就是从0开始遍历有效的cpu,因为我们设置的参数xenomai.supported_cpus=0x3,即第一个核和第二个核,这里相当于转换到内核的0核和1核。并设置位图。
static inline void cpumask_set_cpu(unsigned int cpu, struct cpumask *dstp)
{
set_bit(cpumask_check(cpu), cpumask_bits(dstp));
}
static __always_inline void
set_bit(long nr, volatile unsigned long *addr)
{
if (IS_IMMEDIATE(nr)) {
asm volatile(LOCK_PREFIX "orb %1,%0"
: CONST_MASK_ADDR(nr, addr)
: "iq" ((u8)CONST_MASK(nr))
: "memory");
} else {
asm volatile(LOCK_PREFIX "bts %1,%0"
: BITOP_ADDR(addr) : "Ir" (nr) : "memory");
}
}
具体的执行流程可以查看之前那篇文章.
设置cobalt cpu亲和性
cobalt_cpu_affinity = xnsched_realtime_cpus;
结束语
在这后xenomai在调度的时候会检测核是否为设置的。但是大致检索一下还没有明白如何让linux内核不调度。目前猜测可能是xenomai屏蔽了核的时钟中断,对于被孤立的核,xenomai处理完之后不在转发,对于xenomai不调度的核心。xenomai不做处理直接转发。