1b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//===--------------------- test_fallback_malloc.cpp -----------------------===//
2b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
3b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//                     The LLVM Compiler Infrastructure
4b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
5b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
7b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
8b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//===----------------------------------------------------------------------===//
9b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant
1047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include <iostream>
1147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include <deque>
1247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
1347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include <pthread.h>
1447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
1547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowtypedef std::deque<void *> container;
1647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
1747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow// #define  DEBUG_FALLBACK_MALLOC
1847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#define INSTRUMENT_FALLBACK_MALLOC
1960a178840d23fbf169a22fde1cef5e558ef232f9Howard Hinnant#include "../src/fallback_malloc.ipp"
2047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
2147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowcontainer alloc_series ( size_t sz ) {
2247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
2347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    void *p;
2447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
2547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    while ( NULL != ( p = fallback_malloc ( sz )))
2647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        ptrs.push_back ( p );
2747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    return ptrs;
2847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
2947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
3047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowcontainer alloc_series ( size_t sz, float growth ) {
3147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
3247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    void *p;
3347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
3447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    while ( NULL != ( p = fallback_malloc ( sz ))) {
3547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        ptrs.push_back ( p );
3647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        sz *= growth;
3747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        }
3847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
3947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    return ptrs;
4047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
4147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
4247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowcontainer alloc_series ( const size_t *first, size_t len ) {
4347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
4447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    const size_t *last = first + len;
4547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    void * p;
4647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
4747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( const size_t *iter = first; iter != last; ++iter ) {
4847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        if ( NULL == (p = fallback_malloc ( *iter )))
4947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow            break;
5047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        ptrs.push_back ( p );
5147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        }
5247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
5347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    return ptrs;
5447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
5547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
5647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowvoid *pop ( container &c, bool from_end ) {
5747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    void *ptr;
5847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    if ( from_end ) {
5947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        ptr = c.back ();
6047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        c.pop_back ();
6147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        }
6247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    else {
6347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        ptr = c.front ();
6447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        c.pop_front ();
6547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        }
6647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    return ptr;
6747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
6847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
6947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowvoid exhaustion_test1 () {
7047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
7147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
7247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    init_heap ();
7347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Constant exhaustion tests" << std::endl;
7447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
7547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in allocation order
7647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32 );
7747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
7847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
7947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
8047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
8147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
8247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
8347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
8447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in reverse order
8547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32 );
8647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
8747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
8847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
8947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
9047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
9147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
9247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Alternate deletions
9347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32 );
9447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
9547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    while ( ptrs.size () > 0 )
9647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
9747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
9847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
9947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
10047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowvoid exhaustion_test2 () {
10147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
10247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    init_heap ();
10347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
10447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Growing exhaustion tests" << std::endl;
10547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
10647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in allocation order
10747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32, 1.5 );
10847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... }  byte chunks" << std::endl;
10947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
11047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
11147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
11247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
11347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
11447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
11547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in reverse order
11647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
11747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32, 1.5 );
11847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... }  byte chunks" << std::endl;
11947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
12047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
12147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
12247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
12347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
12447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Alternate deletions
12547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( 32, 1.5 );
12647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... }  byte chunks" << std::endl;
12747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    while ( ptrs.size () > 0 )
12847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
12947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
13047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
13147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
13247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
13347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowvoid exhaustion_test3 () {
13447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    const size_t allocs [] = { 124, 60, 252, 60, 4 };
13547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    container ptrs;
13647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    init_heap ();
13747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
13847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Complete exhaustion tests" << std::endl;
13947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
14047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in allocation order
14147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
14247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
14347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
14447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
14547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
14647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
14747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
14847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
14947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Delete in reverse order
15047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
15147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
15247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
15347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
15447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( *iter );
15547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
15647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "----" << std::endl;
15747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
15847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow//  Alternate deletions
15947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
16047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
16147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    while ( ptrs.size () > 0 )
16247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
16347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
16447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
16547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
16647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
16747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
16847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowint main ( int argc, char *argv [] ) {
16947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
17047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
17147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    char *p = (char *) fallback_malloc ( 1024 );    // too big!
17247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "fallback_malloc ( 1024 ) --> " << (unsigned long ) p << std::endl;
17347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
17447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
17547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    p = (char *) fallback_malloc ( 32 );
17647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << "fallback_malloc ( 32 ) --> " << (unsigned long) (p - heap) << std::endl;
17747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    if ( !is_fallback_ptr ( p ))
17847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow        std::cout << "### p is not a fallback pointer!!" << std::endl;
17947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
18047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
18147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    fallback_free ( p );
18247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    print_free_list ();
18347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow
18447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    std::cout << std::endl;
18547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    exhaustion_test1 (); std::cout << std::endl;
18647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    exhaustion_test2 (); std::cout << std::endl;
18747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    exhaustion_test3 (); std::cout << std::endl;
18847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    return 0;
18947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow    }
190