程序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
你知道是什么问题吗?