summaryrefslogtreecommitdiff
path: root/src/memtest.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2012-11-25 16:21:21 +0100
committerantirez <antirez@gmail.com>2012-11-29 10:24:35 +0100
commitb1b602a92887f271db3101d67e0319ce31fa68b3 (patch)
tree30c31d8bb91664e37167da0761c6057cf32c6077 /src/memtest.c
parent7383c3b12920c6ae20f7c64c5db92f59e2b02aa5 (diff)
downloadredis-b1b602a92887f271db3101d67e0319ce31fa68b3.tar.gz
On crash memory test rewrote so that it actaully works.
1) We no longer test location by location, otherwise the CPU write cache completely makes our business useless. 2) We still need a memory test that operates in steps from the first to the last location in order to never hit the cache, but that is still able to retain the memory content. This was tested using a Linux box containing a bad memory module with a zingle bit error (always zero). So the final solution does has an error propagation step that is: 1) Invert bits at every location. 2) Swap adiacent locations. 3) Swap adiacent locations again. 4) Invert bits at every location. 5) Swap adiacent locations. 6) Swap adiacent locations again. Before and after these steps, and after step 4, a CRC64 checksum is computed. If the three CRC64 checksums don't match, a memory error was detected.
Diffstat (limited to 'src/memtest.c')
-rw-r--r--src/memtest.c42
1 files changed, 19 insertions, 23 deletions
diff --git a/src/memtest.c b/src/memtest.c
index 82da27c8b..754d02024 100644
--- a/src/memtest.c
+++ b/src/memtest.c
@@ -241,34 +241,30 @@ void memtest_test(size_t megabytes, int passes) {
}
}
-/* This is a fast O(N) best effort memory test, only ZERO-ONE tests and
- * checkerboard tests are performed, without pauses between setting and
- * reading the value, so this can only detect a subclass of permanent errors.
- *
- * However the function does not destroy the content of the memory tested that
- * is left unmodified.
- *
- * If a memory error is detected, 1 is returned. Otherwise 0 is returned. */
-int memtest_non_destructive(void *addr, size_t size) {
+void memtest_non_destructive_invert(void *addr, size_t size) {
volatile unsigned long *p = addr;
- unsigned long val;
+ size_t words = size / sizeof(unsigned long);
size_t j;
- size /= sizeof(unsigned long);
- for (j = 0; j < size; j++) {
- val = p[j];
+ /* Invert */
+ for (j = 0; j < words; j++)
+ p[j] = ~p[j];
+}
- p[j] = 0; if (p[j] != 0) goto err;
- p[j] = (unsigned long)-1; if (p[j] != (unsigned long)-1) goto err;
- p[j] = ULONG_ONEZERO; if (p[j] != ULONG_ONEZERO) goto err;
- p[j] = ULONG_ZEROONE; if (p[j] != ULONG_ZEROONE) goto err;
- p[j] = val; /* restore the original value. */
- }
- return 0;
+void memtest_non_destructive_swap(void *addr, size_t size) {
+ volatile unsigned long *p = addr;
+ size_t words = size / sizeof(unsigned long);
+ size_t j;
-err: /* memory error detected. */
- p[j] = val;
- return 1;
+ /* Swap */
+ for (j = 0; j < words; j += 2) {
+ unsigned long a, b;
+
+ a = p[j];
+ b = p[j+1];
+ p[j] = b;
+ p[j+1] = a;
+ }
}
void memtest(size_t megabytes, int passes) {