File srhd.c changed (mode: 100644) (index 4af0777..e3414ce) |
|
1 |
|
/* |
|
2 |
|
* Stop Row Hammer |
|
3 |
|
* Copyright: Catalin(ux) M. BOIE |
|
4 |
|
* After an idea found on Project Zero Google site |
|
5 |
|
* (http://googleprojectzero.blogspot.ro/2015/03/exploiting-dram-rowhammer-bug-to-gain.html) |
|
6 |
|
* |
|
7 |
|
* TODO: investigate PERF_TYPE_BREAKPOINT |
|
8 |
|
*/ |
|
9 |
|
|
1 |
10 |
#include <stdlib.h> |
#include <stdlib.h> |
2 |
11 |
#include <stdio.h> |
#include <stdio.h> |
3 |
12 |
#include <unistd.h> |
#include <unistd.h> |
|
11 |
20 |
#include <asm/unistd.h> |
#include <asm/unistd.h> |
12 |
21 |
#include <sys/epoll.h> |
#include <sys/epoll.h> |
13 |
22 |
#include <signal.h> |
#include <signal.h> |
|
23 |
|
#include <sys/time.h> |
|
24 |
|
#include <sys/types.h> |
|
25 |
|
#include <sys/stat.h> |
|
26 |
|
#include <fcntl.h> |
|
27 |
|
|
|
28 |
|
#define MISSES_SUSPEND_TRIGGER 20000 /* How many events will trigger a suspend */ |
|
29 |
|
#define MISS_TRIGGER 10000 /* How many perf counts events will trigger an epoll wakeup */ |
|
30 |
|
#define PENALTY_TIME 100 /* how much time to suspend the process (in milliseconds) */ |
|
31 |
|
#define MMAP_BUF_SIZE 1 /* in pages */ |
|
32 |
|
#define PID_HASH_SIZE 128 |
14 |
33 |
|
|
15 |
34 |
#define barrier() asm volatile ("" ::: "memory") |
#define barrier() asm volatile ("" ::: "memory") |
16 |
35 |
|
|
17 |
|
#define MMAP_BUF_SIZE 8 /* in pages */ |
|
|
36 |
|
/* This tructure will keep track of suspect pids */ |
|
37 |
|
struct pid_cell |
|
38 |
|
{ |
|
39 |
|
int pid; |
|
40 |
|
struct pid_cell *next; |
|
41 |
|
struct pid_cell *next_in_queue; /* used for suspend queue */ |
|
42 |
|
unsigned long misses; /* how many misses this process got */ |
|
43 |
|
unsigned int suspends; /* how many suspends this pid got */ |
|
44 |
|
struct timeval start; |
|
45 |
|
struct timeval wake; |
|
46 |
|
unsigned int uid; |
|
47 |
|
char cmd[128]; |
|
48 |
|
}; |
|
49 |
|
static struct pid_cell *pid_hash[PID_HASH_SIZE]; |
|
50 |
|
|
|
51 |
|
/* Queue that will store the entries that will need unblocking */ |
|
52 |
|
static struct pid_cell *queue_head, *queue_tail; |
|
53 |
|
|
|
54 |
|
static unsigned long page_size; |
|
55 |
|
|
18 |
56 |
|
|
19 |
|
static unsigned long page_size; |
|
|
57 |
|
/* |
|
58 |
|
* Difference in milliseconds between two timeval structures |
|
59 |
|
*/ |
|
60 |
|
static long time_diff(const struct timeval *t1, const struct timeval *t2) |
|
61 |
|
{ |
|
62 |
|
return (t1->tv_sec - t2->tv_sec) * 1000 |
|
63 |
|
+ (t1->tv_usec - t2->tv_usec) / 1000; |
|
64 |
|
} |
20 |
65 |
|
|
21 |
66 |
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, |
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, |
22 |
67 |
int cpu, int group_fd, unsigned long flags) |
int cpu, int group_fd, unsigned long flags) |
|
... |
... |
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, |
24 |
69 |
return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); |
return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); |
25 |
70 |
} |
} |
26 |
71 |
|
|
27 |
|
// TODO: investigate PERF_TYPE_BREAKPOINT |
|
|
72 |
|
/* |
|
73 |
|
* Lookup proc info |
|
74 |
|
*/ |
|
75 |
|
static void lookup_proc_info(struct pid_cell *p) |
|
76 |
|
{ |
|
77 |
|
struct stat S; |
|
78 |
|
char path[128]; |
|
79 |
|
int fd; |
|
80 |
|
ssize_t n; |
|
81 |
|
|
|
82 |
|
snprintf(path, sizeof(path), "/proc/%d/cmdline", p->pid); |
|
83 |
|
if (stat(path, &S) != 0) |
|
84 |
|
return; |
|
85 |
|
|
|
86 |
|
fd = open(path, O_RDONLY); |
|
87 |
|
if (fd != -1) { |
|
88 |
|
n = read(fd, p->cmd, sizeof(p->cmd) - 1); |
|
89 |
|
if (n > 0) { |
|
90 |
|
int i; |
|
91 |
|
|
|
92 |
|
for (i = 0; i < n; i++) { |
|
93 |
|
if (p->cmd[i] == '\0') |
|
94 |
|
p->cmd[i] = ' '; |
|
95 |
|
} |
|
96 |
|
p->cmd[n] = '\0'; |
|
97 |
|
} |
|
98 |
|
close(fd); |
|
99 |
|
} |
|
100 |
|
|
|
101 |
|
p->uid = S.st_uid; |
|
102 |
|
} |
|
103 |
|
|
|
104 |
|
/* |
|
105 |
|
* Suspends a pid |
|
106 |
|
*/ |
|
107 |
|
static void pid_suspend(const struct timeval *now, struct pid_cell *p) |
|
108 |
|
{ |
|
109 |
|
int r; |
|
110 |
|
|
|
111 |
|
/* I will not block myself */ |
|
112 |
|
if (p->pid == getpid()) |
|
113 |
|
return; |
|
114 |
|
|
|
115 |
|
/* We do not block root processes */ |
|
116 |
|
if (p->uid == 0) |
|
117 |
|
return; |
|
118 |
|
|
|
119 |
|
/* TODO */ |
|
120 |
|
if (p->uid != 503) |
|
121 |
|
return; |
|
122 |
|
|
|
123 |
|
r = kill(p->pid, SIGSTOP); |
|
124 |
|
if (r != 0) |
|
125 |
|
fprintf(stderr, "Cannot suspend pid: %s!\n", strerror(errno)); |
|
126 |
|
|
|
127 |
|
fprintf(stderr, "Suspended pid %d (uid %u) [%s]...\n", |
|
128 |
|
p->pid, p->uid, p->cmd); |
|
129 |
|
|
|
130 |
|
p->suspends++; |
|
131 |
|
p->wake = *now; |
|
132 |
|
if (p->wake.tv_usec > 1000000 - PENALTY_TIME) { |
|
133 |
|
p->wake.tv_sec++; |
|
134 |
|
p->wake.tv_usec = 1000000 - p->wake.tv_usec + PENALTY_TIME; |
|
135 |
|
} else { |
|
136 |
|
p->wake.tv_usec += PENALTY_TIME; |
|
137 |
|
} |
|
138 |
|
|
|
139 |
|
/* To be able to resume it, add it to the resume queue */ |
|
140 |
|
if (queue_head == NULL) |
|
141 |
|
queue_head = p; |
|
142 |
|
else |
|
143 |
|
queue_tail->next_in_queue = p; |
|
144 |
|
queue_tail = p; |
|
145 |
|
} |
|
146 |
|
|
|
147 |
|
/* |
|
148 |
|
* Un-suspends a pid |
|
149 |
|
*/ |
|
150 |
|
static void pid_unsuspend(struct pid_cell *p) |
|
151 |
|
{ |
|
152 |
|
int r; |
|
153 |
|
|
|
154 |
|
fprintf(stderr, "Un-suspend pid %d (uid %u) [%s]...\n", |
|
155 |
|
p->pid, p->uid, p->cmd); |
|
156 |
|
|
|
157 |
|
r = kill(p->pid, SIGCONT); |
|
158 |
|
if (r != 0) |
|
159 |
|
fprintf(stderr, "Cannot un-suspend pid: %s!\n", strerror(errno)); |
|
160 |
|
|
|
161 |
|
p->start.tv_sec = 0; |
|
162 |
|
p->start.tv_usec = 0; |
|
163 |
|
p->misses = 0; |
|
164 |
|
} |
|
165 |
|
|
|
166 |
|
/* |
|
167 |
|
* Adds a pid to suspect list, and suspend it if needed |
|
168 |
|
*/ |
|
169 |
|
static void pid_hash_add(const int pid) |
|
170 |
|
{ |
|
171 |
|
unsigned int i; |
|
172 |
|
struct pid_cell *p, *q; |
|
173 |
|
struct timeval now; |
|
174 |
|
float misses_per_second; |
|
175 |
|
int diff; |
|
176 |
|
|
|
177 |
|
i = pid % PID_HASH_SIZE; |
|
178 |
|
|
|
179 |
|
/* First, search for it */ |
|
180 |
|
q = pid_hash[i]; |
|
181 |
|
while (q) { |
|
182 |
|
if (q->pid == pid) |
|
183 |
|
break; |
|
184 |
|
|
|
185 |
|
q = q->next; |
|
186 |
|
} |
|
187 |
|
|
|
188 |
|
gettimeofday(&now, NULL); |
|
189 |
|
|
|
190 |
|
if (q) { |
|
191 |
|
/* Found an old entry */ |
|
192 |
|
q->misses += MISS_TRIGGER; |
|
193 |
|
|
|
194 |
|
if (q->start.tv_sec == 0) { |
|
195 |
|
q->start = now; |
|
196 |
|
return; |
|
197 |
|
} |
|
198 |
|
|
|
199 |
|
/* Compute the number of misses per second */ |
|
200 |
|
diff = time_diff(&now, &q->start); |
|
201 |
|
misses_per_second = q->misses; |
|
202 |
|
misses_per_second /= diff; |
|
203 |
|
misses_per_second *= 1000; /* ms -> s */ |
|
204 |
|
|
|
205 |
|
/* its time to look-up proc info */ |
|
206 |
|
if (q->uid == 0x0FFFFFFF) |
|
207 |
|
lookup_proc_info(q); |
|
208 |
|
|
|
209 |
|
if (strstr(q->cmd, "attack2")) |
|
210 |
|
fprintf(stderr, "attack2: [%s] diff=%dms misses=%lu mps=%.3f\n", |
|
211 |
|
q->cmd, diff, q->misses, misses_per_second); |
|
212 |
|
|
|
213 |
|
if (misses_per_second > MISSES_SUSPEND_TRIGGER) { |
|
214 |
|
fprintf(stderr, "pid %d [%s] has %.3f/s score (diff=%dms misses=%lu\n", |
|
215 |
|
q->pid, q->cmd, misses_per_second, diff, q->misses); |
|
216 |
|
pid_suspend(&now, q); |
|
217 |
|
return; |
|
218 |
|
} |
|
219 |
|
} |
|
220 |
|
|
|
221 |
|
/* Add it to the hash */ |
|
222 |
|
p = malloc(sizeof(struct pid_cell)); |
|
223 |
|
if (!p) |
|
224 |
|
return; |
|
225 |
|
|
|
226 |
|
p->pid = pid; |
|
227 |
|
p->next = NULL; |
|
228 |
|
p->next_in_queue = NULL; |
|
229 |
|
p->start = now; |
|
230 |
|
p->misses = 0; |
|
231 |
|
p->uid = 0x0FFFFFFF; |
|
232 |
|
strcpy(p->cmd, "?"); |
|
233 |
|
|
|
234 |
|
if (pid_hash[i] == NULL) { |
|
235 |
|
pid_hash[i] = p; |
|
236 |
|
} else { |
|
237 |
|
q = pid_hash[i]; |
|
238 |
|
while (q->next) |
|
239 |
|
q = q->next; |
|
240 |
|
|
|
241 |
|
q->next = p; |
|
242 |
|
} |
|
243 |
|
} |
28 |
244 |
|
|
29 |
245 |
/* |
/* |
30 |
246 |
* Registers a counter |
* Registers a counter |
|
... |
... |
static int register_event(const unsigned int cpu, const __u32 type, |
42 |
258 |
| PERF_SAMPLE_ADDR |
| PERF_SAMPLE_ADDR |
43 |
259 |
| PERF_SAMPLE_PERIOD |
| PERF_SAMPLE_PERIOD |
44 |
260 |
| PERF_SAMPLE_CPU; |
| PERF_SAMPLE_CPU; |
45 |
|
attr.sample_period = 1000; |
|
|
261 |
|
attr.sample_period = MISS_TRIGGER; |
46 |
262 |
//attr.enable_on_exec = 1; |
//attr.enable_on_exec = 1; |
47 |
263 |
attr.disabled = 0; |
attr.disabled = 0; |
48 |
264 |
attr.exclude_kernel = 1; |
attr.exclude_kernel = 1; |
|
... |
... |
static int register_event(const unsigned int cpu, const __u32 type, |
73 |
289 |
return fd; |
return fd; |
74 |
290 |
} |
} |
75 |
291 |
|
|
|
292 |
|
/* |
|
293 |
|
* Increments q with @inc, taking in consideration the wrap around |
|
294 |
|
*/ |
|
295 |
|
static inline void q_inc(void *m, void **q, const unsigned int inc) |
|
296 |
|
{ |
|
297 |
|
void *old_q = *q; |
|
298 |
|
int diff; |
|
299 |
|
|
|
300 |
|
diff = (*q + inc) - (m + (1 + MMAP_BUF_SIZE) * page_size); |
|
301 |
|
if (diff >= 0) |
|
302 |
|
*q = m + page_size; |
|
303 |
|
else |
|
304 |
|
*q = *q + inc; |
|
305 |
|
|
|
306 |
|
#if 0 |
|
307 |
|
fprintf(stderr, "\tm=%p *q=%p -> *q=%p inc=%u\n", |
|
308 |
|
m, old_q, *q, inc); |
|
309 |
|
#endif |
|
310 |
|
} |
|
311 |
|
|
76 |
312 |
/* |
/* |
77 |
313 |
* Checking if any process is on the wrong side |
* Checking if any process is on the wrong side |
78 |
314 |
* Returns the ?TODO |
* Returns the ?TODO |
|
... |
... |
static int check(void *m) |
101 |
337 |
barrier(); |
barrier(); |
102 |
338 |
} while (mp->lock != seq); |
} while (mp->lock != seq); |
103 |
339 |
|
|
104 |
|
head %= MMAP_BUF_SIZE * page_size; |
|
105 |
|
tail %= MMAP_BUF_SIZE * page_size; |
|
106 |
|
|
|
|
340 |
|
#if 0 |
107 |
341 |
fprintf(stderr, "version=%u index=%u count=%llu" |
fprintf(stderr, "version=%u index=%u count=%llu" |
108 |
|
" head=%llu tail=%llu\n", |
|
109 |
|
version, index, count, head, tail); |
|
|
342 |
|
" head=%llu(%llu) tail=%llu(%llu)\n", |
|
343 |
|
version, index, count, |
|
344 |
|
head, head % (MMAP_BUF_SIZE * page_size), |
|
345 |
|
tail, tail % (MMAP_BUF_SIZE * page_size)); |
|
346 |
|
#endif |
110 |
347 |
|
|
111 |
348 |
/* Dump rest of buffers */ |
/* Dump rest of buffers */ |
112 |
|
p = m + page_size + tail; |
|
113 |
349 |
rest = head - tail; |
rest = head - tail; |
114 |
350 |
while (rest > 0) { |
while (rest > 0) { |
|
351 |
|
p = m + page_size + tail % (MMAP_BUF_SIZE * page_size); |
|
352 |
|
//fprintf(stderr, "\trest=%llu p=%p\n", rest, p); |
115 |
353 |
q = p; |
q = p; |
116 |
354 |
h = q; |
h = q; |
117 |
|
fprintf(stderr, "\th: type=%u misc=%hu size=%hu rest=%llu\n", |
|
118 |
|
h->type, h->misc, h->size, rest); |
|
|
355 |
|
#if 0 |
|
356 |
|
fprintf(stderr, "\th: type=%u misc=%hu size=%hu\n", |
|
357 |
|
h->type, h->misc, h->size); |
|
358 |
|
#endif |
119 |
359 |
q += sizeof(struct perf_event_header); |
q += sizeof(struct perf_event_header); |
120 |
360 |
|
|
121 |
361 |
switch (h->type) { |
switch (h->type) { |
122 |
362 |
case PERF_RECORD_MMAP: |
case PERF_RECORD_MMAP: |
123 |
|
p_pid = q; q += 4; |
|
124 |
|
p_tid = q; q += 4; |
|
125 |
|
p_addr = q; q += 8; |
|
126 |
|
p_len = q; q += 8; |
|
127 |
|
p_pgoff = q; q += 8; |
|
|
363 |
|
p_pid = q; q_inc(m, &q, 4); |
|
364 |
|
p_tid = q; q_inc(m, &q, 4); |
|
365 |
|
p_addr = q; q_inc(m, &q, 8); |
|
366 |
|
p_len = q; q_inc(m, &q, 8); |
|
367 |
|
p_pgoff = q; q_inc(m, &q, 8); |
128 |
368 |
filename = q; |
filename = q; |
129 |
369 |
fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx" |
fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx" |
130 |
370 |
" len=%llu pgoff=%llx filename=%s.\n", |
" len=%llu pgoff=%llx filename=%s.\n", |
|
... |
... |
static int check(void *m) |
133 |
373 |
break; |
break; |
134 |
374 |
|
|
135 |
375 |
case PERF_RECORD_SAMPLE: |
case PERF_RECORD_SAMPLE: |
136 |
|
p_ip = q; q += 8; |
|
137 |
|
p_pid = q; q += 4; |
|
138 |
|
p_tid = q; q += 4; |
|
139 |
|
p_addr = q; q += 8; |
|
140 |
|
p_cpu = q; q += 8; |
|
141 |
|
p_period = q; q += 8; |
|
|
376 |
|
p_ip = q; q_inc(m, &q, 8); |
|
377 |
|
p_pid = q; q_inc(m, &q, 4); |
|
378 |
|
p_tid = q; q_inc(m, &q, 4); |
|
379 |
|
p_addr = q; q_inc(m, &q, 8); |
|
380 |
|
p_cpu = q; q_inc(m, &q, 8); |
|
381 |
|
p_period = q; q_inc(m, &q, 8); |
|
382 |
|
#if 0 |
142 |
383 |
fprintf(stderr, "\tsample ip=0x%llx pid=%u" |
fprintf(stderr, "\tsample ip=0x%llx pid=%u" |
143 |
384 |
" tid=%u addr=%llx period=%llu cpu=%u\n", |
" tid=%u addr=%llx period=%llu cpu=%u\n", |
144 |
385 |
*p_ip, *p_pid, *p_tid, *p_addr, *p_period, *p_cpu); |
*p_ip, *p_pid, *p_tid, *p_addr, *p_period, *p_cpu); |
|
386 |
|
#endif |
|
387 |
|
pid_hash_add(*p_pid); |
145 |
388 |
break; |
break; |
146 |
389 |
|
|
147 |
390 |
case PERF_RECORD_EXIT: |
case PERF_RECORD_EXIT: |
148 |
|
p_pid = q; q += 4; |
|
149 |
|
p_ppid = q; q += 4; |
|
150 |
|
p_tid = q; q += 4; |
|
151 |
|
p_ptid = q; q += 4; |
|
152 |
|
p_time = q; q += 8; |
|
|
391 |
|
p_pid = q; q_inc(m, &q, 4); |
|
392 |
|
p_ppid = q; q_inc(m, &q, 4); |
|
393 |
|
p_tid = q; q_inc(m, &q, 4); |
|
394 |
|
p_ptid = q; q_inc(m, &q, 4); |
|
395 |
|
p_time = q; q_inc(m, &q, 8); |
153 |
396 |
fprintf(stderr, "\texit pid=%u ppid=%u tid=%u" |
fprintf(stderr, "\texit pid=%u ppid=%u tid=%u" |
154 |
397 |
" ptid=%u time=%llu\n", |
" ptid=%u time=%llu\n", |
155 |
398 |
*p_pid, *p_ppid, *p_tid, *p_ptid, |
*p_pid, *p_ppid, *p_tid, *p_ptid, |
|
... |
... |
static int check(void *m) |
157 |
400 |
break; |
break; |
158 |
401 |
|
|
159 |
402 |
case PERF_RECORD_COMM: |
case PERF_RECORD_COMM: |
160 |
|
p_pid = q; q += 4; |
|
161 |
|
p_tid = q; q += 4; |
|
|
403 |
|
p_pid = q; q_inc(m, &q, 4); |
|
404 |
|
p_tid = q; q_inc(m, &q, 4); |
162 |
405 |
comm = q; |
comm = q; |
163 |
406 |
fprintf(stderr, "\tcomm pid=%u tid=%u comm=%s\n", |
fprintf(stderr, "\tcomm pid=%u tid=%u comm=%s\n", |
164 |
407 |
*p_pid, *p_tid, comm); |
*p_pid, *p_tid, comm); |
165 |
408 |
break; |
break; |
166 |
409 |
|
|
167 |
410 |
case PERF_RECORD_MMAP2: |
case PERF_RECORD_MMAP2: |
168 |
|
p_pid = q; q += 4; |
|
169 |
|
p_tid = q; q += 4; |
|
170 |
|
p_addr = q; q += 8; |
|
171 |
|
p_len = q; q += 8; |
|
172 |
|
p_pgoff = q; q += 8; |
|
173 |
|
q += 4; /* maj */ |
|
174 |
|
q += 4; /* min */ |
|
175 |
|
q += 8; /* ino */ |
|
176 |
|
q += 8; /* ino_generation */ |
|
177 |
|
q += 4; /* prot */ |
|
178 |
|
q += 4; /* flags */ |
|
|
411 |
|
p_pid = q; q_inc(m, &q, 4); |
|
412 |
|
p_tid = q; q_inc(m, &q, 4); |
|
413 |
|
p_addr = q; q_inc(m, &q, 8); |
|
414 |
|
p_len = q; q_inc(m, &q, 8); |
|
415 |
|
p_pgoff = q; q_inc(m, &q, 8); |
|
416 |
|
q_inc(m, &q, 4); /* maj */ |
|
417 |
|
q_inc(m, &q, 4); /* min */ |
|
418 |
|
q_inc(m, &q, 8); /* ino */ |
|
419 |
|
q_inc(m, &q, 8); /* ino_generation */ |
|
420 |
|
q_inc(m, &q, 4); /* prot */ |
|
421 |
|
q_inc(m, &q, 4); /* flags */ |
179 |
422 |
filename = p; |
filename = p; |
180 |
423 |
fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx" |
fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx" |
181 |
424 |
" len=%llu pgoff=%llx filename=%s.\n", |
" len=%llu pgoff=%llx filename=%s.\n", |
|
... |
... |
static int check(void *m) |
184 |
427 |
break; |
break; |
185 |
428 |
|
|
186 |
429 |
case PERF_RECORD_FORK: |
case PERF_RECORD_FORK: |
187 |
|
p_pid = q; q += 4; |
|
188 |
|
p_ppid = q; q += 4; |
|
189 |
|
p_tid = q; q += 4; |
|
190 |
|
p_ptid = q; q += 4; |
|
191 |
|
p_time = q; q += 8; |
|
|
430 |
|
p_pid = q; q_inc(m, &q, 4); |
|
431 |
|
p_ppid = q; q_inc(m, &q, 4); |
|
432 |
|
p_tid = q; q_inc(m, &q, 4); |
|
433 |
|
p_ptid = q; q_inc(m, &q, 4); |
|
434 |
|
p_time = q; q_inc(m, &q, 8); |
192 |
435 |
fprintf(stderr, "\tfork pid=%u ppid=%u tid=%u" |
fprintf(stderr, "\tfork pid=%u ppid=%u tid=%u" |
193 |
436 |
" ptid=%u time=%llu\n", |
" ptid=%u time=%llu\n", |
194 |
437 |
*p_pid, *p_ppid, *p_tid, *p_ptid, |
*p_pid, *p_ppid, *p_tid, *p_ptid, |
|
... |
... |
static int check(void *m) |
199 |
442 |
fprintf(stderr, "\tUnknown type %u\n", h->type); |
fprintf(stderr, "\tUnknown type %u\n", h->type); |
200 |
443 |
break; |
break; |
201 |
444 |
} |
} |
202 |
|
p += h->size; |
|
|
445 |
|
tail += h->size; |
203 |
446 |
rest -= h->size; |
rest -= h->size; |
204 |
447 |
} |
} |
205 |
448 |
mp->data_tail = head; |
mp->data_tail = head; |
|
... |
... |
int main(void) |
213 |
456 |
int fd1, fd2[2], nr_cpus, r, efd, i, fd; |
int fd1, fd2[2], nr_cpus, r, efd, i, fd; |
214 |
457 |
void *m1, *m2[2]; |
void *m1, *m2[2]; |
215 |
458 |
struct epoll_event ee; |
struct epoll_event ee; |
|
459 |
|
struct pid_cell *p, *prev; |
|
460 |
|
struct timeval now; |
|
461 |
|
int next_wake, diff; |
216 |
462 |
|
|
217 |
463 |
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
218 |
464 |
fprintf(stderr, "%d cpu(s) online.\n", nr_cpus); |
fprintf(stderr, "%d cpu(s) online.\n", nr_cpus); |
|
... |
... |
int main(void) |
220 |
466 |
page_size = sysconf(_SC_PAGE_SIZE); |
page_size = sysconf(_SC_PAGE_SIZE); |
221 |
467 |
fprintf(stderr, "page size is %lu\n", page_size); |
fprintf(stderr, "page size is %lu\n", page_size); |
222 |
468 |
|
|
|
469 |
|
memset(pid_hash, 0, sizeof(pid_hash)); |
|
470 |
|
|
223 |
471 |
/* TODO: move to 99? */ |
/* TODO: move to 99? */ |
224 |
472 |
param.sched_priority = 1; |
param.sched_priority = 1; |
225 |
473 |
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { |
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { |
|
... |
... |
int main(void) |
264 |
512 |
//ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); |
//ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); |
265 |
513 |
|
|
266 |
514 |
while (1) { |
while (1) { |
267 |
|
r = epoll_wait(efd, &ee, 1, 1000); |
|
|
515 |
|
next_wake = -1; |
|
516 |
|
if (queue_head) { |
|
517 |
|
gettimeofday(&now, NULL); |
|
518 |
|
next_wake = time_diff(&queue_head->wake, &now); |
|
519 |
|
} |
|
520 |
|
r = epoll_wait(efd, &ee, 1, next_wake); |
268 |
521 |
if (r == -1) { |
if (r == -1) { |
269 |
522 |
if (errno == EINTR) |
if (errno == EINTR) |
270 |
523 |
continue; |
continue; |
|
... |
... |
int main(void) |
273 |
526 |
return 1; |
return 1; |
274 |
527 |
} |
} |
275 |
528 |
|
|
|
529 |
|
/* Process suspend queue */ |
|
530 |
|
gettimeofday(&now, NULL); |
|
531 |
|
p = queue_head; |
|
532 |
|
prev = NULL; |
|
533 |
|
while (p) { |
|
534 |
|
diff = time_diff(&p->wake, &now); |
|
535 |
|
fprintf(stderr, "Q: p=%p diff=%ums\n", p, diff); |
|
536 |
|
if (diff <= 0) { |
|
537 |
|
pid_unsuspend(p); |
|
538 |
|
if (prev) |
|
539 |
|
prev->next_in_queue = p->next_in_queue; |
|
540 |
|
else |
|
541 |
|
queue_head = p->next_in_queue; |
|
542 |
|
} |
|
543 |
|
prev = p; |
|
544 |
|
p = p->next_in_queue; |
|
545 |
|
} |
|
546 |
|
queue_tail = prev; |
|
547 |
|
|
276 |
548 |
if (r == 0) |
if (r == 0) |
277 |
549 |
continue; |
continue; |
278 |
550 |
|
|