c - SCHED_IDLE 是否实际上排除了在非空闲内核上的执行?

标签 c linux pthreads posix priority-inversion

我正在尝试在没有优先级继承互斥锁的情况下使用 SCHED_IDLE 实现无权限的优先级反转测试用例。该测试适用于 SCHED_FIFO 和不同的实时优先级(非 PI 互斥锁死锁,使用 PI 互斥锁立即解决),但要将其包含在没有实时权限的情况下运行的测试集中,我想使用 SCHED_IDLE 代替,“中”和“高”优先级线程都是 SCHED_OTHER(在这种情况下它不是真正的优先级“反转”,但这个概念应该仍然有效- “中等”应该排除“低”的执行)。

不幸的是,测试无法区分 PI 和非 PI 互斥量;无论哪种方式,它都会取得进展。显然,即使有另一个可运行的任务,SCHED_IDLE 任务也在运行。 CPU affinity 已设置为将它们全部绑定(bind)到同一核心,以便低优先级任务无法迁移到不同的核心运行。而且我知道 SCHED_IDLE 任务应该在内核空间中以提升的权限运行以防止内核空间优先级反转,所以我尝试确保“低”线程不会进入内核空间它在用户空间中忙于循环,并且 strace 没有显示它在它不应该向前推进的时候正在进行系统调用的迹象。

Linux 的 SCHED_IDLE 是否只允许空闲任务在内核实际上不空闲时运行?或者还有其他我可能遗漏的东西吗?

这里是测试代码,稍作调整,以便它可以在实时模式或 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, &param);
    if (pthread_create(&t2, policy==SCHED_IDLE ? 0 : &attr, start2, &mtx)) return 1;

    param.sched_priority = a+2;
    pthread_attr_setschedparam(&attr, &param);
    if (pthread_create(&t3, policy==SCHED_IDLE ? 0 : &attr, start3, &mtx)) return 1;

    param.sched_priority = a;
    pthread_attr_setschedparam(&attr, &param);
    if (pthread_create(&t1, &attr, start1, &mtx)) return 1;

    pthread_join(t1, 0);
    pthread_join(t2, 0);
    pthread_join(t3, 0);
    return 0;
}

最佳答案

Does Linux's SCHED_IDLE just allow idle tasks to run when the core is not actually idle? Or is there something else I might be missing?

这是正确的。 SCHED_IDLE 给出任务 a very low but non-zero weighting - CPU 时间比一个漂亮的 19 任务少大约 70%。

关于c - SCHED_IDLE 是否实际上排除了在非空闲内核上的执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55461648/

相关文章:

c++ - 在 CentOS 6 x64 上构建的应用程序的 32 位版本在较新的 Linux 上启动时会在 `dl_iterate_phdr` 异常期间崩溃

c - Pthreads:我的并行代码在达到一定数量后不会将线程传递到函数中

c - c中的&a,&a[0],a有什么区别

C编译器省略代码,没有错误

c++ - 错误 : lvalue required as left operand of assignment, 我收到此错误什么是左值和右值以及如何删除此错误

c - 使用指针的程序运行不正常

linux - 用于 RHEL 的 gdb-multiarch

c - 结构中的 (file_t)(-1),0 是什么意思?

linux - 如何释放socket?

php - 如何在 PHP 中正确分离和删除 2 个进程之间的共享内存?