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
12*288bf522SAndroid Build Coastguard Worker #define LINESIZE 32
13*288bf522SAndroid Build Coastguard Worker
thrashing_test(int test_runs,bool cache)14*288bf522SAndroid Build Coastguard Worker int thrashing_test(int test_runs, bool cache) {
15*288bf522SAndroid Build Coastguard Worker int fds[4] = {-1, -1, -1, -1};
16*288bf522SAndroid Build Coastguard Worker char tmpnames[4][17] = { "thrashing1XXXXXX", "thrashing2XXXXXX", "thrashing3XXXXXX", "thrashing4XXXXXX" };
17*288bf522SAndroid Build Coastguard Worker volatile char *bufs[4] = {0};
18*288bf522SAndroid Build Coastguard Worker unsigned long long k;
19*288bf522SAndroid Build Coastguard Worker int ret = -1;
20*288bf522SAndroid Build Coastguard Worker struct timeval begin_time, end_time, elapsed_time, total_time;
21*288bf522SAndroid Build Coastguard Worker unsigned long long filesize;
22*288bf522SAndroid Build Coastguard Worker long num_pages;
23*288bf522SAndroid Build Coastguard Worker long pagesize;
24*288bf522SAndroid Build Coastguard Worker
25*288bf522SAndroid Build Coastguard Worker timerclear(&total_time);
26*288bf522SAndroid Build Coastguard Worker
27*288bf522SAndroid Build Coastguard Worker num_pages = sysconf(_SC_PHYS_PAGES);
28*288bf522SAndroid Build Coastguard Worker pagesize = sysconf(_SC_PAGE_SIZE);
29*288bf522SAndroid Build Coastguard Worker if (num_pages < 0) {
30*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "failed to get the number of pages\n");
31*288bf522SAndroid Build Coastguard Worker return -1;
32*288bf522SAndroid Build Coastguard Worker }
33*288bf522SAndroid Build Coastguard Worker
34*288bf522SAndroid Build Coastguard Worker filesize = num_pages * pagesize / (ARRAY_SIZE(fds) - 1);
35*288bf522SAndroid Build Coastguard Worker
36*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(fds); i++) {
37*288bf522SAndroid Build Coastguard Worker fds[i] = create_tmp_file(tmpnames[i], filesize);
38*288bf522SAndroid Build Coastguard Worker if (fds[i] < 0) {
39*288bf522SAndroid Build Coastguard Worker goto err_fd;
40*288bf522SAndroid Build Coastguard Worker }
41*288bf522SAndroid Build Coastguard Worker }
42*288bf522SAndroid Build Coastguard Worker
43*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(fds); i++) {
44*288bf522SAndroid Build Coastguard Worker bufs[i] = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fds[i], 0);
45*288bf522SAndroid Build Coastguard Worker if (bufs[i] == ((void *)-1)) {
46*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno));
47*288bf522SAndroid Build Coastguard Worker goto err;
48*288bf522SAndroid Build Coastguard Worker }
49*288bf522SAndroid Build Coastguard Worker if (!cache) {
50*288bf522SAndroid Build Coastguard Worker //madvise and fadvise as random to prevent prefetching
51*288bf522SAndroid Build Coastguard Worker ret = madvise((void *)bufs[i], filesize, MADV_RANDOM) ||
52*288bf522SAndroid Build Coastguard Worker posix_fadvise(fds[i], 0, filesize, POSIX_FADV_RANDOM);
53*288bf522SAndroid Build Coastguard Worker if (ret) {
54*288bf522SAndroid Build Coastguard Worker goto err;
55*288bf522SAndroid Build Coastguard Worker }
56*288bf522SAndroid Build Coastguard Worker }
57*288bf522SAndroid Build Coastguard Worker }
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker for (int i = 0; i < test_runs; i++) {
60*288bf522SAndroid Build Coastguard Worker for (size_t j = 0; j < ARRAY_SIZE(fds); j++) {
61*288bf522SAndroid Build Coastguard Worker gettimeofday(&begin_time, NULL);
62*288bf522SAndroid Build Coastguard Worker for (k = 0; k < filesize; k += pagesize) {
63*288bf522SAndroid Build Coastguard Worker bufs[j][k];
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker gettimeofday(&end_time, NULL);
66*288bf522SAndroid Build Coastguard Worker
67*288bf522SAndroid Build Coastguard Worker timersub(&end_time, &begin_time, &elapsed_time);
68*288bf522SAndroid Build Coastguard Worker timeradd(&total_time, &elapsed_time, &total_time);
69*288bf522SAndroid Build Coastguard Worker }
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker
72*288bf522SAndroid Build Coastguard Worker printf("%scached thrashing: %llu MB/s\n", cache ? "" : "un",
73*288bf522SAndroid Build Coastguard Worker (filesize * ARRAY_SIZE(fds) * test_runs * USEC_PER_SEC) /
74*288bf522SAndroid Build Coastguard Worker (1024 * 1024 * (total_time.tv_sec * USEC_PER_SEC + total_time.tv_usec)));
75*288bf522SAndroid Build Coastguard Worker
76*288bf522SAndroid Build Coastguard Worker ret = 0;
77*288bf522SAndroid Build Coastguard Worker
78*288bf522SAndroid Build Coastguard Worker err:
79*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(bufs) && bufs[i] != NULL; i++) {
80*288bf522SAndroid Build Coastguard Worker munmap((void *)bufs[i], filesize);
81*288bf522SAndroid Build Coastguard Worker }
82*288bf522SAndroid Build Coastguard Worker err_fd:
83*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(fds) && fds[i] >= 0; i++) {
84*288bf522SAndroid Build Coastguard Worker close(fds[i]);
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker return ret;
87*288bf522SAndroid Build Coastguard Worker }
88