1 //===--------------------- test_fallback_malloc.cpp -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <iostream> 10 #include <deque> 11 12 #include <__threading_support> 13 14 typedef std::deque<void *> container; 15 16 // #define DEBUG_FALLBACK_MALLOC 17 #define INSTRUMENT_FALLBACK_MALLOC 18 #include "../src/fallback_malloc.cpp" 19 20 container alloc_series ( size_t sz ) { 21 container ptrs; 22 void *p; 23 24 while ( NULL != ( p = fallback_malloc ( sz ))) 25 ptrs.push_back ( p ); 26 return ptrs; 27 } 28 29 container alloc_series ( size_t sz, float growth ) { 30 container ptrs; 31 void *p; 32 33 while ( NULL != ( p = fallback_malloc ( sz ))) { 34 ptrs.push_back ( p ); 35 sz *= growth; 36 } 37 38 return ptrs; 39 } 40 41 container alloc_series ( const size_t *first, size_t len ) { 42 container ptrs; 43 const size_t *last = first + len; 44 void * p; 45 46 for ( const size_t *iter = first; iter != last; ++iter ) { 47 if ( NULL == (p = fallback_malloc ( *iter ))) 48 break; 49 ptrs.push_back ( p ); 50 } 51 52 return ptrs; 53 } 54 55 void *pop ( container &c, bool from_end ) { 56 void *ptr; 57 if ( from_end ) { 58 ptr = c.back (); 59 c.pop_back (); 60 } 61 else { 62 ptr = c.front (); 63 c.pop_front (); 64 } 65 return ptr; 66 } 67 68 void exhaustion_test1 () { 69 container ptrs; 70 71 init_heap (); 72 std::cout << "Constant exhaustion tests" << std::endl; 73 74 // Delete in allocation order 75 ptrs = alloc_series ( 32 ); 76 std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl; 77 print_free_list (); 78 for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter ) 79 fallback_free ( *iter ); 80 print_free_list (); 81 std::cout << "----" << std::endl; 82 83 // Delete in reverse order 84 ptrs = alloc_series ( 32 ); 85 std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl; 86 for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter ) 87 fallback_free ( *iter ); 88 print_free_list (); 89 std::cout << "----" << std::endl; 90 91 // Alternate deletions 92 ptrs = alloc_series ( 32 ); 93 std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl; 94 while ( ptrs.size () > 0 ) 95 fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 )); 96 print_free_list (); 97 } 98 99 void exhaustion_test2 () { 100 container ptrs; 101 init_heap (); 102 103 std::cout << "Growing exhaustion tests" << std::endl; 104 105 // Delete in allocation order 106 ptrs = alloc_series ( 32, 1.5 ); 107 std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl; 108 print_free_list (); 109 for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter ) 110 fallback_free ( *iter ); 111 print_free_list (); 112 std::cout << "----" << std::endl; 113 114 // Delete in reverse order 115 print_free_list (); 116 ptrs = alloc_series ( 32, 1.5 ); 117 std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl; 118 for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter ) 119 fallback_free ( *iter ); 120 print_free_list (); 121 std::cout << "----" << std::endl; 122 123 // Alternate deletions 124 ptrs = alloc_series ( 32, 1.5 ); 125 std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl; 126 while ( ptrs.size () > 0 ) 127 fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 )); 128 print_free_list (); 129 130 } 131 132 void exhaustion_test3 () { 133 const size_t allocs [] = { 124, 60, 252, 60, 4 }; 134 container ptrs; 135 init_heap (); 136 137 std::cout << "Complete exhaustion tests" << std::endl; 138 139 // Delete in allocation order 140 ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] )); 141 std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl; 142 print_free_list (); 143 for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter ) 144 fallback_free ( *iter ); 145 print_free_list (); 146 std::cout << "----" << std::endl; 147 148 // Delete in reverse order 149 print_free_list (); 150 ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] )); 151 std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl; 152 for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter ) 153 fallback_free ( *iter ); 154 print_free_list (); 155 std::cout << "----" << std::endl; 156 157 // Alternate deletions 158 ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] )); 159 std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl; 160 while ( ptrs.size () > 0 ) 161 fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 )); 162 print_free_list (); 163 164 } 165 166 167 int main () { 168 print_free_list (); 169 170 char *p = (char *) fallback_malloc ( 1024 ); // too big! 171 std::cout << "fallback_malloc ( 1024 ) --> " << (unsigned long ) p << std::endl; 172 print_free_list (); 173 174 p = (char *) fallback_malloc ( 32 ); 175 std::cout << "fallback_malloc ( 32 ) --> " << (unsigned long) (p - heap) << std::endl; 176 if ( !is_fallback_ptr ( p )) 177 std::cout << "### p is not a fallback pointer!!" << std::endl; 178 179 print_free_list (); 180 fallback_free ( p ); 181 print_free_list (); 182 183 std::cout << std::endl; 184 exhaustion_test1 (); std::cout << std::endl; 185 exhaustion_test2 (); std::cout << std::endl; 186 exhaustion_test3 (); std::cout << std::endl; 187 return 0; 188 } 189