forked from volatile-ranges-test/vranges-test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
volatile-test.c
134 lines (102 loc) · 2.72 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
133
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/wait.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;
#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) {
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 = NULL;
int fd;
int pressure = 0;
int opt;
/* Process arguments */
while ((opt = getopt(argc, argv, "p:f:"))!=-1) {
switch(opt) {
case 'p':
pressure = atoi(optarg);
break;
case 'f':
file = optarg;
break;
default:
printf("Usage: %s [-p <mempressure in megs>] [-f <filename>]\n", argv[0]);
printf(" -p: Amount of memory pressure to generate\n");
printf(" -f: Use a file\n");
exit(-1);
}
}
if (file) {
printf("Using file %s\n", file);
fd = open(file, O_RDWR);
vaddr = mmap(0, FULLSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
} else {
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;
}
printf("Generating %i megs of pressure\n", pressure);
generate_pressure(pressure);
for(i=0; i < CHUNKNUM; ) {
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;
}