-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathvolatile-test-signal.c
181 lines (141 loc) · 3.58 KB
/
volatile-test-signal.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <signal.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;
}
void sigaction_sigbusy(int signum, siginfo_t *info, void *ctxt)
{
char *ptr;
int ret;
char x;
long len;
if (signum != SIGBUS)
return;
ptr = info->si_addr;
mnovolatile(ptr, CHUNK, &ret);
printf("Fixing up data\n");
len = (ptr - vaddr)/CHUNK;
x = 'A' + len;
memset(ptr, x, CHUNK);
printf("%c\n", x);
}
void signal_handler_sigbusy(int signum)
{
if (signum == SIGBUS) {
printf("We received SIGBUSY\n");
}
}
void register_signal_handler()
{
struct sigaction action;
action.sa_sigaction = &sigaction_sigbusy;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
action.sa_restorer = NULL;
sigaction(SIGBUS, &action, NULL);
}
int main(int argc, char *argv[])
{
int i, purged;
char* file = NULL;
int fd;
int pressure = 0;
int opt;
//signal(SIGBUS, signal_handler_sigbusy
//sigaction(SIGBUS, sigaction_sigbusy, NULL);
register_signal_handler();
/* 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) {
file = argv[1];
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;
}
// for(i=0; i < CHUNKNUM; i++)
// printf("%c\n", vaddr[i*CHUNK]);
generate_pressure(pressure);
// 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;
}