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