]> git.saurik.com Git - redis.git/blame - src/memtest.c
Number of iteration of --test-memory is now 300 (several minutes per gigabyte). Memte...
[redis.git] / src / memtest.c
CommitLineData
f4df22d1 1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <assert.h>
5#include <limits.h>
6#include <errno.h>
d605fdab 7#include <termios.h>
8#include <sys/ioctl.h>
f4df22d1 9
10#if (ULONG_MAX == 4294967295UL)
11#define MEMTEST_32BIT
12#elif (ULONG_MAX == 18446744073709551615ULL)
13#define MEMTEST_64BIT
14#else
15#error "ULONG_MAX value not supported."
16#endif
17
d605fdab 18static struct winsize ws;
19size_t progress_printed; /* Printed chars in screen-wide progress bar. */
20size_t progress_full; /* How many chars to write to fill the progress bar. */
21
22void memtest_progress_start(char *title, int pass) {
23 int j;
24
25 printf("\x1b[H\x1b[2J"); /* Cursor home, clear screen. */
26 /* Fill with dots. */
32f62ed6 27 for (j = 0; j < ws.ws_col*(ws.ws_row-2); j++) printf(".");
28 printf("Please keep the test running several minutes per GB of memory.\n");
29 printf("Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/");
d605fdab 30 printf("\x1b[H\x1b[2K"); /* Cursor home, clear current line. */
31 printf("%s [%d]\n", title, pass); /* Print title. */
32 progress_printed = 0;
32f62ed6 33 progress_full = ws.ws_col*(ws.ws_row-3);
d605fdab 34 fflush(stdout);
35}
36
37void memtest_progress_end(void) {
38 printf("\x1b[H\x1b[2J"); /* Cursor home, clear screen. */
39}
40
41void memtest_progress_step(size_t curr, size_t size, char c) {
42 size_t chars = (curr*progress_full)/size, j;
43
44 for (j = 0; j < chars-progress_printed; j++) {
45 printf("%c",c);
46 progress_printed++;
47 }
48 fflush(stdout);
49}
50
f4df22d1 51/* Fill words stepping a single page at every write, so we continue to
52 * touch all the pages in the smallest amount of time reducing the
53 * effectiveness of caches, and making it hard for the OS to transfer
54 * pages on the swap. */
55void memtest_fill(unsigned long *l, size_t bytes) {
56 unsigned long step = 4096/sizeof(unsigned long);
57 unsigned long words = bytes/sizeof(unsigned long)/2;
58 unsigned long iwords = words/step; /* words per iteration */
59 unsigned long off, w, *l1, *l2;
60
61 assert((bytes & 4095) == 0);
62 for (off = 0; off < step; off++) {
63 l1 = l+off;
64 l2 = l1+words;
65 for (w = 0; w < iwords; w++) {
66#ifdef MEMTEST_32BIT
67 *l1 = *l2 = ((unsigned long) (rand()&0xffff)) |
68 (((unsigned long) (rand()&0xffff)) << 16);
69#else
70 *l1 = *l2 = ((unsigned long) (rand()&0xffff)) |
71 (((unsigned long) (rand()&0xffff)) << 16) |
72 (((unsigned long) (rand()&0xffff)) << 32) |
73 (((unsigned long) (rand()&0xffff)) << 48);
74#endif
75 l1 += step;
76 l2 += step;
d605fdab 77 if ((w & 0xffff) == 0)
78 memtest_progress_step(w+iwords*off,words,'+');
f4df22d1 79 }
80 }
81}
82
83void memtest_compare(unsigned long *l, size_t bytes) {
84 unsigned long words = bytes/sizeof(unsigned long)/2;
85 unsigned long w, *l1, *l2;
86
87 assert((bytes & 4095) == 0);
88 l1 = l;
89 l2 = l1+words;
90 for (w = 0; w < words; w++) {
91 if (*l1 != *l2) {
92 printf("\n*** MEMORY ERROR DETECTED: %p != %p (%lu vs %lu)\n",
93 (void*)l1, (void*)l2, *l1, *l2);
94 exit(1);
95 }
96 l1 ++;
97 l2 ++;
d605fdab 98 if ((w & 0xffff) == 0) memtest_progress_step(w,words,'=');
f4df22d1 99 }
100}
101
102void memtest_test(size_t megabytes, int passes) {
103 size_t bytes = megabytes*1024*1024;
104 unsigned long *m = malloc(bytes);
d605fdab 105 int pass = 0, j;
f4df22d1 106
107 if (m == NULL) {
108 fprintf(stderr,"Unable to allocate %zu megabytes: %s",
109 megabytes, strerror(errno));
110 exit(1);
111 }
112 while (pass != passes) {
113 pass++;
d605fdab 114 memtest_progress_start("Random fill",pass);
f4df22d1 115 memtest_fill(m,bytes);
d605fdab 116 memtest_progress_end();
117 for (j = 0; j < 4; j++) {
118 memtest_progress_start("Compare",pass);
119 memtest_compare(m,bytes);
120 memtest_progress_end();
121 }
f4df22d1 122 }
123}
124
125void memtest(size_t megabytes, int passes) {
d605fdab 126 if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
127 ws.ws_col = 80;
128 ws.ws_row = 20;
129 }
f4df22d1 130 memtest_test(megabytes,passes);
131 printf("\nYour memory passed this test.\n");
132 printf("Please if you are stil in doubt use the following two tools:\n");
133 printf("1) memtest86: http://www.memtest86.com/\n");
134 printf("2) memtester: http://pyropus.ca/software/memtester/\n");
135 exit(0);
136}