| 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 // form of the name instead. | 117 // form of the name instead. |
| 118 #ifndef MAP_ANONYMOUS | 118 #ifndef MAP_ANONYMOUS |
| 119 # define MAP_ANONYMOUS MAP_ANON | 119 # define MAP_ANONYMOUS MAP_ANON |
| 120 #endif | 120 #endif |
| 121 | 121 |
| 122 #define LOGSTREAM stdout | 122 #define LOGSTREAM stdout |
| 123 | 123 |
| 124 using std::vector; | 124 using std::vector; |
| 125 using std::string; | 125 using std::string; |
| 126 | 126 |
| 127 DECLARE_double(tcmalloc_release_rate); | |
| 128 DECLARE_int32(max_free_queue_size); // in debugallocation.cc | |
| 129 | |
| 130 namespace testing { | 127 namespace testing { |
| 131 | 128 |
| 132 static const int FLAGS_numtests = 50000; | 129 static const int FLAGS_numtests = 50000; |
| 133 static const int FLAGS_log_every_n_tests = 50000; // log exactly once | 130 static const int FLAGS_log_every_n_tests = 50000; // log exactly once |
| 134 | 131 |
| 135 // Testing parameters | 132 // Testing parameters |
| 136 static const int FLAGS_lgmaxsize = 16; // lg() of the max size object to alloc | 133 static const int FLAGS_lgmaxsize = 16; // lg() of the max size object to alloc |
| 137 static const int FLAGS_numthreads = 10; // Number of threads | 134 static const int FLAGS_numthreads = 10; // Number of threads |
| 138 static const int FLAGS_threadmb = 4; // Max memory size allocated by thread | 135 static const int FLAGS_threadmb = 4; // Max memory size allocated by thread |
| 139 static const int FLAGS_lg_max_memalign = 18; // lg of max alignment for memalign | 136 static const int FLAGS_lg_max_memalign = 18; // lg of max alignment for memalign |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 char** array = new char*[kNum]; | 740 char** array = new char*[kNum]; |
| 744 for (int i = 0; i < kNum; ++i) { | 741 for (int i = 0; i < kNum; ++i) { |
| 745 array[i] = new char[10]; | 742 array[i] = new char[10]; |
| 746 } | 743 } |
| 747 for (int i = 0; i < kNum; ++i) { | 744 for (int i = 0; i < kNum; ++i) { |
| 748 delete[] array[i]; | 745 delete[] array[i]; |
| 749 } | 746 } |
| 750 delete[] array; | 747 delete[] array; |
| 751 } | 748 } |
| 752 | 749 |
| 753 namespace { | |
| 754 | |
| 755 struct RangeCallbackState { | |
| 756 uintptr_t ptr; | |
| 757 base::MallocRange::Type expected_type; | |
| 758 size_t min_size; | |
| 759 bool matched; | |
| 760 }; | |
| 761 | |
| 762 static void RangeCallback(void* arg, const base::MallocRange* r) { | |
| 763 RangeCallbackState* state = reinterpret_cast<RangeCallbackState*>(arg); | |
| 764 if (state->ptr >= r->address && | |
| 765 state->ptr < r->address + r->length) { | |
| 766 CHECK_EQ(r->type, state->expected_type); | |
| 767 CHECK_GE(r->length, state->min_size); | |
| 768 state->matched = true; | |
| 769 } | |
| 770 } | |
| 771 | |
| 772 // Check that at least one of the callbacks from Ranges() contains | |
| 773 // the specified address with the specified type, and has size | |
| 774 // >= min_size. | |
| 775 static void CheckRangeCallback(void* ptr, base::MallocRange::Type type, | |
| 776 size_t min_size) { | |
| 777 RangeCallbackState state; | |
| 778 state.ptr = reinterpret_cast<uintptr_t>(ptr); | |
| 779 state.expected_type = type; | |
| 780 state.min_size = min_size; | |
| 781 state.matched = false; | |
| 782 MallocExtension::instance()->Ranges(&state, RangeCallback); | |
| 783 CHECK(state.matched); | |
| 784 } | |
| 785 | |
| 786 } | |
| 787 | |
| 788 static void TestRanges() { | |
| 789 static const int MB = 1048576; | |
| 790 void* a = malloc(MB); | |
| 791 void* b = malloc(MB); | |
| 792 CheckRangeCallback(a, base::MallocRange::INUSE, MB); | |
| 793 CheckRangeCallback(b, base::MallocRange::INUSE, MB); | |
| 794 free(a); | |
| 795 CheckRangeCallback(a, base::MallocRange::FREE, MB); | |
| 796 CheckRangeCallback(b, base::MallocRange::INUSE, MB); | |
| 797 MallocExtension::instance()->ReleaseFreeMemory(); | |
| 798 CheckRangeCallback(a, base::MallocRange::UNMAPPED, MB); | |
| 799 CheckRangeCallback(b, base::MallocRange::INUSE, MB); | |
| 800 free(b); | |
| 801 CheckRangeCallback(a, base::MallocRange::UNMAPPED, MB); | |
| 802 CheckRangeCallback(b, base::MallocRange::FREE, MB); | |
| 803 } | |
| 804 | |
| 805 #ifndef DEBUGALLOCATION | |
| 806 static size_t GetUnmappedBytes() { | |
| 807 size_t bytes; | |
| 808 CHECK(MallocExtension::instance()->GetNumericProperty( | |
| 809 "tcmalloc.pageheap_unmapped_bytes", &bytes)); | |
| 810 return bytes; | |
| 811 } | |
| 812 #endif | |
| 813 | |
| 814 static void TestReleaseToSystem() { | |
| 815 // Debug allocation mode adds overhead to each allocation which | |
| 816 // messes up all the equality tests here. I just disable the | |
| 817 // teset in this mode. TODO(csilvers): get it to work for debugalloc? | |
| 818 #ifndef DEBUGALLOCATION | |
| 819 const double old_tcmalloc_release_rate = FLAGS_tcmalloc_release_rate; | |
| 820 FLAGS_tcmalloc_release_rate = 0; | |
| 821 | |
| 822 static const int MB = 1048576; | |
| 823 void* a = malloc(MB); | |
| 824 void* b = malloc(MB); | |
| 825 MallocExtension::instance()->ReleaseFreeMemory(); | |
| 826 size_t starting_bytes = GetUnmappedBytes(); | |
| 827 | |
| 828 // Calling ReleaseFreeMemory() a second time shouldn't do anything. | |
| 829 MallocExtension::instance()->ReleaseFreeMemory(); | |
| 830 EXPECT_EQ(starting_bytes, GetUnmappedBytes()); | |
| 831 | |
| 832 // ReleaseToSystem shouldn't do anything either. | |
| 833 MallocExtension::instance()->ReleaseToSystem(MB); | |
| 834 EXPECT_EQ(starting_bytes, GetUnmappedBytes()); | |
| 835 | |
| 836 free(a); | |
| 837 | |
| 838 // The span to release should be 1MB. | |
| 839 MallocExtension::instance()->ReleaseToSystem(MB/2); | |
| 840 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); | |
| 841 | |
| 842 // Should do nothing since the previous call released too much. | |
| 843 MallocExtension::instance()->ReleaseToSystem(MB/4); | |
| 844 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); | |
| 845 | |
| 846 free(b); | |
| 847 | |
| 848 // Use up the extra MB/4 bytes from 'a' and also release 'b'. | |
| 849 MallocExtension::instance()->ReleaseToSystem(MB/2); | |
| 850 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); | |
| 851 | |
| 852 // Should do nothing since the previous call released too much. | |
| 853 MallocExtension::instance()->ReleaseToSystem(MB/2); | |
| 854 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); | |
| 855 | |
| 856 // Nothing else to release. | |
| 857 MallocExtension::instance()->ReleaseFreeMemory(); | |
| 858 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); | |
| 859 | |
| 860 a = malloc(MB); | |
| 861 free(a); | |
| 862 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); | |
| 863 | |
| 864 // Releasing less than a page should still trigger a release. | |
| 865 MallocExtension::instance()->ReleaseToSystem(1); | |
| 866 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); | |
| 867 | |
| 868 FLAGS_tcmalloc_release_rate = old_tcmalloc_release_rate; | |
| 869 #endif // #ifndef DEBUGALLOCATION | |
| 870 } | |
| 871 | |
| 872 bool g_no_memory = false; | |
| 873 std::new_handler g_old_handler = NULL; | |
| 874 static void OnNoMemory() { | |
| 875 g_no_memory = true; | |
| 876 std::set_new_handler(g_old_handler); | |
| 877 } | |
| 878 | |
| 879 static void TestSetNewMode() { | |
| 880 int old_mode = tc_set_new_mode(1); | |
| 881 | |
| 882 // DebugAllocation will try to catch huge allocations. We need to avoid this | |
| 883 // by requesting a smaller malloc block, that still can't be satisfied. | |
| 884 const size_t kHugeRequest = kTooBig - 1024; | |
| 885 | |
| 886 g_old_handler = std::set_new_handler(&OnNoMemory); | |
| 887 g_no_memory = false; | |
| 888 void* ret = malloc(kHugeRequest); | |
| 889 EXPECT_EQ(NULL, ret); | |
| 890 EXPECT_TRUE(g_no_memory); | |
| 891 | |
| 892 g_old_handler = std::set_new_handler(&OnNoMemory); | |
| 893 g_no_memory = false; | |
| 894 ret = calloc(1, kHugeRequest); | |
| 895 EXPECT_EQ(NULL, ret); | |
| 896 EXPECT_TRUE(g_no_memory); | |
| 897 | |
| 898 g_old_handler = std::set_new_handler(&OnNoMemory); | |
| 899 g_no_memory = false; | |
| 900 ret = realloc(NULL, kHugeRequest); | |
| 901 EXPECT_EQ(NULL, ret); | |
| 902 EXPECT_TRUE(g_no_memory); | |
| 903 | |
| 904 // Not really important, but must be small enough such that kAlignment + | |
| 905 // kHugeRequest does not overflow. | |
| 906 const int kAlignment = 1 << 5; | |
| 907 | |
| 908 g_old_handler = std::set_new_handler(&OnNoMemory); | |
| 909 g_no_memory = false; | |
| 910 ret = memalign(kAlignment, kHugeRequest); | |
| 911 EXPECT_EQ(NULL, ret); | |
| 912 EXPECT_TRUE(g_no_memory); | |
| 913 | |
| 914 g_old_handler = std::set_new_handler(&OnNoMemory); | |
| 915 g_no_memory = false; | |
| 916 EXPECT_EQ(ENOMEM, | |
| 917 posix_memalign(&ret, kAlignment, kHugeRequest)); | |
| 918 EXPECT_EQ(NULL, ret); | |
| 919 EXPECT_TRUE(g_no_memory); | |
| 920 | |
| 921 tc_set_new_mode(old_mode); | |
| 922 } | |
| 923 | |
| 924 static int RunAllTests(int argc, char** argv) { | 750 static int RunAllTests(int argc, char** argv) { |
| 925 // Optional argv[1] is the seed | 751 // Optional argv[1] is the seed |
| 926 AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); | 752 AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); |
| 927 | 753 |
| 928 SetTestResourceLimit(); | 754 SetTestResourceLimit(); |
| 929 | 755 |
| 930 // TODO(odo): This test has been disabled because it is only by luck that it | 756 // TODO(odo): This test has been disabled because it is only by luck that it |
| 931 // does not result in fragmentation. When tcmalloc makes an allocation which | 757 // does not result in fragmentation. When tcmalloc makes an allocation which |
| 932 // spans previously unused leaves of the pagemap it will allocate and fill in | 758 // spans previously unused leaves of the pagemap it will allocate and fill in |
| 933 // the leaves to cover the new allocation. The leaves happen to be 256MiB in | 759 // the leaves to cover the new allocation. The leaves happen to be 256MiB in |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 #ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs | 1016 #ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs |
| 1191 fprintf(LOGSTREAM, "Testing out of memory\n"); | 1017 fprintf(LOGSTREAM, "Testing out of memory\n"); |
| 1192 for (int s = 0; ; s += (10<<20)) { | 1018 for (int s = 0; ; s += (10<<20)) { |
| 1193 void* large_object = rnd.alloc(s); | 1019 void* large_object = rnd.alloc(s); |
| 1194 if (large_object == NULL) break; | 1020 if (large_object == NULL) break; |
| 1195 free(large_object); | 1021 free(large_object); |
| 1196 } | 1022 } |
| 1197 #endif | 1023 #endif |
| 1198 | 1024 |
| 1199 TestHugeThreadCache(); | 1025 TestHugeThreadCache(); |
| 1200 TestRanges(); | |
| 1201 TestReleaseToSystem(); | |
| 1202 TestSetNewMode(); | |
| 1203 | 1026 |
| 1204 return 0; | 1027 return 0; |
| 1205 } | 1028 } |
| 1206 | 1029 |
| 1207 } | 1030 } |
| 1208 | 1031 |
| 1209 using testing::RunAllTests; | 1032 using testing::RunAllTests; |
| 1210 | 1033 |
| 1211 int main(int argc, char** argv) { | 1034 int main(int argc, char** argv) { |
| 1212 #ifdef DEBUGALLOCATION // debug allocation takes forever for huge allocs | |
| 1213 FLAGS_max_free_queue_size = 0; // return freed blocks to tcmalloc immediately | |
| 1214 #endif | |
| 1215 | |
| 1216 RunAllTests(argc, argv); | 1035 RunAllTests(argc, argv); |
| 1217 | 1036 |
| 1218 // Test tc_version() | 1037 // Test tc_version() |
| 1219 fprintf(LOGSTREAM, "Testing tc_version()\n"); | 1038 fprintf(LOGSTREAM, "Testing tc_version()\n"); |
| 1220 int major; | 1039 int major; |
| 1221 int minor; | 1040 int minor; |
| 1222 const char* patch; | 1041 const char* patch; |
| 1223 char mmp[64]; | 1042 char mmp[64]; |
| 1224 const char* human_version = tc_version(&major, &minor, &patch); | 1043 const char* human_version = tc_version(&major, &minor, &patch); |
| 1225 snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); | 1044 snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); |
| 1226 CHECK(!strcmp(PACKAGE_STRING, human_version)); | 1045 CHECK(!strcmp(PACKAGE_STRING, human_version)); |
| 1227 CHECK(!strcmp(PACKAGE_VERSION, mmp)); | 1046 CHECK(!strcmp(PACKAGE_VERSION, mmp)); |
| 1228 | 1047 |
| 1229 fprintf(LOGSTREAM, "PASS\n"); | 1048 fprintf(LOGSTREAM, "PASS\n"); |
| 1230 } | 1049 } |
| OLD | NEW |