move_pages () иногда блокируется, когда приоритетный поток в реальном времени привязан к одному ядру - PullRequest
0 голосов
/ 11 декабря 2018

Программа numa_rt_prio.c запускает фоновый поток с политикой SCHED_FIFO и приоритетом в реальном времени на ядре 4 процессора, а затем программа перемещает одну страницу памяти на узел NUMA 0:

#define _GNU_SOURCE
#include <assert.h>
#include <numa.h>
#include <numaif.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

const int MY_POLICY= SCHED_FIFO;
const int MY_PRIORITY= 10;

struct ThreadCtrl
{
    volatile int terminationRequested;
};

static void *startRoutine(void *args)
{
    struct ThreadCtrl *ctrl= (struct ThreadCtrl *) args;

    while (! ctrl->terminationRequested)
    {
    }

    return 0;
}

int main(int argc, char **argv)
{
    int error= 0;

    pthread_attr_t attr;
    error= pthread_attr_init(&attr);
    assert(error == 0);

    const int THREAD_CORE= 4;
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(THREAD_CORE, &cpuset);
    error= pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
    assert(error == 0);

    error= pthread_attr_setschedpolicy(&attr, MY_POLICY);
    assert(error == 0);

    error= pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    assert(error == 0);

    struct sched_param threadParam;
    error= pthread_attr_getschedparam(&attr, &threadParam);
    assert(error == 0);

    threadParam.sched_priority= MY_PRIORITY;
    error= pthread_attr_setschedparam(&attr, &threadParam);
    assert(error == 0);

    pthread_t thread;
    struct ThreadCtrl threadCtrl= {.terminationRequested = 0};
    error= pthread_create(&thread, &attr, startRoutine, &threadCtrl);
    assert(error == 0);

    printf("Sleeping and waiting until thread runs ...\n");
    sleep(3);
    printf("Awaked\n");

    const size_t BUF_SIZE= 42;
    void *ptr;
    error= posix_memalign(&ptr, sysconf(_SC_PAGE_SIZE), BUF_SIZE);
    assert(error == 0);
    char *buf= ptr;
    memset(buf, 0, BUF_SIZE);

    int pageNode= 0;
    int status= -1;
    ptr= buf;
    printf("Moving one page ...\n");
    error= move_pages(0, 1, &ptr, &pageNode, &status, MPOL_MF_MOVE);
    assert(error == 0);
    assert(status == pageNode);
    printf("One page has been moved ...\n");

    threadCtrl.terminationRequested= 1;
    error= pthread_join(thread, 0);
    assert(error == 0);

    return EXIT_SUCCESS;
}

После компиляциис cc -Wall -o numa_rt_prio -pthread numa_rt_prio.c -lnuma вызов (конечно как root) иногда блокируется:

# ./numa_rt_prio
Sleeping and waiting until thread runs ...
Awaked
Moving one page ...

Но иногда программа запускается без проблем:

# ./numa_rt_prio 
Sleeping and waiting until thread runs ...
Awaked
Moving one page ...
One page has been moved ...

Если фоновый поток выполняется безприоритеты реального времени, move_pages () всегда успешно выполняется.Если фоновый поток не привязан к какому-либо ядру ЦП, move_pages () также всегда успешно выполняется.

Даже уменьшение sched_rt_runtime_us не помогает:

$ cat /proc/sys/kernel/sched_rt_runtime_us 
550000

Есть ли у вас какие-либо представления о том, чтопроблема?

...