-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemalloc.c
More file actions
121 lines (103 loc) · 3.48 KB
/
memalloc.c
File metadata and controls
121 lines (103 loc) · 3.48 KB
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
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define SIZE_4KB (4 * 1024)
#define SIZE_1GB (1024 * 1024 * 1024)
#define SIZE_256MB (256 * 1024 * 1024)
#define SIZE_512MB (512 * 1024 * 1024)
#define LKP_FILE "/proc/lkp25p3"
// Structure to hold the buffer and the region to read
typedef struct {
void *buffer;
uintptr_t start;
uintptr_t end;
struct timespec delay;
} read_region_args;
/* Access all pages for the memory bounded by `start` and `end` */
void *read_region(void *arg) {
printf("Reading region with delay\n");
read_region_args *args = (read_region_args *)arg;
do {
for (uintptr_t addr = args->start; addr < args->end; addr += SIZE_4KB) {
*((unsigned char *)addr) = 1;
}
nanosleep(&args->delay, NULL);
} while (1);
pthread_exit(NULL);
}
int main() {
/* Allocate 1GB of memory */
void *buffer = calloc(1, SIZE_1GB);
if (buffer == NULL) {
perror("calloc failed");
return 1;
}
/* FORCE PAGE ACCESS : to ensure the pages are mapped to their physical
* memory*/
volatile char *touch_ptr = (volatile char *)buffer;
size_t touch_offset = 0;
while (touch_offset < SIZE_1GB) {
touch_ptr[touch_offset] = 0;
touch_offset += SIZE_4KB;
}
/* Write the virtual memory address to /proc/lkp25p3 */
int lkp_fd = open(LKP_FILE, O_WRONLY);
if (lkp_fd == -1) {
perror("open " LKP_FILE " failed");
return 1;
}
char va_string[32];
snprintf(va_string, sizeof(va_string), "%p", buffer);
ssize_t bytes_written = write(lkp_fd, &va_string, sizeof(va_string));
if (bytes_written != sizeof(va_string)) {
perror("write to " LKP_FILE " failed");
close(lkp_fd);
return 1;
}
close(lkp_fd);
printf("Allocated 1GB at address: %p. Address written to %s\n", buffer,
LKP_FILE);
/* Spawn 2 threads for accessing sections of memory at different speeds */
pthread_t fast_read_thread, slow_read_thread;
read_region_args fast_args, slow_args;
struct timespec fast_read_delay = {0, 1}; // Delay: 1ns
struct timespec slow_read_delay = {0, 1000000}; // Delay: 1ms
fast_args.buffer = buffer;
fast_args.start = (uintptr_t)buffer;
fast_args.end = (uintptr_t)buffer + (SIZE_256MB);
fast_args.delay = fast_read_delay;
if (pthread_create(&fast_read_thread, NULL, read_region,
(void *)&fast_args) != 0) {
perror("pthread_create for fast reader failed");
free(buffer);
return 1;
}
slow_args.buffer = buffer;
slow_args.start = (uintptr_t)buffer + (SIZE_256MB);
slow_args.end = (uintptr_t)buffer + (SIZE_512MB);
slow_args.delay = slow_read_delay;
if (pthread_create(&slow_read_thread, NULL, read_region,
(void *)&slow_args) != 0) {
perror("pthread_create for slow reader failed");
pthread_cancel(fast_read_thread);
free(buffer);
return 1;
}
printf("Accessing pages for 2 minutes...\n");
sleep(120);
printf("Finished reading pages.\n");
/* Clean up threads */
pthread_cancel(fast_read_thread);
pthread_cancel(slow_read_thread);
pthread_join(fast_read_thread, NULL);
pthread_join(slow_read_thread, NULL);
/* Wait for user input before releasing the memory - to ensure clean exit of
* kernel module */
getchar();
free(buffer);
return 0;
}