This repository has been archived by the owner on Nov 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
autoflushwrite.c
101 lines (85 loc) · 2.62 KB
/
autoflushwrite.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
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2020, Intel Corporation. All rights reserved.
*
* autoflushwrite.c -- test flush-on-fail persistent CPU caches
*
* usage:
* autoflushwrite filename [filesize]
*
* Where filename is a DAX file this program will create. filename
* must not exist already. After mapping the file and warming up
* the cache, the program will loop forever writing data to the cache
* until power is removed. Use autoflushcheck to verify results
* after reboot.
*
* If the file size is not specified, a default of 20M is used.
*/
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <x86intrin.h>
/* allow building with older Linux header files */
#ifndef MAP_SYNC
#define MAP_SYNC 0x80000
#endif
#ifndef MAP_SHARED_VALIDATE
#define MAP_SHARED_VALIDATE 0x03
#endif
/*
* 20 megs fits in the cache and is still a non-trivial
* amount of data to test flush-on-fail
*/
#define MB (1<<20)
#define DEFAULT_FILESIZE (20 * MB)
/*
* first page is used to store iteration number with deep flush.
* rest of file is then filled up with iteration number, written
* once per 64-byte cache line and not flushed.
*/
int
main(int argc, char *argv[])
{
int fd;
char *pmaddr;
unsigned int filesize;
unsigned int nstore;
if (argc < 1 || argc > 3) {
fprintf(stderr, "Usage: %s filename [filesize]\n", argv[0]);
exit(1);
}
if ((fd = open(argv[1], O_RDWR|O_CREAT|O_EXCL, 0644)) < 0)
err(1, "open: %s", argv[1]);
if (argv[2] != NULL)
filesize = atoi(argv[2]) * MB;
else
filesize = DEFAULT_FILESIZE;
printf("Filesize entered is %d",filesize);
if (ftruncate(fd, (off_t)filesize) < 0)
err(1, "ftruncate: %s", argv[1]);
if ((pmaddr = (char *)mmap(NULL, (off_t)filesize, PROT_READ|PROT_WRITE,
MAP_SHARED_VALIDATE|MAP_SYNC,
fd, 0)) == MAP_FAILED)
err(1, "mmap(MAP_SYNC): %s", argv[1]);
nstore = (filesize - 0x1000) / 64;
close(fd);
for (unsigned iteration = 0; 1; iteration++) {
/* store iteration number in first page and deep flush it */
*(unsigned *)pmaddr = iteration;
_mm_clflush(pmaddr);
if (msync(pmaddr, 0x1000, MS_SYNC) < 0)
err(1, "msync");
/* store iteration number in each cache line and don't flush */
for (int i = 0; i < nstore; i++)
*(unsigned *)(pmaddr + 0x1000 + 64 * i) = iteration;
if (iteration == 2) {
printf("%s: stores running, ready for power fail...\n",
argv[0]);
fflush(stdout);
}
}
}