]>
git.saurik.com Git - redis.git/blob - src/memtest.c
10 #if (ULONG_MAX == 4294967295UL)
12 #elif (ULONG_MAX == 18446744073709551615ULL)
15 #error "ULONG_MAX value not supported."
19 #define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL
20 #define ULONG_ZEROONE 0x5555555555555555UL
22 #define ULONG_ONEZERO 0xaaaaaaaaUL
23 #define ULONG_ZEROONE 0x55555555UL
26 static struct winsize ws
;
27 size_t progress_printed
; /* Printed chars in screen-wide progress bar. */
28 size_t progress_full
; /* How many chars to write to fill the progress bar. */
30 void memtest_progress_start(char *title
, int pass
) {
33 printf("\x1b[H\x1b[2J"); /* Cursor home, clear screen. */
35 for (j
= 0; j
< ws
.ws_col
*(ws
.ws_row
-2); j
++) printf(".");
36 printf("Please keep the test running several minutes per GB of memory.\n");
37 printf("Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/");
38 printf("\x1b[H\x1b[2K"); /* Cursor home, clear current line. */
39 printf("%s [%d]\n", title
, pass
); /* Print title. */
41 progress_full
= ws
.ws_col
*(ws
.ws_row
-3);
45 void memtest_progress_end(void) {
46 printf("\x1b[H\x1b[2J"); /* Cursor home, clear screen. */
49 void memtest_progress_step(size_t curr
, size_t size
, char c
) {
50 size_t chars
= (curr
*progress_full
)/size
, j
;
52 for (j
= 0; j
< chars
-progress_printed
; j
++) {
59 /* Fill words stepping a single page at every write, so we continue to
60 * touch all the pages in the smallest amount of time reducing the
61 * effectiveness of caches, and making it hard for the OS to transfer
62 * pages on the swap. */
63 void memtest_fill_random(unsigned long *l
, size_t bytes
) {
64 unsigned long step
= 4096/sizeof(unsigned long);
65 unsigned long words
= bytes
/sizeof(unsigned long)/2;
66 unsigned long iwords
= words
/step
; /* words per iteration */
67 unsigned long off
, w
, *l1
, *l2
;
69 assert((bytes
& 4095) == 0);
70 for (off
= 0; off
< step
; off
++) {
73 for (w
= 0; w
< iwords
; w
++) {
75 *l1
= *l2
= ((unsigned long) (rand()&0xffff)) |
76 (((unsigned long) (rand()&0xffff)) << 16);
78 *l1
= *l2
= ((unsigned long) (rand()&0xffff)) |
79 (((unsigned long) (rand()&0xffff)) << 16) |
80 (((unsigned long) (rand()&0xffff)) << 32) |
81 (((unsigned long) (rand()&0xffff)) << 48);
85 if ((w
& 0xffff) == 0)
86 memtest_progress_step(w
+iwords
*off
,words
,'R');
91 /* Like memtest_fill_random() but uses the two specified values to fill
92 * memory, in an alternated way (v1|v2|v1|v2|...) */
93 void memtest_fill_value(unsigned long *l
, size_t bytes
, unsigned long v1
,
94 unsigned long v2
, char sym
)
96 unsigned long step
= 4096/sizeof(unsigned long);
97 unsigned long words
= bytes
/sizeof(unsigned long)/2;
98 unsigned long iwords
= words
/step
; /* words per iteration */
99 unsigned long off
, w
, *l1
, *l2
, v
;
101 assert((bytes
& 4095) == 0);
102 for (off
= 0; off
< step
; off
++) {
105 v
= (off
& 1) ? v2
: v1
;
106 for (w
= 0; w
< iwords
; w
++) {
108 *l1
= *l2
= ((unsigned long) (rand()&0xffff)) |
109 (((unsigned long) (rand()&0xffff)) << 16);
111 *l1
= *l2
= ((unsigned long) (rand()&0xffff)) |
112 (((unsigned long) (rand()&0xffff)) << 16) |
113 (((unsigned long) (rand()&0xffff)) << 32) |
114 (((unsigned long) (rand()&0xffff)) << 48);
118 if ((w
& 0xffff) == 0)
119 memtest_progress_step(w
+iwords
*off
,words
,sym
);
124 void memtest_compare(unsigned long *l
, size_t bytes
) {
125 unsigned long words
= bytes
/sizeof(unsigned long)/2;
126 unsigned long w
, *l1
, *l2
;
128 assert((bytes
& 4095) == 0);
131 for (w
= 0; w
< words
; w
++) {
133 printf("\n*** MEMORY ERROR DETECTED: %p != %p (%lu vs %lu)\n",
134 (void*)l1
, (void*)l2
, *l1
, *l2
);
139 if ((w
& 0xffff) == 0) memtest_progress_step(w
,words
,'=');
143 void memtest_compare_times(unsigned long *m
, size_t bytes
, int pass
, int times
) {
146 for (j
= 0; j
< times
; j
++) {
147 memtest_progress_start("Compare",pass
);
148 memtest_compare(m
,bytes
);
149 memtest_progress_end();
153 void memtest_test(size_t megabytes
, int passes
) {
154 size_t bytes
= megabytes
*1024*1024;
155 unsigned long *m
= malloc(bytes
);
159 fprintf(stderr
,"Unable to allocate %zu megabytes: %s",
160 megabytes
, strerror(errno
));
163 while (pass
!= passes
) {
165 memtest_progress_start("Random fill",pass
);
166 memtest_fill_random(m
,bytes
);
167 memtest_progress_end();
168 memtest_compare_times(m
,bytes
,pass
,4);
170 memtest_progress_start("Solid fill",pass
);
171 memtest_fill_value(m
,bytes
,0,(unsigned long)-1,'S');
172 memtest_progress_end();
173 memtest_compare_times(m
,bytes
,pass
,4);
175 memtest_progress_start("Checkerboard fill",pass
);
176 memtest_fill_value(m
,bytes
,ULONG_ONEZERO
,ULONG_ZEROONE
,'C');
177 memtest_progress_end();
178 memtest_compare_times(m
,bytes
,pass
,4);
182 void memtest(size_t megabytes
, int passes
) {
183 if (ioctl(1, TIOCGWINSZ
, &ws
) == -1) {
187 memtest_test(megabytes
,passes
);
188 printf("\nYour memory passed this test.\n");
189 printf("Please if you are still in doubt use the following two tools:\n");
190 printf("1) memtest86: http://www.memtest86.com/\n");
191 printf("2) memtester: http://pyropus.ca/software/memtester/\n");