0001
0002
0003
0004
0005
0006
0007 #include "../kselftest_harness.h"
0008 #include <strings.h>
0009 #include <pthread.h>
0010 #include <numa.h>
0011 #include <numaif.h>
0012 #include <sys/mman.h>
0013 #include <sys/types.h>
0014 #include <signal.h>
0015 #include <time.h>
0016
0017 #define TWOMEG (2<<20)
0018 #define RUNTIME (60)
0019
0020 #define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
0021
0022 FIXTURE(migration)
0023 {
0024 pthread_t *threads;
0025 pid_t *pids;
0026 int nthreads;
0027 int n1;
0028 int n2;
0029 };
0030
0031 FIXTURE_SETUP(migration)
0032 {
0033 int n;
0034
0035 ASSERT_EQ(numa_available(), 0);
0036 self->nthreads = numa_num_task_cpus() - 1;
0037 self->n1 = -1;
0038 self->n2 = -1;
0039
0040 for (n = 0; n < numa_max_possible_node(); n++)
0041 if (numa_bitmask_isbitset(numa_all_nodes_ptr, n)) {
0042 if (self->n1 == -1) {
0043 self->n1 = n;
0044 } else {
0045 self->n2 = n;
0046 break;
0047 }
0048 }
0049
0050 self->threads = malloc(self->nthreads * sizeof(*self->threads));
0051 ASSERT_NE(self->threads, NULL);
0052 self->pids = malloc(self->nthreads * sizeof(*self->pids));
0053 ASSERT_NE(self->pids, NULL);
0054 };
0055
0056 FIXTURE_TEARDOWN(migration)
0057 {
0058 free(self->threads);
0059 free(self->pids);
0060 }
0061
0062 int migrate(uint64_t *ptr, int n1, int n2)
0063 {
0064 int ret, tmp;
0065 int status = 0;
0066 struct timespec ts1, ts2;
0067
0068 if (clock_gettime(CLOCK_MONOTONIC, &ts1))
0069 return -1;
0070
0071 while (1) {
0072 if (clock_gettime(CLOCK_MONOTONIC, &ts2))
0073 return -1;
0074
0075 if (ts2.tv_sec - ts1.tv_sec >= RUNTIME)
0076 return 0;
0077
0078 ret = move_pages(0, 1, (void **) &ptr, &n2, &status,
0079 MPOL_MF_MOVE_ALL);
0080 if (ret) {
0081 if (ret > 0)
0082 printf("Didn't migrate %d pages\n", ret);
0083 else
0084 perror("Couldn't migrate pages");
0085 return -2;
0086 }
0087
0088 tmp = n2;
0089 n2 = n1;
0090 n1 = tmp;
0091 }
0092
0093 return 0;
0094 }
0095
0096 void *access_mem(void *ptr)
0097 {
0098 uint64_t y = 0;
0099 volatile uint64_t *x = ptr;
0100
0101 while (1) {
0102 pthread_testcancel();
0103 y += *x;
0104 }
0105
0106 return NULL;
0107 }
0108
0109
0110
0111
0112
0113
0114 TEST_F_TIMEOUT(migration, private_anon, 2*RUNTIME)
0115 {
0116 uint64_t *ptr;
0117 int i;
0118
0119 if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
0120 SKIP(return, "Not enough threads or NUMA nodes available");
0121
0122 ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
0123 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0124 ASSERT_NE(ptr, MAP_FAILED);
0125
0126 memset(ptr, 0xde, TWOMEG);
0127 for (i = 0; i < self->nthreads - 1; i++)
0128 if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
0129 perror("Couldn't create thread");
0130
0131 ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
0132 for (i = 0; i < self->nthreads - 1; i++)
0133 ASSERT_EQ(pthread_cancel(self->threads[i]), 0);
0134 }
0135
0136
0137
0138
0139 TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
0140 {
0141 pid_t pid;
0142 uint64_t *ptr;
0143 int i;
0144
0145 if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
0146 SKIP(return, "Not enough threads or NUMA nodes available");
0147
0148 ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
0149 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
0150 ASSERT_NE(ptr, MAP_FAILED);
0151
0152 memset(ptr, 0xde, TWOMEG);
0153 for (i = 0; i < self->nthreads - 1; i++) {
0154 pid = fork();
0155 if (!pid)
0156 access_mem(ptr);
0157 else
0158 self->pids[i] = pid;
0159 }
0160
0161 ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
0162 for (i = 0; i < self->nthreads - 1; i++)
0163 ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
0164 }
0165
0166
0167
0168
0169 TEST_F_TIMEOUT(migration, private_anon_thp, 2*RUNTIME)
0170 {
0171 uint64_t *ptr;
0172 int i;
0173
0174 if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
0175 SKIP(return, "Not enough threads or NUMA nodes available");
0176
0177 ptr = mmap(NULL, 2*TWOMEG, PROT_READ | PROT_WRITE,
0178 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0179 ASSERT_NE(ptr, MAP_FAILED);
0180
0181 ptr = (uint64_t *) ALIGN((uintptr_t) ptr, TWOMEG);
0182 ASSERT_EQ(madvise(ptr, TWOMEG, MADV_HUGEPAGE), 0);
0183 memset(ptr, 0xde, TWOMEG);
0184 for (i = 0; i < self->nthreads - 1; i++)
0185 if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
0186 perror("Couldn't create thread");
0187
0188 ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
0189 for (i = 0; i < self->nthreads - 1; i++)
0190 ASSERT_EQ(pthread_cancel(self->threads[i]), 0);
0191 }
0192
0193 TEST_HARNESS_MAIN