我正在尝试使用,在没有优先级继承互斥体的情况下实现无限制的优先级倒置的无特权测试用例SCHED_IDLE
。该测试适用于SCHED_FIFO
不同的实时优先级(非PI互斥锁解除锁定,立即使用PI互斥锁进行解析),但是为了将其包含在无需实时特权即可运行的测试集中,我想使用SCHED_IDLE
“中等”和“高”优先级线程都使用SCHED_OTHER
(在这种情况下,它并不是真正的优先级“倒置”,但是该概念仍然有效-“中” 线程应禁止执行“低” 线程)。
不幸的是,该测试无法区分PI和非PI互斥锁。无论哪种方式,它都能取得进步。显然,SCHED_IDLE
即使有另一个可运行的任务,该任务仍在运行。已设置CPU亲和力以将它们全部绑定到同一内核,以便低优先级任务无法迁移到其他内核以运行。而且我知道SCHED_IDLE
应该在内核空间中以较高的特权运行任务,以防止内核空间优先级倒置,因此我尝试通过使“低”线程不会进入用户空间来使其进入用户空间的繁忙循环,从而确保其不会进入内核空间,并且strace
没有显示它在不应该前进的时间内正在进行系统调用的迹象。
SCHED_IDLE
当内核实际上不处于空闲状态时,Linux是否仅允许运行空闲任务?还是我可能会缺少的东西?
这是测试代码,稍作修改后可以在实时模式下运行SCHED_IDLE
:
#define _GNU_SOURCE
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
sem_t sem;
void *start1(void *p)
{
pthread_mutex_lock(p);
sem_post(&sem);
sem_post(&sem);
usleep(100000);
pthread_mutex_unlock(p);
return 0;
}
void *start2(void *p)
{
sem_wait(&sem);
time_t t0 = time(0);
while (pthread_mutex_trylock(p)) {
if (time(0)>t0+5) return 0;
}
pthread_mutex_unlock(p);
return 0;
}
void *start3(void *p)
{
sem_wait(&sem);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 5;
int r;
if (r=pthread_mutex_timedlock(p, &ts)) {
printf("failed: %d %s\n", r, strerror(r));
} else {
pthread_mutex_unlock(p);
}
return 0;
}
int main(int argc, char **argv)
{
int policy = argc>1 ? SCHED_IDLE : SCHED_FIFO;
int a = sched_get_priority_min(policy);
pthread_attr_t attr;
pthread_t t1,t2,t3;
struct sched_param param = {0};
cpu_set_t set = {0};
CPU_ZERO(&set);
CPU_SET(0, &set);
pthread_setaffinity_np(pthread_self(), sizeof set, &set);
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, policy);
pthread_mutexattr_t ma;
pthread_mutexattr_init(&ma);
pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_t mtx;
pthread_mutex_init(&mtx, &ma);
sem_init(&sem, 0, 0);
param.sched_priority = a+1;
pthread_attr_setschedparam(&attr, ¶m);
if (pthread_create(&t2, policy==SCHED_IDLE ? 0 : &attr, start2, &mtx)) return 1;
param.sched_priority = a+2;
pthread_attr_setschedparam(&attr, ¶m);
if (pthread_create(&t3, policy==SCHED_IDLE ? 0 : &attr, start3, &mtx)) return 1;
param.sched_priority = a;
pthread_attr_setschedparam(&attr, ¶m);
if (pthread_create(&t1, &attr, start1, &mtx)) return 1;
pthread_join(t1, 0);
pthread_join(t2, 0);
pthread_join(t3, 0);
return 0;
}
SCHED_IDLE
当内核实际上不处于空闲状态时,Linux是否仅允许运行空闲任务?还是我可能会缺少的东西?
这是对的。SCHED_IDLE
使任务的加权很低但不为零 -比19任务少CPU时间约70%。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句