当实时优先级线程绑定到一个内核时,move_pages()有时会阻塞

时间:2018-12-11 13:23:02

标签: linux multithreading real-time system-calls numa

程序numa_rt_prio.c在CPU内核4上启动具有策略SCHED_FIFO和实时优先级的后台线程,然后,该程序将一个内存页移动到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()总是成功。 如果后台线程未绑定到任何CPU内核,则move_pages()也总是成功。

即使减少sched_rt_runtime_us也无济于事:

$ cat /proc/sys/kernel/sched_rt_runtime_us 
550000

你知道是什么问题吗?

0 个答案:

没有答案