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