16e86b511cfbdbd3f52cd228f52822e9602a23bb4Yabin Cui#include "pagingtest.h"
26e86b511cfbdbd3f52cd228f52822e9602a23bb4Yabin Cui
36e86b511cfbdbd3f52cd228f52822e9602a23bb4Yabin Cui#include <errno.h>
4611dba4c6a194ce0ffa6e43907aa9881f39d27e3Yabin Cui#include <fcntl.h>
5de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#include <stdio.h>
6de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#include <stdlib.h>
7de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#include <string.h>
8de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#include <sys/mman.h>
9de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#include <sys/stat.h>
106e86b511cfbdbd3f52cd228f52822e9602a23bb4Yabin Cui#include <sys/types.h>
116e86b511cfbdbd3f52cd228f52822e9602a23bb4Yabin Cui#include <unistd.h>
12de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
13de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#define TEST_RUNS 10
14de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#define ALLOC_SIZE (10 * 1024 * 1024)
15de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand#define FILE_SIZE (10 * 1024 * 1024)
16de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
17de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchandint create_tmp_file(char *filename, off_t size) {
18de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    void *buf;
19de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    ssize_t rc;
20de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    int fd;
21de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    int urandom;
22de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
23de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    fd = mkstemp(filename);
24de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (fd < 0) {
25de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "unable to create temp file: %s\n", strerror(errno));
26de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err_mkstemp;
27de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
28de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
29de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    urandom = open("/dev/urandom", O_RDONLY);
30de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (urandom < 0) {
31de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "unable to open urandom: %s\n", strerror(errno));
32de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err_open;
33de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
34de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
35de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (unlink(filename)) {
36de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "unable to unlink temp file: %s\n", strerror(errno));
37de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err_unlink;
38de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
39de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
40de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (ftruncate(fd, size)) {
41de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "unable to allocate temp file: %s\n", strerror(errno));
42de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err_truncate;
43de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
44de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
45de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    buf = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
46de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (buf == (void *)-1) {
47de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "unable to mmap temp file: %s\n", strerror(errno));
48de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err_mmap;
49de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
50de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
51de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    rc = read(urandom, buf, size);
52de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
53de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (rc < 0) {
54de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "write random data failed: %s\n", strerror(errno));
55de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err;
56de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
57de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
58de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (rc != size) {
59de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "write random data incomplete\n");
60de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err;
61de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
62de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
63de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (madvise(buf, size, MADV_DONTNEED)) {
64de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "madvise DONTNEED failed: %s\n", strerror(errno));
65de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err;
66de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
67de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
68de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (fsync(fd) < 0) {
69de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "fsync failed: %s\n", strerror(errno));
70de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err;
71de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
72de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
73de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    rc = posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED);
74de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (rc) {
75de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "fadvise DONTNEED failed: %s\n", strerror(errno));
76de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        goto err;
77de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
78de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
79de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    munmap(buf, size);
80de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    close(urandom);
81de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    return fd;
82de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
83de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr:
84de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    munmap(buf, size);
85de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr_mmap:
86de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr_truncate:
87de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr_unlink:
88de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    close(urandom);
89de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr_open:
90de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    close(fd);
91de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchanderr_mkstemp:
92de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    return -1;
93de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand}
94de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
95de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchandunsigned char *alloc_mincore_vec(size_t size) {
96de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    unsigned char *vec;
97de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
98de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    vec = malloc(mincore_vec_len(size));
99de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (vec == NULL) {
100de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "malloc failed\n");
101de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
102de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
103de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    return vec;
104de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand}
105de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
106de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchandbool check_caching(void *buf, unsigned char *vec, size_t size, bool is_cached) {
107de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    bool ret = true;
108de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    size_t i;
109de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
110de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (mincore(buf, size, vec)) {
111de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        fprintf(stderr, "mincore failed: %s\n", strerror(errno));
112de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        return false;
113de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
114de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
115de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (is_cached) {
116de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        for (i = 0; i < mincore_vec_len(size); i++) {
117de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand            if (!(vec[i] & 0x1)) {
118de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand                fprintf(stderr, "found an uncached page at page offset %zd\n", i);
119de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand                ret = false;
120de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand            }
121de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        }
122de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    } else {
123de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        for (i = 0; i < mincore_vec_len(size); i++) {
124de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand            if (vec[i] & 0x1) {
125de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand                fprintf(stderr, "found a cached page at page offset %zd\n", i);
126de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand                ret = false;
127de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand            }
128de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        }
129de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
130de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
131de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    return ret;
132de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand}
133de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
134de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchandint main(int argc, char **argv) {
135de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    unsigned long long alloc_size = 0ULL;
136de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    unsigned long long file_size = 0ULL;
137de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    int test_runs = 0;
138de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    int rc;
139de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
140de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    //arguments: <program> [test_runs [alloc_size [file_size]]]
141de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (argc >= 2) {
142de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        test_runs = atoi(argv[1]);
143de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
144de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (test_runs <= 0) {
145de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        test_runs = TEST_RUNS;
146de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
147de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (argc >= 3) {
148de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        alloc_size = strtoull(argv[2], NULL, 10);
149de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
150de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (!alloc_size) {
151de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        alloc_size = ALLOC_SIZE;
152de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
153de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (argc >= 4) {
154de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        file_size = strtoull(argv[3], NULL, 10);
155de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
156de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (!file_size) {
157de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        file_size = FILE_SIZE;
158de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
159de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
160de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    rc = mmap_test(test_runs, alloc_size);
161de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (rc) {
162de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        return rc;
163de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
164de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    rc = pageinout_test(test_runs, file_size);
165de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    if (rc) {
166de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand        return rc;
167de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    }
168de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    rc = thrashing_test(test_runs);
169de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand
170de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand    return rc;
171de3942afaa4a84529f7c110fe302bb2b346fbe23Rom Lemarchand}
172