[英]A pthread with SCHED_RR and higher real time priority failed to preempt a kthread in kernel module with lower priority
I have two threads: one kernel thread and one userspace pthread
.我有两个线程:一个 kernel 线程和一个用户空间
pthread
。 I assume pthread
set to SCHED_RR
with higher rt priority should preempt a kthread
with SCHED_RR
and lower priority while both of them running one the same cpu.我假设
pthread
设置为SCHED_RR
具有更高的 rt 优先级应该抢占具有kthread
和更低优先级的SCHED_RR
,同时它们都运行一个相同的 cpu。
However my test failed.但是我的测试失败了。
kthread
keeps running and pthread did not progress. kthread
一直在运行,而 pthread 没有进展。
NOTE: I add both C and C++ tag for this post since my example are one with C++ and one with C. If any tag suits this post, please edit it and remove C and C++ tag.注意:我为这篇文章添加了 C 和 C++ 标签,因为我的例子是一个带有 C++ 和一个带有 C 的标签。如果有任何标签适合这篇文章,请编辑它并删除 C 和 C++ 标签。
Ubuntu 18.04. Ubuntu 18.04。 ( I assume it's workable whether on normal linux and RT linux )
(我假设它在正常 linux 和 RT linux 上都是可行的)
kthread is created with SCHED_RR
and rt priority 50. kthread 是用
SCHED_RR
和 rt 优先级 50 创建的。
udelay()
which should not disable preeption. udelay()
的无限循环,它不应该禁用抢占。kthread_should_stop()
before calling udelay
udelay
之前会检查kthread_should_stop()
pthread is created with SCHED_RR
and rt priority 70. pthread 是使用
SCHED_RR
和 rt 优先级 70 创建的。
pthread
would call pthread_join
to wait until pthread
end by ctrl+cpthread
会调用pthread_join
等待直到pthread
结束 ctrl+c while( true ){
sleep( 1 );
std:: cout << "wake\n";
}
If kthread
run first, and userprogram would stuck after pthread_join
called.如果
kthread
先运行,而 userprogram 会在pthread_join
调用后卡住。 Output string from pthread
cannot be received until kernel module removed ( calling kthread to stop ). Output 在 kernel 模块移除之前无法接收到来自
pthread
的字符串(调用 kthread 停止)。
My assumption is pthread never start since no output printed on console.我的假设是 pthread 永远不会启动,因为控制台上没有打印 output。 But I'm not sure if this assumption correct.
但我不确定这个假设是否正确。
pthread failed to preempt kthread pthread 无法抢占 kthread
How “real-time” are the FIFO/RR schedulers on non-RT Linux kernel?非 RT Linux kernel 上的 FIFO/RR 调度程序有多“实时”?
==== This is the wall of text with test code ==== ====这是带有测试代码的文字墙====
#include <uapi/linux/sched/types.h> // For sched_param
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h> // kthread_create(), kthread_should_stop(), kthread_stop()
#include <linux/delay.h> // msleep()
#include <linux/sched.h> // For struct sched_param, sched_setcheduler()
#define MY_THREADNAME "kthread example"
#define MY_MODULENAME "kthread occupy cpu1 module"
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement" // Ignore C90 declaration convention since gcc has extension for it.
MODULE_LICENSE( "GPL v2" );
MODULE_AUTHOR( "TEST" );
MODULE_DESCRIPTION( MY_MODULENAME );
struct task_struct *m_task1;
static int m_t1id = 1;
int thread_fn(void *data)
{
int id = *((int*)data);
int ret = 0;
int cpu = -1;
cpu = get_cpu();
put_cpu();
pr_info( "IN THREAD FUNCTION %d, CPU is %d \n", id, cpu);
while(!kthread_should_stop()){
// try to busy blocking cpu, but udelay doesn't disable preemption.
udelay(1000);
}
pr_info( "EXIT from thread function 1\n");
return 0;
}
static int __init init_my_module(void) {
pr_info( "Hello, %s!\n", MY_MODULENAME );
// Get cpu will disable preemption, so must put_cpu to enable preemption
int cpu = get_cpu();
put_cpu();
pr_info( "Current cpu for initializing is %d\n", cpu );
pr_info( "Current pid is %d\n", current->pid );
// threadfn, data, and printf-style name. Created thread would be suspended, need to wake up.
m_task1 = kthread_create(&thread_fn,(void *)&m_t1id,"testing kt%d",m_t1id);
pr_info( "T1 pid is %d", m_task1->pid );
kthread_bind(m_task1,1 );
// Set Realtime priority
struct sched_param param = {50};
sched_setscheduler( m_task1, SCHED_RR, ¶m );
pr_info( "T1 effective prio AFTER set policy= %d", m_task1->prio );
wake_up_process(m_task1);
return 0;
}
static void __exit exit_my_module(void) {
kthread_stop( m_task1 );
pr_info( "Bye, %s!\n", MY_MODULENAME );
}
module_init( init_my_module);
module_exit( exit_my_module);
#Test on local ubuntu
KVERSION := $(shell uname -r)
KERNEL_DIR = /lib/modules/$(KVERSION)/build
PWD := $(shell pwd)
MODULE_NAME = kthread
obj-m = $(MODULE_NAME).o
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
Compile commandline for pthread.cpp is g++ pthread.cpp -pthread
pthread.cpp 的编译命令行是
g++ pthread.cpp -pthread
#include <pthread.h>
#include <sched.h>
#include <iostream>
#include <sys/resource.h> // to use getrusage
#include <unistd.h>
void* helloworld ( void *arg ){
int cpuid = sched_getcpu();
int sum = 0;
std::cout<< "Hello pthread on cpu " << cpuid << std::endl;
pthread_t pself = pthread_self();
int policy = 0;
struct sched_param sparam;
pthread_getschedparam( pself, &policy, &sparam );
std::cout << "Current thread Policy: " << policy << " prio:" << sparam.sched_priority << "\n";
int err = pthread_setschedprio( pself, 99 );
std::cout<< "set prio ret:"<< err <<"\n";
// keep sleep to check process priority
while( true ){
sleep( 1 );
std:: cout << "wake\n";
}
return NULL;
}
int main(void){
std::cout<<" pthread create\n";
pthread_t handle;
pthread_attr_t attr;
cpu_set_t cpus;
struct sched_param sparam;
int error = 0;
// Setting SCHED_FIFO must run program in sudo
int policy = SCHED_RR;
CPU_ZERO( &cpus );
// Set bit cpu0 to enable in mask.
CPU_SET( 1, &cpus );
pthread_attr_init( &attr );
// Let pthread using specified attribute explicitly
error = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
std::cout << "set inherit sched result: "<< error << "\n";
error = pthread_attr_setschedpolicy( &attr, policy );
std::cout << "set policy result: "<< error << "\n";
// _np means "non-portable"
pthread_attr_setaffinity_np( &attr,sizeof(cpu_set_t), &cpus );
// Set priority
int max = 70;//sched_get_priority_max(policy);
sparam.sched_priority = max;// ( 4* min + 6*max )/10;
std::cout << "Set priority: " << sparam.sched_priority << "\n";
error = pthread_attr_setschedparam(&attr ,&sparam);
std::cout << "setschedparam: " << error << std::endl;
// before create thread, raise main thread as higher priority
error = pthread_setschedparam(pthread_self(), policy, &sparam);
std::cout<< "main thread set prio " << error << std::endl;
error = pthread_create( &handle, &attr , &helloworld, NULL );
std::cout<< "pthread_create " << error << std::endl;
void* retvalue;
pthread_join( handle, &retvalue );
pthread_attr_destroy( &attr );
return 0;
}
The short answer: CONFIG_PREEMPT
enabled is required.简短的回答:需要启用
CONFIG_PREEMPT
。
I tried on CONFIG_PREEMPT linux and pthread does preempt the kernel thread with higher priority.我试过 CONFIG_PREEMPT linux 并且 pthread 确实抢占了具有更高优先级的 kernel 线程。
If you're interested in build a kernel, following links are for ubuntu 18.04.如果您有兴趣构建 kernel,以下链接适用于 ubuntu 18.04。
I choose to my own question but would not accept it since it's just the tested behavior but not why .我选择了我自己的问题,但不会接受它,因为它只是经过测试的行为,而不是为什么。 I'd like to receive an anwer explaining
CONFIG_PREEPT
.我想收到一个解释
CONFIG_PREEPT
的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.