1*288bf522SAndroid Build Coastguard Worker #include <errno.h>
2*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
3*288bf522SAndroid Build Coastguard Worker #include <stdbool.h>
4*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
5*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
6*288bf522SAndroid Build Coastguard Worker #include <string.h>
7*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
8*288bf522SAndroid Build Coastguard Worker #include <sys/time.h>
9*288bf522SAndroid Build Coastguard Worker
10*288bf522SAndroid Build Coastguard Worker #include "pagingtest.h"
11*288bf522SAndroid Build Coastguard Worker
pageinout_test(int test_runs,bool cache,unsigned long long file_size)12*288bf522SAndroid Build Coastguard Worker int pageinout_test(int test_runs, bool cache, unsigned long long file_size) {
13*288bf522SAndroid Build Coastguard Worker int fd;
14*288bf522SAndroid Build Coastguard Worker char tmpname[] = "pageinoutXXXXXX";
15*288bf522SAndroid Build Coastguard Worker unsigned char *vec;
16*288bf522SAndroid Build Coastguard Worker int i;
17*288bf522SAndroid Build Coastguard Worker unsigned long long j;
18*288bf522SAndroid Build Coastguard Worker volatile char *buf;
19*288bf522SAndroid Build Coastguard Worker int ret = -1;
20*288bf522SAndroid Build Coastguard Worker int rc;
21*288bf522SAndroid Build Coastguard Worker struct timeval begin_time, end_time, elapsed_time, total_time_in, total_time_out;
22*288bf522SAndroid Build Coastguard Worker long pagesize = sysconf(_SC_PAGE_SIZE);
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker timerclear(&total_time_in);
25*288bf522SAndroid Build Coastguard Worker timerclear(&total_time_out);
26*288bf522SAndroid Build Coastguard Worker
27*288bf522SAndroid Build Coastguard Worker fd = create_tmp_file(tmpname, file_size);
28*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
29*288bf522SAndroid Build Coastguard Worker return -1;
30*288bf522SAndroid Build Coastguard Worker }
31*288bf522SAndroid Build Coastguard Worker
32*288bf522SAndroid Build Coastguard Worker vec = alloc_mincore_vec(file_size);
33*288bf522SAndroid Build Coastguard Worker if (vec == NULL) {
34*288bf522SAndroid Build Coastguard Worker goto err_alloc;
35*288bf522SAndroid Build Coastguard Worker }
36*288bf522SAndroid Build Coastguard Worker
37*288bf522SAndroid Build Coastguard Worker buf = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
38*288bf522SAndroid Build Coastguard Worker if (buf == ((void *)-1)) {
39*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno));
40*288bf522SAndroid Build Coastguard Worker goto err_mmap;
41*288bf522SAndroid Build Coastguard Worker }
42*288bf522SAndroid Build Coastguard Worker
43*288bf522SAndroid Build Coastguard Worker if (!check_caching((void *)buf, vec, file_size, false)) {
44*288bf522SAndroid Build Coastguard Worker goto err;
45*288bf522SAndroid Build Coastguard Worker }
46*288bf522SAndroid Build Coastguard Worker
47*288bf522SAndroid Build Coastguard Worker if (!cache) {
48*288bf522SAndroid Build Coastguard Worker //madvise and fadvise as random to prevent prefetching
49*288bf522SAndroid Build Coastguard Worker rc = madvise((void *)buf, file_size, MADV_RANDOM) ||
50*288bf522SAndroid Build Coastguard Worker posix_fadvise(fd, 0, file_size, POSIX_FADV_RANDOM);
51*288bf522SAndroid Build Coastguard Worker if (rc) {
52*288bf522SAndroid Build Coastguard Worker goto err;
53*288bf522SAndroid Build Coastguard Worker }
54*288bf522SAndroid Build Coastguard Worker }
55*288bf522SAndroid Build Coastguard Worker
56*288bf522SAndroid Build Coastguard Worker for (i = 0; i < test_runs; i++) {
57*288bf522SAndroid Build Coastguard Worker gettimeofday(&begin_time, NULL);
58*288bf522SAndroid Build Coastguard Worker //read every page into the page cache
59*288bf522SAndroid Build Coastguard Worker for (j = 0; j < file_size; j += pagesize) {
60*288bf522SAndroid Build Coastguard Worker buf[j];
61*288bf522SAndroid Build Coastguard Worker }
62*288bf522SAndroid Build Coastguard Worker gettimeofday(&end_time, NULL);
63*288bf522SAndroid Build Coastguard Worker
64*288bf522SAndroid Build Coastguard Worker timersub(&end_time, &begin_time, &elapsed_time);
65*288bf522SAndroid Build Coastguard Worker timeradd(&total_time_in, &elapsed_time, &total_time_in);
66*288bf522SAndroid Build Coastguard Worker
67*288bf522SAndroid Build Coastguard Worker if (!check_caching((void *)buf, vec, file_size, true)) {
68*288bf522SAndroid Build Coastguard Worker goto err;
69*288bf522SAndroid Build Coastguard Worker }
70*288bf522SAndroid Build Coastguard Worker
71*288bf522SAndroid Build Coastguard Worker gettimeofday(&begin_time, NULL);
72*288bf522SAndroid Build Coastguard Worker rc = madvise((void *)buf, file_size, MADV_DONTNEED) ||
73*288bf522SAndroid Build Coastguard Worker posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED);
74*288bf522SAndroid Build Coastguard Worker gettimeofday(&end_time, NULL);
75*288bf522SAndroid Build Coastguard Worker if (rc) {
76*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "posix_fadvise/madvise DONTNEED failed\n");
77*288bf522SAndroid Build Coastguard Worker goto err;
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker
80*288bf522SAndroid Build Coastguard Worker timersub(&end_time, &begin_time, &elapsed_time);
81*288bf522SAndroid Build Coastguard Worker timeradd(&total_time_out, &elapsed_time, &total_time_out);
82*288bf522SAndroid Build Coastguard Worker
83*288bf522SAndroid Build Coastguard Worker if (!check_caching((void *)buf, vec, file_size, false)) {
84*288bf522SAndroid Build Coastguard Worker goto err;
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker }
87*288bf522SAndroid Build Coastguard Worker
88*288bf522SAndroid Build Coastguard Worker printf("%scached page-in: %llu MB/s\n", cache ? "" : "un",
89*288bf522SAndroid Build Coastguard Worker (file_size * test_runs * USEC_PER_SEC) /
90*288bf522SAndroid Build Coastguard Worker (1024 * 1024 * (total_time_in.tv_sec * USEC_PER_SEC + total_time_in.tv_usec)));
91*288bf522SAndroid Build Coastguard Worker printf("%scached page-out (clean): %llu MB/s\n", cache ? "" : "un",
92*288bf522SAndroid Build Coastguard Worker (file_size * test_runs * USEC_PER_SEC) /
93*288bf522SAndroid Build Coastguard Worker (1024 * 1024 * (total_time_out.tv_sec * USEC_PER_SEC + total_time_out.tv_usec)));
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Worker ret = 0;
96*288bf522SAndroid Build Coastguard Worker
97*288bf522SAndroid Build Coastguard Worker err:
98*288bf522SAndroid Build Coastguard Worker munmap((void *)buf, file_size);
99*288bf522SAndroid Build Coastguard Worker err_mmap:
100*288bf522SAndroid Build Coastguard Worker free(vec);
101*288bf522SAndroid Build Coastguard Worker err_alloc:
102*288bf522SAndroid Build Coastguard Worker close(fd);
103*288bf522SAndroid Build Coastguard Worker return ret;
104*288bf522SAndroid Build Coastguard Worker }
105