| OLD | NEW |
| 1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 #include "base/logging.h" | 89 #include "base/logging.h" |
| 90 #include "base/simple_mutex.h" | 90 #include "base/simple_mutex.h" |
| 91 #include "google/malloc_hook.h" | 91 #include "google/malloc_hook.h" |
| 92 #include "google/malloc_extension.h" | 92 #include "google/malloc_extension.h" |
| 93 #include "google/tcmalloc.h" | 93 #include "google/tcmalloc.h" |
| 94 #include "thread_cache.h" | 94 #include "thread_cache.h" |
| 95 #include "tests/testutil.h" | 95 #include "tests/testutil.h" |
| 96 | 96 |
| 97 // Windows doesn't define pvalloc and a few other obsolete unix | 97 // Windows doesn't define pvalloc and a few other obsolete unix |
| 98 // functions; nor does it define posix_memalign (which is not obsolete). | 98 // functions; nor does it define posix_memalign (which is not obsolete). |
| 99 #if defined(_MSC_VER) || defined(__MINGW32__) | 99 #if defined(_WIN32) |
| 100 # define cfree free // don't bother to try to test these obsolete fns | 100 # define cfree free // don't bother to try to test these obsolete fns |
| 101 # define valloc malloc | 101 # define valloc malloc |
| 102 # define pvalloc malloc | 102 # define pvalloc malloc |
| 103 // I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc | 103 // I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc |
| 104 // must be paired with _aligned_free (not normal free), which is too | 104 // must be paired with _aligned_free (not normal free), which is too |
| 105 // invasive a change to how we allocate memory here. So just bail | 105 // invasive a change to how we allocate memory here. So just bail |
| 106 # include <errno.h> | 106 static bool kOSSupportsMemalign = false; |
| 107 # define memalign(alignment, size) malloc(size) | 107 static inline void* Memalign(size_t align, size_t size) { |
| 108 # define posix_memalign(pptr, align, size) ((*(pptr)=malloc(size)) ? 0 : ENOMEM) | 108 //LOG(FATAL) << "memalign not supported on windows"; |
| 109 exit(1); |
| 110 } |
| 111 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { |
| 112 //LOG(FATAL) << "posix_memalign not supported on windows"; |
| 113 exit(1); |
| 114 } |
| 115 |
| 116 // OS X defines posix_memalign in some OS versions but not others; |
| 117 // it's confusing enough to check that it's easiest to just not to test. |
| 118 #elif defined(__APPLE__) |
| 119 static bool kOSSupportsMemalign = false; |
| 120 static inline void* Memalign(size_t align, size_t size) { |
| 121 //LOG(FATAL) << "memalign not supported on OS X"; |
| 122 exit(1); |
| 123 } |
| 124 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { |
| 125 //LOG(FATAL) << "posix_memalign not supported on OS X"; |
| 126 exit(1); |
| 127 } |
| 128 |
| 129 #else |
| 130 static bool kOSSupportsMemalign = true; |
| 131 static inline void* Memalign(size_t align, size_t size) { |
| 132 return memalign(align, size); |
| 133 } |
| 134 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { |
| 135 return posix_memalign(ptr, align, size); |
| 136 } |
| 137 |
| 109 #endif | 138 #endif |
| 110 | 139 |
| 111 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old | 140 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old |
| 112 // form of the name instead. | 141 // form of the name instead. |
| 113 #ifndef MAP_ANONYMOUS | 142 #ifndef MAP_ANONYMOUS |
| 114 # define MAP_ANONYMOUS MAP_ANON | 143 # define MAP_ANONYMOUS MAP_ANON |
| 115 #endif | 144 #endif |
| 116 | 145 |
| 117 #define LOGSTREAM stdout | 146 #define LOGSTREAM stdout |
| 118 | 147 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 142 static const int FLAGS_allocweight = 50; // Weight for picking allocation | 171 static const int FLAGS_allocweight = 50; // Weight for picking allocation |
| 143 static const int FLAGS_freeweight = 50; // Weight for picking free | 172 static const int FLAGS_freeweight = 50; // Weight for picking free |
| 144 static const int FLAGS_updateweight = 10; // Weight for picking update | 173 static const int FLAGS_updateweight = 10; // Weight for picking update |
| 145 static const int FLAGS_passweight = 1; // Weight for passing object | 174 static const int FLAGS_passweight = 1; // Weight for passing object |
| 146 | 175 |
| 147 static const int kSizeBits = 8 * sizeof(size_t); | 176 static const int kSizeBits = 8 * sizeof(size_t); |
| 148 static const size_t kMaxSize = ~static_cast<size_t>(0); | 177 static const size_t kMaxSize = ~static_cast<size_t>(0); |
| 149 static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1); | 178 static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1); |
| 150 | 179 |
| 151 static const size_t kNotTooBig = 100000; | 180 static const size_t kNotTooBig = 100000; |
| 152 static const size_t kTooBig = kMaxSize; | 181 // We want an allocation that is definitely more than main memory. OS |
| 182 // X has special logic to discard very big allocs before even passing |
| 183 // the request along to the user-defined memory allocator; we're not |
| 184 // interested in testing their logic, so we have to make sure we're |
| 185 // not *too* big. |
| 186 static const size_t kTooBig = kMaxSize - 100000; |
| 153 | 187 |
| 154 static int news_handled = 0; | 188 static int news_handled = 0; |
| 155 | 189 |
| 156 // Global array of threads | 190 // Global array of threads |
| 157 class TesterThread; | 191 class TesterThread; |
| 158 static TesterThread** threads; | 192 static TesterThread** threads; |
| 159 | 193 |
| 160 // To help with generating random numbers | 194 // To help with generating random numbers |
| 161 class TestHarness { | 195 class TestHarness { |
| 162 private: | 196 private: |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 assert(i < types_->size()); | 273 assert(i < types_->size()); |
| 240 if ((num_tests_ % FLAGS_log_every_n_tests) == 0) { | 274 if ((num_tests_ % FLAGS_log_every_n_tests) == 0) { |
| 241 fprintf(LOGSTREAM, " Test %d out of %d: %s\n", | 275 fprintf(LOGSTREAM, " Test %d out of %d: %s\n", |
| 242 num_tests_, FLAGS_numtests, (*types_)[i].name.c_str()); | 276 num_tests_, FLAGS_numtests, (*types_)[i].name.c_str()); |
| 243 } | 277 } |
| 244 return (*types_)[i].type; | 278 return (*types_)[i].type; |
| 245 } | 279 } |
| 246 | 280 |
| 247 class AllocatorState : public TestHarness { | 281 class AllocatorState : public TestHarness { |
| 248 public: | 282 public: |
| 249 explicit AllocatorState(int seed) : TestHarness(seed) { | 283 explicit AllocatorState(int seed) : TestHarness(seed), memalign_fraction_(0) { |
| 250 CHECK_GE(FLAGS_memalign_max_fraction, 0); | 284 if (kOSSupportsMemalign) { |
| 251 CHECK_LE(FLAGS_memalign_max_fraction, 1); | 285 CHECK_GE(FLAGS_memalign_max_fraction, 0); |
| 252 CHECK_GE(FLAGS_memalign_min_fraction, 0); | 286 CHECK_LE(FLAGS_memalign_max_fraction, 1); |
| 253 CHECK_LE(FLAGS_memalign_min_fraction, 1); | 287 CHECK_GE(FLAGS_memalign_min_fraction, 0); |
| 254 double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; | 288 CHECK_LE(FLAGS_memalign_min_fraction, 1); |
| 255 CHECK_GE(delta, 0); | 289 double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; |
| 256 memalign_fraction_ = (Uniform(10000)/10000.0 * delta + | 290 CHECK_GE(delta, 0); |
| 257 FLAGS_memalign_min_fraction); | 291 memalign_fraction_ = (Uniform(10000)/10000.0 * delta + |
| 258 //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); | 292 FLAGS_memalign_min_fraction); |
| 293 //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); |
| 294 } |
| 259 } | 295 } |
| 260 virtual ~AllocatorState() {} | 296 virtual ~AllocatorState() {} |
| 261 | 297 |
| 262 // Allocate memory. Randomly choose between malloc() or posix_memalign(). | 298 // Allocate memory. Randomly choose between malloc() or posix_memalign(). |
| 263 void* alloc(size_t size) { | 299 void* alloc(size_t size) { |
| 264 if (Uniform(100) < memalign_fraction_ * 100) { | 300 if (Uniform(100) < memalign_fraction_ * 100) { |
| 265 // Try a few times to find a reasonable alignment, or fall back on malloc. | 301 // Try a few times to find a reasonable alignment, or fall back on malloc. |
| 266 for (int i = 0; i < 5; i++) { | 302 for (int i = 0; i < 5; i++) { |
| 267 size_t alignment = 1 << Uniform(FLAGS_lg_max_memalign); | 303 size_t alignment = 1 << Uniform(FLAGS_lg_max_memalign); |
| 268 if (alignment >= sizeof(intptr_t) && | 304 if (alignment >= sizeof(intptr_t) && |
| 269 (size < sizeof(intptr_t) || | 305 (size < sizeof(intptr_t) || |
| 270 alignment < FLAGS_memalign_max_alignment_ratio * size)) { | 306 alignment < FLAGS_memalign_max_alignment_ratio * size)) { |
| 271 void *result = reinterpret_cast<void*>(static_cast<intptr_t>(0x1234)); | 307 void *result = reinterpret_cast<void*>(static_cast<intptr_t>(0x1234)); |
| 272 int err = posix_memalign(&result, alignment, size); | 308 int err = PosixMemalign(&result, alignment, size); |
| 273 if (err != 0) { | 309 if (err != 0) { |
| 274 CHECK_EQ(err, ENOMEM); | 310 CHECK_EQ(err, ENOMEM); |
| 275 } | 311 } |
| 276 return err == 0 ? result : NULL; | 312 return err == 0 ? result : NULL; |
| 277 } | 313 } |
| 278 } | 314 } |
| 279 } | 315 } |
| 280 return malloc(size); | 316 return malloc(size); |
| 281 } | 317 } |
| 282 | 318 |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 volatile bool g_no_memory = false; | 920 volatile bool g_no_memory = false; |
| 885 std::new_handler g_old_handler = NULL; | 921 std::new_handler g_old_handler = NULL; |
| 886 static void OnNoMemory() { | 922 static void OnNoMemory() { |
| 887 g_no_memory = true; | 923 g_no_memory = true; |
| 888 std::set_new_handler(g_old_handler); | 924 std::set_new_handler(g_old_handler); |
| 889 } | 925 } |
| 890 | 926 |
| 891 static void TestSetNewMode() { | 927 static void TestSetNewMode() { |
| 892 int old_mode = tc_set_new_mode(1); | 928 int old_mode = tc_set_new_mode(1); |
| 893 | 929 |
| 894 // DebugAllocation will try to catch huge allocations. We need to avoid this | |
| 895 // by requesting a smaller malloc block, that still can't be satisfied. | |
| 896 const size_t kHugeRequest = kTooBig - 1024; | |
| 897 | |
| 898 g_old_handler = std::set_new_handler(&OnNoMemory); | 930 g_old_handler = std::set_new_handler(&OnNoMemory); |
| 899 g_no_memory = false; | 931 g_no_memory = false; |
| 900 void* ret = malloc(kHugeRequest); | 932 void* ret = malloc(kTooBig); |
| 901 EXPECT_EQ(NULL, ret); | 933 EXPECT_EQ(NULL, ret); |
| 902 EXPECT_TRUE(g_no_memory); | 934 EXPECT_TRUE(g_no_memory); |
| 903 | 935 |
| 904 g_old_handler = std::set_new_handler(&OnNoMemory); | 936 g_old_handler = std::set_new_handler(&OnNoMemory); |
| 905 g_no_memory = false; | 937 g_no_memory = false; |
| 906 ret = calloc(1, kHugeRequest); | 938 ret = calloc(1, kTooBig); |
| 907 EXPECT_EQ(NULL, ret); | 939 EXPECT_EQ(NULL, ret); |
| 908 EXPECT_TRUE(g_no_memory); | 940 EXPECT_TRUE(g_no_memory); |
| 909 | 941 |
| 910 g_old_handler = std::set_new_handler(&OnNoMemory); | 942 g_old_handler = std::set_new_handler(&OnNoMemory); |
| 911 g_no_memory = false; | 943 g_no_memory = false; |
| 912 ret = realloc(NULL, kHugeRequest); | 944 ret = realloc(NULL, kTooBig); |
| 913 EXPECT_EQ(NULL, ret); | 945 EXPECT_EQ(NULL, ret); |
| 914 EXPECT_TRUE(g_no_memory); | 946 EXPECT_TRUE(g_no_memory); |
| 915 | 947 |
| 916 // Not really important, but must be small enough such that kAlignment + | 948 if (kOSSupportsMemalign) { |
| 917 // kHugeRequest does not overflow. | 949 // Not really important, but must be small enough such that |
| 918 const int kAlignment = 1 << 5; | 950 // kAlignment + kTooBig does not overflow. |
| 951 const int kAlignment = 1 << 5; |
| 919 | 952 |
| 920 g_old_handler = std::set_new_handler(&OnNoMemory); | 953 g_old_handler = std::set_new_handler(&OnNoMemory); |
| 921 g_no_memory = false; | 954 g_no_memory = false; |
| 922 ret = memalign(kAlignment, kHugeRequest); | 955 ret = Memalign(kAlignment, kTooBig); |
| 923 EXPECT_EQ(NULL, ret); | 956 EXPECT_EQ(NULL, ret); |
| 924 EXPECT_TRUE(g_no_memory); | 957 EXPECT_TRUE(g_no_memory); |
| 925 | 958 |
| 926 g_old_handler = std::set_new_handler(&OnNoMemory); | 959 g_old_handler = std::set_new_handler(&OnNoMemory); |
| 927 g_no_memory = false; | 960 g_no_memory = false; |
| 928 EXPECT_EQ(ENOMEM, | 961 EXPECT_EQ(ENOMEM, |
| 929 posix_memalign(&ret, kAlignment, kHugeRequest)); | 962 PosixMemalign(&ret, kAlignment, kTooBig)); |
| 930 EXPECT_EQ(NULL, ret); | 963 EXPECT_EQ(NULL, ret); |
| 931 EXPECT_TRUE(g_no_memory); | 964 EXPECT_TRUE(g_no_memory); |
| 965 } |
| 932 | 966 |
| 933 tc_set_new_mode(old_mode); | 967 tc_set_new_mode(old_mode); |
| 934 } | 968 } |
| 935 | 969 |
| 936 static int RunAllTests(int argc, char** argv) { | 970 static int RunAllTests(int argc, char** argv) { |
| 937 // Optional argv[1] is the seed | 971 // Optional argv[1] is the seed |
| 938 AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); | 972 AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); |
| 939 | 973 |
| 940 SetTestResourceLimit(); | 974 SetTestResourceLimit(); |
| 941 | 975 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 // We make sure we realloc to a big size, since some systems (OS | 1059 // We make sure we realloc to a big size, since some systems (OS |
| 1026 // X) will notice if the realloced size continues to fit into the | 1060 // X) will notice if the realloced size continues to fit into the |
| 1027 // malloc-block and make this a noop if so. | 1061 // malloc-block and make this a noop if so. |
| 1028 p1 = realloc(p1, 30000); | 1062 p1 = realloc(p1, 30000); |
| 1029 CHECK(p1 != NULL); | 1063 CHECK(p1 != NULL); |
| 1030 VerifyNewHookWasCalled(); | 1064 VerifyNewHookWasCalled(); |
| 1031 VerifyDeleteHookWasCalled(); | 1065 VerifyDeleteHookWasCalled(); |
| 1032 cfree(p1); // synonym for free | 1066 cfree(p1); // synonym for free |
| 1033 VerifyDeleteHookWasCalled(); | 1067 VerifyDeleteHookWasCalled(); |
| 1034 | 1068 |
| 1035 CHECK_EQ(posix_memalign(&p1, sizeof(p1), 40), 0); | 1069 if (kOSSupportsMemalign) { |
| 1036 CHECK(p1 != NULL); | 1070 CHECK_EQ(PosixMemalign(&p1, sizeof(p1), 40), 0); |
| 1037 VerifyNewHookWasCalled(); | 1071 CHECK(p1 != NULL); |
| 1038 free(p1); | 1072 VerifyNewHookWasCalled(); |
| 1039 VerifyDeleteHookWasCalled(); | 1073 free(p1); |
| 1074 VerifyDeleteHookWasCalled(); |
| 1040 | 1075 |
| 1041 p1 = memalign(sizeof(p1) * 2, 50); | 1076 p1 = Memalign(sizeof(p1) * 2, 50); |
| 1042 CHECK(p1 != NULL); | 1077 CHECK(p1 != NULL); |
| 1043 VerifyNewHookWasCalled(); | 1078 VerifyNewHookWasCalled(); |
| 1044 free(p1); | 1079 free(p1); |
| 1045 VerifyDeleteHookWasCalled(); | 1080 VerifyDeleteHookWasCalled(); |
| 1081 } |
| 1046 | 1082 |
| 1047 // Windows has _aligned_malloc. Let's test that that's captured too. | 1083 // Windows has _aligned_malloc. Let's test that that's captured too. |
| 1048 #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED
_MALLOC) | 1084 #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED
_MALLOC) |
| 1049 p1 = _aligned_malloc(sizeof(p1) * 2, 64); | 1085 p1 = _aligned_malloc(sizeof(p1) * 2, 64); |
| 1050 VerifyNewHookWasCalled(); | 1086 VerifyNewHookWasCalled(); |
| 1051 _aligned_free(p1); | 1087 _aligned_free(p1); |
| 1052 VerifyDeleteHookWasCalled(); | 1088 VerifyDeleteHookWasCalled(); |
| 1053 #endif | 1089 #endif |
| 1054 | 1090 |
| 1055 p1 = valloc(60); | 1091 p1 = valloc(60); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 int minor; | 1313 int minor; |
| 1278 const char* patch; | 1314 const char* patch; |
| 1279 char mmp[64]; | 1315 char mmp[64]; |
| 1280 const char* human_version = tc_version(&major, &minor, &patch); | 1316 const char* human_version = tc_version(&major, &minor, &patch); |
| 1281 snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); | 1317 snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); |
| 1282 CHECK(!strcmp(PACKAGE_STRING, human_version)); | 1318 CHECK(!strcmp(PACKAGE_STRING, human_version)); |
| 1283 CHECK(!strcmp(PACKAGE_VERSION, mmp)); | 1319 CHECK(!strcmp(PACKAGE_VERSION, mmp)); |
| 1284 | 1320 |
| 1285 fprintf(LOGSTREAM, "PASS\n"); | 1321 fprintf(LOGSTREAM, "PASS\n"); |
| 1286 } | 1322 } |
| OLD | NEW |