Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2004, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // ---
     31 // Author: Sanjay Ghemawat
     32 //
     33 // Check memalign related routines.
     34 //
     35 // We can't really do a huge amount of checking, but at the very
     36 // least, the following code checks that return values are properly
     37 // aligned, and that writing into the objects works.
     38 
     39 #include "config_for_unittests.h"
     40 
     41 // Complicated ordering requirements.  tcmalloc.h defines (indirectly)
     42 // _POSIX_C_SOURCE, which it needs so stdlib.h defines posix_memalign.
     43 // unistd.h, on the other hand, requires _POSIX_C_SOURCE to be unset,
     44 // at least on Mac OS X, in order to define getpagesize.  The solution
     45 // is to #include unistd.h first.  This is safe because unistd.h
     46 // doesn't sub-include stdlib.h, so we'll still get posix_memalign
     47 // when we #include stdlib.h.  Blah.
     48 #ifdef HAVE_UNISTD_H
     49 #include <unistd.h>        // for getpagesize()
     50 #endif
     51 #include "tcmalloc.h"      // must come early, to pick up posix_memalign
     52 #include <assert.h>
     53 #include <stdlib.h>        // defines posix_memalign
     54 #include <stdio.h>         // for the printf at the end
     55 #ifdef HAVE_STDINT_H
     56 #include <stdint.h>        // for uintptr_t
     57 #endif
     58 #ifdef HAVE_UNISTD_H
     59 #include <unistd.h>        // for getpagesize()
     60 #endif
     61 // Malloc can be in several places on older versions of OS X.
     62 #if defined(HAVE_MALLOC_H)
     63 #include <malloc.h>        // for memalign() and valloc()
     64 #elif defined(HAVE_MALLOC_MALLOC_H)
     65 #include <malloc/malloc.h>
     66 #elif defined(HAVE_SYS_MALLOC_H)
     67 #include <sys/malloc.h>
     68 #endif
     69 #include "base/basictypes.h"
     70 #include "base/logging.h"
     71 #include "tests/testutil.h"
     72 
     73 
     74 // Return the next interesting size/delta to check.  Returns -1 if no more.
     75 static int NextSize(int size) {
     76   if (size < 100) {
     77     return size+1;
     78   } else if (size < 1048576) {
     79     // Find next power of two
     80     int power = 1;
     81     while (power < size) {
     82       power <<= 1;
     83     }
     84 
     85     // Yield (power-1, power, power+1)
     86     if (size < power-1) {
     87       return power-1;
     88     } else if (size == power-1) {
     89       return power;
     90     } else {
     91       assert(size == power);
     92       return power+1;
     93     }
     94   } else {
     95     return -1;
     96   }
     97 }
     98 
     99 // Shortform for cast
    100 static uintptr_t Number(void* p) {
    101   return reinterpret_cast<uintptr_t>(p);
    102 }
    103 
    104 // Check alignment
    105 static void CheckAlignment(void* p, int align) {
    106   if ((Number(p) & (align-1)) != 0)
    107     LOG(FATAL, "wrong alignment; wanted 0x%x; got %p\n", align, p);
    108 }
    109 
    110 // Fill a buffer of the specified size with a predetermined pattern
    111 static void Fill(void* p, int n, char seed) {
    112   unsigned char* buffer = reinterpret_cast<unsigned char*>(p);
    113   for (int i = 0; i < n; i++) {
    114     buffer[i] = ((seed + i) & 0xff);
    115   }
    116 }
    117 
    118 // Check that the specified buffer has the predetermined pattern
    119 // generated by Fill()
    120 static bool Valid(const void* p, int n, char seed) {
    121   const unsigned char* buffer = reinterpret_cast<const unsigned char*>(p);
    122   for (int i = 0; i < n; i++) {
    123     if (buffer[i] != ((seed + i) & 0xff)) {
    124       return false;
    125     }
    126   }
    127   return true;
    128 }
    129 
    130 int main(int argc, char** argv) {
    131   SetTestResourceLimit();
    132 
    133   // Try allocating data with a bunch of alignments and sizes
    134   for (int a = 1; a < 1048576; a *= 2) {
    135     for (int s = 0; s != -1; s = NextSize(s)) {
    136       void* ptr = memalign(a, s);
    137       CheckAlignment(ptr, a);
    138       Fill(ptr, s, 'x');
    139       CHECK(Valid(ptr, s, 'x'));
    140       free(ptr);
    141 
    142       if ((a >= sizeof(void*)) && ((a & (a-1)) == 0)) {
    143         CHECK(posix_memalign(&ptr, a, s) == 0);
    144         CheckAlignment(ptr, a);
    145         Fill(ptr, s, 'y');
    146         CHECK(Valid(ptr, s, 'y'));
    147         free(ptr);
    148       }
    149     }
    150   }
    151 
    152   {
    153     // Check various corner cases
    154     void* p1 = memalign(1<<20, 1<<19);
    155     void* p2 = memalign(1<<19, 1<<19);
    156     void* p3 = memalign(1<<21, 1<<19);
    157     CheckAlignment(p1, 1<<20);
    158     CheckAlignment(p2, 1<<19);
    159     CheckAlignment(p3, 1<<21);
    160     Fill(p1, 1<<19, 'a');
    161     Fill(p2, 1<<19, 'b');
    162     Fill(p3, 1<<19, 'c');
    163     CHECK(Valid(p1, 1<<19, 'a'));
    164     CHECK(Valid(p2, 1<<19, 'b'));
    165     CHECK(Valid(p3, 1<<19, 'c'));
    166     free(p1);
    167     free(p2);
    168     free(p3);
    169   }
    170 
    171   {
    172     // posix_memalign
    173     void* ptr;
    174     CHECK(posix_memalign(&ptr, 0, 1) == EINVAL);
    175     CHECK(posix_memalign(&ptr, sizeof(void*)/2, 1) == EINVAL);
    176     CHECK(posix_memalign(&ptr, sizeof(void*)+1, 1) == EINVAL);
    177     CHECK(posix_memalign(&ptr, 4097, 1) == EINVAL);
    178 
    179     // Grab some memory so that the big allocation below will definitely fail.
    180     void* p_small = malloc(4*1048576);
    181     CHECK(p_small != NULL);
    182 
    183     // Make sure overflow is returned as ENOMEM
    184     const size_t zero = 0;
    185     static const size_t kMinusNTimes = 10;
    186     for ( size_t i = 1; i < kMinusNTimes; ++i ) {
    187       int r = posix_memalign(&ptr, 1024, zero - i);
    188       CHECK(r == ENOMEM);
    189     }
    190 
    191     free(p_small);
    192   }
    193 
    194   const int pagesize = getpagesize();
    195   {
    196     // valloc
    197     for (int s = 0; s != -1; s = NextSize(s)) {
    198       void* p = valloc(s);
    199       CheckAlignment(p, pagesize);
    200       Fill(p, s, 'v');
    201       CHECK(Valid(p, s, 'v'));
    202       free(p);
    203     }
    204   }
    205 
    206   {
    207     // pvalloc
    208     for (int s = 0; s != -1; s = NextSize(s)) {
    209       void* p = pvalloc(s);
    210       CheckAlignment(p, pagesize);
    211       int alloc_needed = ((s + pagesize - 1) / pagesize) * pagesize;
    212       Fill(p, alloc_needed, 'x');
    213       CHECK(Valid(p, alloc_needed, 'x'));
    214       free(p);
    215     }
    216   }
    217 
    218   printf("PASS\n");
    219   return 0;
    220 }
    221