]> git.saurik.com Git - redis.git/blob - src/memtest.c
Fixed typo.
[redis.git] / src / memtest.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <limits.h>
6 #include <errno.h>
7 #include <termios.h>
8 #include <sys/ioctl.h>
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
18 static struct winsize ws;
19 size_t progress_printed; /* Printed chars in screen-wide progress bar. */
20 size_t progress_full; /* How many chars to write to fill the progress bar. */
21
22 void 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. */
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/");
30 printf("\x1b[H\x1b[2K"); /* Cursor home, clear current line. */
31 printf("%s [%d]\n", title, pass); /* Print title. */
32 progress_printed = 0;
33 progress_full = ws.ws_col*(ws.ws_row-3);
34 fflush(stdout);
35 }
36
37 void memtest_progress_end(void) {
38 printf("\x1b[H\x1b[2J"); /* Cursor home, clear screen. */
39 }
40
41 void 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
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. */
55 void 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;
77 if ((w & 0xffff) == 0)
78 memtest_progress_step(w+iwords*off,words,'+');
79 }
80 }
81 }
82
83 void 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 ++;
98 if ((w & 0xffff) == 0) memtest_progress_step(w,words,'=');
99 }
100 }
101
102 void memtest_test(size_t megabytes, int passes) {
103 size_t bytes = megabytes*1024*1024;
104 unsigned long *m = malloc(bytes);
105 int pass = 0, j;
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++;
114 memtest_progress_start("Random fill",pass);
115 memtest_fill(m,bytes);
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 }
122 }
123 }
124
125 void memtest(size_t megabytes, int passes) {
126 if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
127 ws.ws_col = 80;
128 ws.ws_row = 20;
129 }
130 memtest_test(megabytes,passes);
131 printf("\nYour memory passed this test.\n");
132 printf("Please if you are still 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 }