forked from volatile-ranges-test/vranges-test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
volatile-test.c
132 lines (98 loc) · 2.48 KB
/
volatile-test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>
#define SYS_vrange 314
#define VRANGE_VOLATILE 0 /* unpin all pages so VM can discard them */
#define VRANGE_NOVOLATILE 1 /* pin all pages so VM can't discard them */
#define VRANGE_MODE_SHARED 0x1 /* discard all pages of the range */
#define VRANGE_MODE 0x1
static int vrange(unsigned long start, size_t length, int mode, int *purged)
{
return syscall(SYS_vrange, start, length, mode, purged);
}
static int mvolatile(void *addr, size_t length)
{
return vrange((long)addr, length, VRANGE_VOLATILE, 0);
}
static int mnovolatile(void *addr, size_t length, int* purged)
{
return vrange((long)addr, length, VRANGE_NOVOLATILE, purged);
}
char* vaddr;
int is_anon = 0;
#define PAGE_SIZE (4*1024)
#define CHUNK (4*1024*4)
#define CHUNKNUM 26
#define FULLSIZE (CHUNK*CHUNKNUM + 2*PAGE_SIZE)
void generate_pressure(megs)
{
pid_t child;
int one_meg = 1024*1024;
char *addr;
int i, status;
child = fork();
if (!child) {
if (is_anon) {
/* make sure we write to all the vrange pages
* in order to break the copy-on-write
*/
for(i=0; i < CHUNKNUM; i++)
memset(vaddr + (i*CHUNK), '0', CHUNK);
}
for (i=0; i < megs; i++) {
addr = malloc(one_meg);
bzero(addr, one_meg);
}
exit(0);
}
waitpid(child, &status, 0);
return;
}
int main(int argc, char *argv[])
{
int i, purged;
char* file;
int fd;
int is_file = 0;
if (argc > 1) {
file = argv[1];
fd = open(file, O_RDWR);
vaddr = mmap(0, FULLSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
is_file = 1;
} else {
is_anon = 1;
vaddr = malloc(FULLSIZE);
}
purged = 0;
vaddr += PAGE_SIZE-1;
vaddr -= (long)vaddr % PAGE_SIZE;
for(i=0; i < CHUNKNUM; i++)
memset(vaddr + (i*CHUNK), 'A'+i, CHUNK);
for(i=0; i < CHUNKNUM; ) {
mvolatile(vaddr + (i*CHUNK), CHUNK);
i+=2;
}
// for(i=0; i < CHUNKNUM; i++)
// printf("%c\n", vaddr[i*CHUNK]);
generate_pressure(3);
// for(i=0; i < CHUNKNUM; i++)
// printf("%c\n", vaddr[i*CHUNK]);
for(i=0; i < CHUNKNUM; ) {
int ret;
ret = mnovolatile(vaddr + (i*CHUNK), CHUNK, &purged);
i+=2;
}
if (purged)
printf("Data purged!\n");
for(i=0; i < CHUNKNUM; i++)
printf("%c\n", vaddr[i*CHUNK]);
return 0;
}