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