LCOV - code coverage report
Current view: directory - redis/src - memtest.c (source / functions) Found Hit Coverage
Test: redis.info Lines: 127 0 0.0 %
Date: 2012-04-04 Functions: 10 0 0.0 %
Colors: not hit hit

       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                 : #ifdef MEMTEST_32BIT
      19                 : #define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL
      20                 : #define ULONG_ZEROONE 0x5555555555555555UL
      21                 : #else
      22                 : #define ULONG_ONEZERO 0xaaaaaaaaUL
      23                 : #define ULONG_ZEROONE 0x55555555UL
      24                 : #endif
      25                 : 
      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. */
      29                 : 
      30               0 : void memtest_progress_start(char *title, int pass) {
      31                 :     int j;
      32                 : 
      33               0 :     printf("\x1b[H\x1b[2J");    /* Cursor home, clear screen. */
      34                 :     /* Fill with dots. */
      35               0 :     for (j = 0; j < ws.ws_col*(ws.ws_row-2); j++) printf(".");
      36               0 :     printf("Please keep the test running several minutes per GB of memory.\n");
      37               0 :     printf("Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/");
      38               0 :     printf("\x1b[H\x1b[2K");          /* Cursor home, clear current line.  */
      39               0 :     printf("%s [%d]\n", title, pass); /* Print title. */
      40               0 :     progress_printed = 0;
      41               0 :     progress_full = ws.ws_col*(ws.ws_row-3);
      42               0 :     fflush(stdout);
      43               0 : }
      44                 : 
      45               0 : void memtest_progress_end(void) {
      46               0 :     printf("\x1b[H\x1b[2J");    /* Cursor home, clear screen. */
      47               0 : }
      48                 : 
      49               0 : void memtest_progress_step(size_t curr, size_t size, char c) {
      50               0 :     size_t chars = (curr*progress_full)/size, j;
      51                 : 
      52               0 :     for (j = 0; j < chars-progress_printed; j++) {
      53               0 :         printf("%c",c);
      54               0 :         progress_printed++;
      55                 :     }
      56               0 :     fflush(stdout);
      57               0 : }
      58                 : 
      59                 : /* Test that addressing is fine. Every location is populated with its own
      60                 :  * address, and finally verified. This test is very fast but may detect
      61                 :  * ASAP big issues with the memory subsystem. */
      62               0 : void memtest_addressing(unsigned long *l, size_t bytes) {
      63               0 :     unsigned long words = bytes/sizeof(unsigned long);
      64                 :     unsigned long j, *p;
      65                 : 
      66                 :     /* Fill */
      67               0 :     p = l;
      68               0 :     for (j = 0; j < words; j++) {
      69               0 :         *p = (unsigned long)p;
      70               0 :         p++;
      71               0 :         if ((j & 0xffff) == 0) memtest_progress_step(j,words*2,'A');
      72                 :     }
      73                 :     /* Test */
      74               0 :     p = l;
      75               0 :     for (j = 0; j < words; j++) {
      76               0 :         if (*p != (unsigned long)p) {
      77               0 :             printf("\n*** MEMORY ADDRESSING ERROR: %p contains %lu\n",
      78                 :                 (void*) p, *p);
      79               0 :             exit(1);
      80                 :         }
      81               0 :         p++;
      82               0 :         if ((j & 0xffff) == 0) memtest_progress_step(j+words,words*2,'A');
      83                 :     }
      84               0 : }
      85                 : 
      86                 : /* Fill words stepping a single page at every write, so we continue to
      87                 :  * touch all the pages in the smallest amount of time reducing the
      88                 :  * effectiveness of caches, and making it hard for the OS to transfer
      89                 :  * pages on the swap. */
      90               0 : void memtest_fill_random(unsigned long *l, size_t bytes) {
      91               0 :     unsigned long step = 4096/sizeof(unsigned long);
      92               0 :     unsigned long words = bytes/sizeof(unsigned long)/2;
      93               0 :     unsigned long iwords = words/step;  /* words per iteration */
      94                 :     unsigned long off, w, *l1, *l2;
      95                 : 
      96               0 :     assert((bytes & 4095) == 0);
      97               0 :     for (off = 0; off < step; off++) {
      98               0 :         l1 = l+off;
      99               0 :         l2 = l1+words;
     100               0 :         for (w = 0; w < iwords; w++) {
     101                 : #ifdef MEMTEST_32BIT
     102                 :             *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |
     103                 :                         (((unsigned long)    (rand()&0xffff)) << 16);
     104                 : #else
     105               0 :             *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |
     106               0 :                         (((unsigned long)    (rand()&0xffff)) << 16) |
     107               0 :                         (((unsigned long)    (rand()&0xffff)) << 32) |
     108               0 :                         (((unsigned long)    (rand()&0xffff)) << 48);
     109                 : #endif
     110               0 :             l1 += step;
     111               0 :             l2 += step;
     112               0 :             if ((w & 0xffff) == 0)
     113               0 :                 memtest_progress_step(w+iwords*off,words,'R');
     114                 :         }
     115                 :     }
     116               0 : }
     117                 : 
     118                 : /* Like memtest_fill_random() but uses the two specified values to fill
     119                 :  * memory, in an alternated way (v1|v2|v1|v2|...) */
     120               0 : void memtest_fill_value(unsigned long *l, size_t bytes, unsigned long v1,
     121                 :                         unsigned long v2, char sym)
     122                 : {
     123               0 :     unsigned long step = 4096/sizeof(unsigned long);
     124               0 :     unsigned long words = bytes/sizeof(unsigned long)/2;
     125               0 :     unsigned long iwords = words/step;  /* words per iteration */
     126                 :     unsigned long off, w, *l1, *l2, v;
     127                 : 
     128               0 :     assert((bytes & 4095) == 0);
     129               0 :     for (off = 0; off < step; off++) {
     130               0 :         l1 = l+off;
     131               0 :         l2 = l1+words;
     132               0 :         v = (off & 1) ? v2 : v1;
     133               0 :         for (w = 0; w < iwords; w++) {
     134                 : #ifdef MEMTEST_32BIT
     135                 :             *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |
     136                 :                         (((unsigned long)    (rand()&0xffff)) << 16);
     137                 : #else
     138               0 :             *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |
     139               0 :                         (((unsigned long)    (rand()&0xffff)) << 16) |
     140               0 :                         (((unsigned long)    (rand()&0xffff)) << 32) |
     141               0 :                         (((unsigned long)    (rand()&0xffff)) << 48);
     142                 : #endif
     143               0 :             l1 += step;
     144               0 :             l2 += step;
     145               0 :             if ((w & 0xffff) == 0)
     146               0 :                 memtest_progress_step(w+iwords*off,words,sym);
     147                 :         }
     148                 :     }
     149               0 : }
     150                 : 
     151               0 : void memtest_compare(unsigned long *l, size_t bytes) {
     152               0 :     unsigned long words = bytes/sizeof(unsigned long)/2;
     153                 :     unsigned long w, *l1, *l2;
     154                 : 
     155               0 :     assert((bytes & 4095) == 0);
     156               0 :     l1 = l;
     157               0 :     l2 = l1+words;
     158               0 :     for (w = 0; w < words; w++) {
     159               0 :         if (*l1 != *l2) {
     160               0 :             printf("\n*** MEMORY ERROR DETECTED: %p != %p (%lu vs %lu)\n",
     161                 :                 (void*)l1, (void*)l2, *l1, *l2);
     162               0 :             exit(1);
     163                 :         }
     164               0 :         l1 ++;
     165               0 :         l2 ++;
     166               0 :         if ((w & 0xffff) == 0) memtest_progress_step(w,words,'=');
     167                 :     }
     168               0 : }
     169                 : 
     170               0 : void memtest_compare_times(unsigned long *m, size_t bytes, int pass, int times) {
     171                 :     int j;
     172                 : 
     173               0 :     for (j = 0; j < times; j++) {
     174               0 :         memtest_progress_start("Compare",pass);
     175               0 :         memtest_compare(m,bytes);
     176               0 :         memtest_progress_end();
     177                 :     }
     178               0 : }
     179                 : 
     180               0 : void memtest_test(size_t megabytes, int passes) {
     181               0 :     size_t bytes = megabytes*1024*1024;
     182               0 :     unsigned long *m = malloc(bytes);
     183               0 :     int pass = 0;
     184                 : 
     185               0 :     if (m == NULL) {
     186               0 :         fprintf(stderr,"Unable to allocate %zu megabytes: %s",
     187                 :             megabytes, strerror(errno));
     188               0 :         exit(1);
     189                 :     }
     190               0 :     while (pass != passes) {
     191               0 :         pass++;
     192                 : 
     193               0 :         memtest_progress_start("Addressing test",pass);
     194               0 :         memtest_addressing(m,bytes);
     195               0 :         memtest_progress_end();
     196                 : 
     197               0 :         memtest_progress_start("Random fill",pass);
     198               0 :         memtest_fill_random(m,bytes);
     199               0 :         memtest_progress_end();
     200               0 :         memtest_compare_times(m,bytes,pass,4);
     201                 : 
     202               0 :         memtest_progress_start("Solid fill",pass);
     203               0 :         memtest_fill_value(m,bytes,0,(unsigned long)-1,'S');
     204               0 :         memtest_progress_end();
     205               0 :         memtest_compare_times(m,bytes,pass,4);
     206                 : 
     207               0 :         memtest_progress_start("Checkerboard fill",pass);
     208               0 :         memtest_fill_value(m,bytes,ULONG_ONEZERO,ULONG_ZEROONE,'C');
     209               0 :         memtest_progress_end();
     210               0 :         memtest_compare_times(m,bytes,pass,4);
     211                 :     }
     212               0 : }
     213                 : 
     214               0 : void memtest(size_t megabytes, int passes) {
     215               0 :     if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
     216               0 :         ws.ws_col = 80;
     217               0 :         ws.ws_row = 20;
     218                 :     }
     219               0 :     memtest_test(megabytes,passes);
     220               0 :     printf("\nYour memory passed this test.\n");
     221               0 :     printf("Please if you are still in doubt use the following two tools:\n");
     222               0 :     printf("1) memtest86: http://www.memtest86.com/\n");
     223               0 :     printf("2) memtester: http://pyropus.ca/software/memtester/\n");
     224               0 :     exit(0);
     225                 : }

Generated by: LCOV version 1.7