sched_setaffinity () для SCHED_DEADLINE - PullRequest
0 голосов
/ 04 мая 2018

Есть ли способ, которым я могу использовать планирование сроков и в то же время установить привязку процессора к процессу в Linux? Я использую ядро ​​4.16. Ниже мой тестовый код:

#define _GNU_SOURCE
#include "include/my_sched.h"
#include <stdio.h>
#include <time.h>
#include <sys/time.h>

int main() {
    struct sched_attr attr;
    int x = 0;
    int ret;
    unsigned int flags = 0;
    long int tid = gettid();

    printf("deadline thread started [%ld]\n", tid);

    /* Set scheduling properties */
    attr.size = sizeof(attr);
    attr.sched_flags = 0;
    attr.sched_nice = 0;
    attr.sched_priority = 0;

    /* This creates a 100ms/300ms reservation */
    attr.sched_policy = SCHED_DEADLINE;
    attr.sched_runtime = 100 * 1000 * 1000;
    attr.sched_period = attr.sched_deadline = 300 * 1000 * 1000;

    ret = sched_setattr(0, &attr, flags);
    if (ret != 0) {
        done = 0;
        perror("sched_setattr");
        printf("exit!\n");
        exit(-1);
    }

    /* Set CPU affinity */
    cpu_set_t  mask;
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    ret = sched_setaffinity(0, sizeof(mask), &mask);

    if (ret != 0) {
        done = 0;
        perror("sched_setaffinity");
        printf("exit!\n");
        exit(-1);
    }


    return 0;
}

Даже если я скомпилирую вышеупомянутую программу и запустлю ее в sudo, я получу ошибку:

sched_setaffinity: Device or resource busy

Если я поменяю местами порядок sched_setattr () и sched_setaffinity (), я получу другую ошибку:

sched_setattr: Operation not permitted

Это происходит, даже если я в Судо.

Есть ли проблемы с моим кодом? Почему я не могу использовать sched_setaffinity () и sched_setattr () с расписанием сроков в одной и той же программе?

Для тех, кому интересно скомпилировать и попробовать программу, ниже приведен код для my_include.h:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <sys/syscall.h>
#include <pthread.h>

#define gettid() syscall(__NR_gettid)

#define SCHED_DEADLINE  6

/* XXX use the proper syscall numbers */
#ifdef __x86_64__
#define __NR_sched_setattr      314
#define __NR_sched_getattr      315
#endif

#ifdef __i386__
#define __NR_sched_setattr      351
#define __NR_sched_getattr      352
#endif

#ifdef __arm__
#define __NR_sched_setattr      380
#define __NR_sched_getattr      381
#endif

static volatile int done;

struct sched_attr {
    __u32 size;

    __u32 sched_policy;
    __u64 sched_flags;

    /* SCHED_NORMAL, SCHED_BATCH */
    __s32 sched_nice;

    /* SCHED_FIFO, SCHED_RR */
    __u32 sched_priority;

    /* SCHED_DEADLINE (nsec) */
    __u64 sched_runtime;
    __u64 sched_deadline;
    __u64 sched_period;
};

int sched_setattr(pid_t pid,
        const struct sched_attr *attr,
        unsigned int flags)
{
    return syscall(__NR_sched_setattr, pid, attr, flags);
}

int sched_getattr(pid_t pid,
        struct sched_attr *attr,
        unsigned int size,
        unsigned int flags)
{
    return syscall(__NR_sched_getattr, pid, attr, size, flags);
}

Что я сделал:

Я попытался покопаться в коде ядра, который выполняет соответствующую проверку работоспособности. Следующий фрагмент кода взят из kernel/sched/core.c:

/*
 * Don't allow tasks with an affinity mask smaller than
 * the entire root_domain to become SCHED_DEADLINE. We
 * will also fail if there's no bandwidth available.
 */
if (!cpumask_subset(span, &p->cpus_allowed) ||
    rq->rd->dl_bw.bw == 0) {
    task_rq_unlock(rq, p, &rf);
    return -EPERM;
}

... 

/*
 * Since bandwidth control happens on root_domain basis,
 * if admission test is enabled, we only admit -deadline
 * tasks allowed to run on all the CPUs in the task's
 * root_domain.
 */
#ifdef CONFIG_SMP
if (task_has_dl_policy(p) && dl_bandwidth_enabled()) {
    rcu_read_lock();
    if (!cpumask_subset(task_rq(p)->rd->span, new_mask)) {
        retval = -EBUSY;
        rcu_read_unlock();
        goto out_free_new_mask;
    }
    rcu_read_unlock();
}

Выше двух разделов соответствуют те две ошибки, которые я упоминал ранее. Может кто-нибудь объяснить мне, что означает комментарий? Я знаю, что такое домен планирования и корневой домен, но я не вижу, чем задача SCHED_DEADLINE отличается от других политик планирования в отношении домена планирования? Почему не имеет смысла связывать задачу SCHED_DEADLINE с конкретным ядром?

1 Ответ

0 голосов
/ 05 мая 2018

После некоторых раскопок я наконец понял, почему установка сходства может вызвать проблемы в планировщиках SCHED_DEADLINE.

Для тех, кто просто хочет связать задачи EDF с подмножеством ядер, вы можете обратиться к https://elixir.bootlin.com/linux/v4.17-rc3/source/Documentation/scheduler/sched-deadline.txt#L634, разделу 5. Вы можете использовать cpuset вместе с утилитой cgroup для назначения ядер задачам EDF.

Запрещение sched_setaffinity () для задач SCHED_DEADLINE - это консервативный подход для обеспечения эффективного тестирования планируемости в ядре Linux . Рассмотрим следующий сценарий, где машина имеет 9 ядер, и задача 1 хочет иметь сродство с ядром 1,2,4,5, а задача 2 хочет иметь сродство с ядром 3,4,5,6,7,8.

enter image description here

Оказывается, что если маски сродства для разных задач SCHED_DEADLINE частично перекрываются, проверка планируемости становится трудной проблемой NP. Поэтому нет эффективного способа определить, можно ли планировать наборы задач. Современный тест планируемости для произвольного сродства ядра требует экспоненциальной вычислительной сложности. Добавление функциональности в этот вид проверки планируемости резко ухудшит производительность ядра.

Однако я бы сказал, что это консервативный подход к достижению планируемости с точки зрения ядра. Это потому, что если администратор Linux знает, что он делает, он может преднамеренно отобразить все задачи SCHED_DEADLINE на определенное подмножество ядер. В следующем примере мы можем посвятить ядро ​​1,2,4,5 задачам EDF. Эффект ничем не отличается от использования подхода cpuset. В любом случае, sched_setaffinity () может эмулировать глобальное, кластерное и секционированное планирование с фиксированным приоритетом на уровне заданий.

enter image description here

справка:

Гуджарати А., Черкейра Ф. и Бранденбург Б.Б. (2014). Многопроцессорное планирование в реальном времени с произвольной привязкой к процессору: от практики к теории. Системы реального времени, 51, 440-483.

...