master
c 538 lines 9.93 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 madvise.c
8
9 Abstract:
10
11 This file is a madvise test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <string.h>
18 #include <sys/mman.h>
19 #include <sched.h>
20 #include <signal.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/ioctl.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <time.h>
27
28 #define LXT_NAME "madvise"
29
30 int MadviseVariation2(PLXT_ARGS Args);
31
32 int MadviseVariation3(PLXT_ARGS Args);
33
34 int MadviseVariation4(PLXT_ARGS Args);
35
36 int MadviseVariation5(PLXT_ARGS Args);
37
38 //
39 // Global constants
40 //
41
42 static const LXT_VARIATION g_LxtVariations[] = {
43 {"Anonymous mapping", MadviseVariation2},
44 {"Anonymous mapping with fork", MadviseVariation3},
45 {"File-backed mapping", MadviseVariation4},
46 {"File-backed with fork", MadviseVariation5}};
47
48 int MadviseTestEntry(int Argc, char* Argv[])
49
50 /*++
51 --*/
52
53 {
54
55 LXT_ARGS Args;
56 int Result;
57
58 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
59 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
60
61 ErrorExit:
62 LxtUninitialize();
63 return !LXT_SUCCESS(Result);
64 }
65
66 #define MADVISE_TEST_BUFFER_SIZE 0x5000
67
68 int MadviseRunTest(int FileId, int BufferSize, int DoFork)
69 {
70 int Result;
71 unsigned char* SharedBuffer;
72 unsigned char* PrivateBuffer;
73 unsigned char* Ptr;
74 unsigned char* EndPtr;
75 unsigned char ExpectedByte;
76 int MapAnonymousFlag;
77 int IsChild;
78
79 //
80 // Initialize locals.
81 //
82
83 SharedBuffer = MAP_FAILED;
84 PrivateBuffer = MAP_FAILED;
85 IsChild = 0;
86
87 MapAnonymousFlag = 0;
88
89 if (FileId == -1)
90 {
91 MapAnonymousFlag = MAP_ANONYMOUS;
92 }
93
94 //
95 // Allocate the shared buffer.
96 //
97
98 SharedBuffer = mmap(NULL, BufferSize, PROT_READ | PROT_WRITE, MAP_SHARED | MapAnonymousFlag, FileId, 0);
99
100 if (SharedBuffer == MAP_FAILED)
101 {
102 Result = errno;
103 LxtLogError("Could not map shared! %d", Result);
104 goto cleanup;
105 }
106
107 //
108 // Allocate the private buffer.
109 //
110
111 PrivateBuffer = mmap(NULL, BufferSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MapAnonymousFlag, FileId, 0);
112
113 if (PrivateBuffer == MAP_FAILED)
114 {
115 Result = errno;
116 LxtLogError("Could not map private! %d", Result);
117 goto cleanup;
118 }
119
120 //
121 // Fill the shared buffer.
122 //
123
124 Ptr = SharedBuffer;
125 EndPtr = Ptr + BufferSize;
126
127 for (; Ptr < EndPtr; Ptr += 1)
128 {
129 *Ptr = 0xDE;
130 }
131
132 //
133 // Make sure the private buffer sees the shared buffer.
134 //
135
136 if (FileId != -1)
137 {
138
139 Ptr = PrivateBuffer;
140 EndPtr = Ptr + BufferSize;
141
142 for (; Ptr < EndPtr; Ptr += 1)
143 {
144 if (*Ptr != 0xDE)
145 {
146 *((volatile int*)0) = 0xDEADBEEF;
147 }
148 }
149 }
150
151 //
152 // Fill the private buffer.
153 //
154
155 Ptr = PrivateBuffer;
156 EndPtr = Ptr + BufferSize;
157
158 for (; Ptr < EndPtr; Ptr += 1)
159 {
160 *Ptr = 0xCA;
161 }
162
163 //
164 // Protect one of the two pages that will be reverted.
165 //
166
167 Result = mprotect(PrivateBuffer + PAGE_SIZE, PAGE_SIZE, PROT_READ);
168
169 if (Result == -1)
170 {
171 Result = errno;
172 LxtLogError("Could not set protection on buffer! %d", Result);
173 goto cleanup;
174 }
175
176 //
177 // Fork the process if desired.
178 //
179
180 if (DoFork)
181 {
182
183 Result = fork();
184
185 if (Result == -1)
186 {
187 Result = errno;
188 LxtLogError("Could not fork the child! %d", Result);
189 goto cleanup;
190 }
191
192 if (Result == 0)
193 {
194 IsChild = 1;
195 }
196 }
197
198 //
199 // Revert the middle two pages back to the shared buffer.
200 //
201
202 Result = madvise((PrivateBuffer + PAGE_SIZE), (PAGE_SIZE * 2), MADV_DONTNEED);
203
204 if (Result == -1)
205 {
206 Result = errno;
207 LxtLogError("Could not madvise on private buffer! %d", Result);
208 goto cleanup;
209 }
210
211 //
212 // Make sure the first page contains private data.
213 //
214
215 Ptr = PrivateBuffer;
216 EndPtr = Ptr + PAGE_SIZE;
217
218 for (; Ptr < EndPtr; Ptr += 1)
219 {
220
221 if (*Ptr != 0xCA)
222 {
223 LxtLogError("Private buffer not contain expected data (1), %d", *Ptr);
224 Result = EFAULT;
225 goto cleanup;
226 }
227 }
228
229 //
230 // Make sure the next two pages contain shared data or zeroes in the private
231 // allocation case.
232 //
233
234 EndPtr = Ptr + (PAGE_SIZE * 2);
235
236 for (; Ptr < EndPtr; Ptr += 1)
237 {
238 if (FileId == -1)
239 {
240 ExpectedByte = 0;
241 }
242 else
243 {
244 ExpectedByte = 0xDE;
245 }
246
247 if (*Ptr != ExpectedByte)
248 {
249 LxtLogError("Private buffer not contain expected data (2), %d", *Ptr);
250 Result = EFAULT;
251 goto cleanup;
252 }
253 }
254
255 //
256 // Make sure the remaining pages contain private data.
257 //
258
259 EndPtr = PrivateBuffer + BufferSize;
260
261 for (; Ptr < EndPtr; Ptr += 1)
262 {
263 if (*Ptr != 0xCA)
264 {
265 LxtLogError("Private buffer not contain expected data (3), %d", *Ptr);
266 Result = EFAULT;
267 goto cleanup;
268 }
269 }
270
271 //
272 // Make sure that the shared buffer contains all shared data.
273 //
274
275 Ptr = SharedBuffer;
276 EndPtr = Ptr + BufferSize;
277
278 for (; Ptr < EndPtr; Ptr += 1)
279 {
280 if (*Ptr != 0xDE)
281 {
282 LxtLogError("Shared buffer not contain expected data (4), %d", *Ptr);
283 Result = EFAULT;
284 goto cleanup;
285 }
286 }
287
288 Result = 0;
289
290 cleanup:
291
292 if (SharedBuffer != MAP_FAILED)
293 {
294 munmap(SharedBuffer, BufferSize);
295 }
296
297 if (PrivateBuffer != MAP_FAILED)
298 {
299 munmap(PrivateBuffer, BufferSize);
300 }
301
302 if (IsChild)
303 {
304 _exit(Result);
305 }
306
307 return Result;
308 }
309
310 int MadviseVariation2(PLXT_ARGS Args)
311
312 /*++
313 --*/
314
315 {
316
317 int Result;
318 int FileId;
319 int BufferSize;
320
321 //
322 // Initialize locals.
323 //
324
325 FileId = -1;
326 BufferSize = MADVISE_TEST_BUFFER_SIZE;
327
328 //
329 // Run the test on private memory.
330 //
331
332 Result = MadviseRunTest(FileId, BufferSize, 0);
333
334 if (Result != 0)
335 {
336 LxtLogError("Variation2 failed! %d", Result);
337 goto ErrorExit;
338 }
339
340 Result = LXT_RESULT_SUCCESS;
341
342 ErrorExit:
343
344 if (FileId != -1)
345 {
346 close(FileId);
347 }
348
349 return Result;
350 }
351
352 int MadviseVariation3(PLXT_ARGS Args)
353
354 /*++
355 --*/
356
357 {
358
359 int Result;
360 int FileId;
361 int BufferSize;
362
363 //
364 // Initialize locals.
365 //
366
367 FileId = -1;
368 BufferSize = MADVISE_TEST_BUFFER_SIZE;
369
370 //
371 // Run the test on private memory with fork.
372 //
373
374 Result = MadviseRunTest(FileId, BufferSize, 1);
375
376 if (Result != 0)
377 {
378 LxtLogError("Variation3 failed! %d", Result);
379 goto ErrorExit;
380 }
381
382 Result = LXT_RESULT_SUCCESS;
383
384 ErrorExit:
385
386 if (FileId != -1)
387 {
388 close(FileId);
389 }
390
391 return Result;
392 }
393
394 int MadviseVariation4(PLXT_ARGS Args)
395
396 /*++
397 --*/
398
399 {
400
401 int Result;
402 int FileId;
403 int BufferSize;
404 unsigned int WriteData;
405 int BytesWritten;
406 int ByteIndex;
407
408 //
409 // Initialize locals.
410 //
411
412 FileId = -1;
413 BufferSize = MADVISE_TEST_BUFFER_SIZE;
414
415 //
416 // Open the file and fill it to the appropriate size.
417 //
418
419 FileId = open("/data/test/madvise_test.bin", O_RDWR | O_CREAT, S_IRWXU);
420
421 if (FileId == -1)
422 {
423 Result = errno;
424 LxtLogError("Could not create test file! %d", Result);
425 goto ErrorExit;
426 }
427
428 WriteData = (unsigned int)-1;
429
430 for (ByteIndex = 0; ByteIndex < BufferSize; ByteIndex += sizeof(WriteData))
431 {
432
433 BytesWritten = write(FileId, &WriteData, sizeof(WriteData));
434
435 if (BytesWritten != sizeof(WriteData))
436 {
437 Result = errno;
438 LxtLogError("Could not write to file! %d", Result);
439 goto ErrorExit;
440 }
441 }
442
443 //
444 // Run the test on file-backed memory.
445 //
446
447 Result = MadviseRunTest(FileId, BufferSize, 0);
448
449 if (Result != 0)
450 {
451 LxtLogError("Variation4 failed! %d", Result);
452 goto ErrorExit;
453 }
454
455 Result = LXT_RESULT_SUCCESS;
456
457 ErrorExit:
458
459 if (FileId != -1)
460 {
461 close(FileId);
462 }
463
464 return Result;
465 }
466
467 int MadviseVariation5(PLXT_ARGS Args)
468
469 /*++
470 --*/
471
472 {
473
474 int Result;
475 int FileId;
476 int BufferSize;
477 unsigned int WriteData;
478 int BytesWritten;
479 int ByteIndex;
480
481 //
482 // Initialize locals.
483 //
484
485 FileId = -1;
486 BufferSize = MADVISE_TEST_BUFFER_SIZE;
487
488 //
489 // Open the file and fill it to the appropriate size.
490 //
491
492 FileId = open("/data/test/madvise_test.bin", O_RDWR | O_CREAT, S_IRWXU);
493
494 if (FileId == -1)
495 {
496 Result = errno;
497 LxtLogError("Could not create test file! %d", Result);
498 goto ErrorExit;
499 }
500
501 WriteData = (unsigned int)-1;
502
503 for (ByteIndex = 0; ByteIndex < BufferSize; ByteIndex += sizeof(WriteData))
504 {
505
506 BytesWritten = write(FileId, &WriteData, sizeof(WriteData));
507
508 if (BytesWritten != sizeof(WriteData))
509 {
510 Result = errno;
511 LxtLogError("Could not write to file! %d", Result);
512 goto ErrorExit;
513 }
514 }
515
516 //
517 // Run the test on file-backed memory with fork.
518 //
519
520 Result = MadviseRunTest(FileId, BufferSize, 1);
521
522 if (Result != 0)
523 {
524 LxtLogError("Variation5 failed! %d", Result);
525 goto ErrorExit;
526 }
527
528 Result = LXT_RESULT_SUCCESS;
529
530 ErrorExit:
531
532 if (FileId != -1)
533 {
534 close(FileId);
535 }
536
537 return Result;
538 }