1e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*
2e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
3e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1996,1997
4e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Silicon Graphics Computer Systems, Inc.
5e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
6e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1997
7e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Moscow Center for SPARC Technology
8e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
9e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1999
10e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Boris Fomitchev
11e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
12e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * This material is provided "as is", with absolutely no warranty expressed
13e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * or implied. Any use is at your own risk.
14e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
15e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to use or copy this software for any purpose is hereby granted
16e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * without fee, provided the above notices are retained on all copies.
17e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to modify the code and to distribute modified code is granted,
18e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * provided the above notices are retained, and a notice that the code was
19e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * modified is included with the above copyright notice.
20e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
21e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */
22e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
23e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "stlport_prefix.h"
24e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
25e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <memory>
26e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
27e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (__GNUC__) && (defined (__CYGWIN__) || defined (__MINGW32__))
28e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <malloc.h>
29e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
30e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
31e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
32e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <pthread_alloc>
33e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <cerrno>
34e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
35e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
36e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <stl/_threads.h>
37e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
38e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "lock_free_slist.h"
39e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
40e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (__WATCOMC__)
41e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  pragma warning 13 9
42e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  pragma warning 367 9
43e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  pragma warning 368 9
44e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
45e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
46e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_SGI_THREADS)
47e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // We test whether threads are in use before locking.
48e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Perhaps this should be moved into stl_threads.h, but that
49e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // probably makes it harder to avoid the procedure call when
50e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // it isn't needed.
51e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottextern "C" {
52e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  extern int __us_rsthread_malloc;
53e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
54e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
55e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
56e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Specialised debug form of new operator which does not provide "false"
57e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// memory leaks when run with debug CRT libraries.
58e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_MSVC) && (_STLP_MSVC >= 1020 && defined (_STLP_DEBUG_ALLOC)) && !defined (_STLP_WCE)
59e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  include <crtdbg.h>
60e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline char* __stlp_new_chunk(size_t __bytes) {
61e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  void *__chunk = _STLP_CHECK_NULL_ALLOC(::operator new(__bytes, __FILE__, __LINE__));
62e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __STATIC_CAST(char*, __chunk);
63e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
64e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void __stlp_delete_chunck(void* __p) { ::operator delete(__p, __FILE__, __LINE__); }
65e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
66e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  ifdef _STLP_NODE_ALLOC_USE_MALLOC
67e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    include <cstdlib>
68e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline char* __stlp_new_chunk(size_t __bytes) {
69e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // do not use _STLP_CHECK_NULL_ALLOC, this macro is dedicated to new operator.
70e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  void *__chunk = _STLP_VENDOR_CSTD::malloc(__bytes);
71e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__chunk == 0) {
72e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _STLP_THROW_BAD_ALLOC;
73e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
74e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __STATIC_CAST(char*, __chunk);
75e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
76e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void __stlp_delete_chunck(void* __p) { _STLP_VENDOR_CSTD::free(__p); }
77e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
78e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline char* __stlp_new_chunk(size_t __bytes)
79e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return __STATIC_CAST(char*, _STLP_STD::__stl_new(__bytes)); }
80e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline void __stlp_delete_chunck(void* __p) { _STLP_STD::__stl_delete(__p); }
81e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
82e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
83e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
84e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* This is an additional atomic operations to the ones already defined in
85e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * stl/_threads.h, platform should try to support it to improve performance.
86e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * __add_atomic_t _STLP_ATOMIC_ADD(volatile __add_atomic_t* __target, __add_atomic_t __val) :
87e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * does *__target = *__target + __val and returns the old *__target value */
88e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttypedef long __add_atomic_t;
89e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttypedef unsigned long __uadd_atomic_t;
90e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
91e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (__GNUC__) && defined (__i386__)
92e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottinline long _STLP_atomic_add_gcc_x86(long volatile* p, long addend) {
93e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  long result;
94e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __asm__ __volatile__
95e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    ("lock; xaddl %1, %0;"
96e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    :"=m" (*p), "=r" (result)
97e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    :"m"  (*p), "1"  (addend)
98e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    :"cc");
99e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott return result + addend;
100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  define _STLP_ATOMIC_ADD(__dst, __val)  _STLP_atomic_add_gcc_x86(__dst, __val)
102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#elif defined (_STLP_WIN32THREADS)
103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// The Win32 API function InterlockedExchangeAdd is not available on Windows 95.
104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if !defined (_STLP_WIN95_LIKE)
105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    if defined (_STLP_NEW_PLATFORM_SDK)
106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__dst, __val)
107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    else
108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__CONST_CAST(__add_atomic_t*, __dst), __val)
109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    endif
110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (__OS400__)
114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// dums 02/05/2007: is it really necessary ?
115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottenum { _ALIGN = 16, _ALIGN_SHIFT = 4 };
116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottenum { _ALIGN = 2 * sizeof(void*), _ALIGN_SHIFT = 2 + sizeof(void*) / 4 };
118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#define _S_FREELIST_INDEX(__bytes) ((__bytes - size_t(1)) >> (int)_ALIGN_SHIFT)
121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
122e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_BEGIN_NAMESPACE
123e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
124e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// malloc_alloc out-of-memory handling
125e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic __oom_handler_type __oom_handler = __STATIC_CAST(__oom_handler_type, 0);
126e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
127e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef _STLP_THREADS
128e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_mutex __oom_handler_lock;
129e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
130e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
131e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid* _STLP_CALL __malloc_alloc::allocate(size_t __n)
132e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{
133e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  void *__result = malloc(__n);
134e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if ( 0 == __result ) {
135e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __oom_handler_type __my_malloc_handler;
136e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
137e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    for (;;) {
138e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      {
139e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef _STLP_THREADS
140e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _STLP_auto_lock _l( __oom_handler_lock );
141e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
142e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        __my_malloc_handler = __oom_handler;
143e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
144e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if ( 0 == __my_malloc_handler) {
145e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _STLP_THROW_BAD_ALLOC;
146e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
147e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      (*__my_malloc_handler)();
148e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result = malloc(__n);
149e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if ( __result )
150e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        return __result;
151e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
152e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
153e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
154e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
155e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
156e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__oom_handler_type _STLP_CALL __malloc_alloc::set_malloc_handler(__oom_handler_type __f)
157e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{
158e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#ifdef _STLP_THREADS
159e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_auto_lock _l( __oom_handler_lock );
160e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
161e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __oom_handler_type __old = __oom_handler;
162e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __oom_handler = __f;
163e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __old;
164e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
165e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
166e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// *******************************************************
167e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Default node allocator.
168e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// With a reasonable compiler, this should be roughly as fast as the
169e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// original STL class-specific allocators, but with less fragmentation.
170e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//
171e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Important implementation properties:
172e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// 1. If the client request an object of size > _MAX_BYTES, the resulting
173e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//    object will be obtained directly from malloc.
174e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// 2. In all other cases, we allocate an object of size exactly
175e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//    _S_round_up(requested_size).  Thus the client has enough size
176e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//    information that we can return the object to the proper free list
177e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//    without permanently losing part of the object.
178e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//
179e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
180e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#define _STLP_NFREELISTS 16
181e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
182e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_LEAKS_PEDANTIC) && defined (_STLP_USE_DYNAMIC_LIB)
183e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*
184e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * We can only do cleanup of the node allocator memory pool if we are
185e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * sure that the STLport library is used as a shared one as it guaranties
186e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * the unicity of the node allocator instance. Without that guaranty node
187e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * allocator instances might exchange memory blocks making the implementation
188e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * of a cleaning process much more complicated.
189e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */
190e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  define _STLP_DO_CLEAN_NODE_ALLOC
191e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
192e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
193e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* When STLport is used without multi threaded safety we use the node allocator
194e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * implementation with locks as locks becomes no-op. The lock free implementation
195e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * always use system specific atomic operations which are slower than 'normal'
196e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * ones.
197e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */
198e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_THREADS) && \
199e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    defined (_STLP_HAS_ATOMIC_FREELIST) && defined (_STLP_ATOMIC_ADD)
200e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*
201e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * We have an implementation of the atomic freelist (_STLP_atomic_freelist)
202e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * for this architecture and compiler.  That means we can use the non-blocking
203e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * implementation of the node-allocation engine.*/
204e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  define _STLP_USE_LOCK_FREE_IMPLEMENTATION
205e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
206e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
207e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
208e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_THREADS)
209e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
210e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottclass _Node_Alloc_Lock {
211e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _STLP_STATIC_MUTEX& _S_Mutex() {
212e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    static _STLP_STATIC_MUTEX mutex _STLP_MUTEX_INITIALIZER;
213e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return mutex;
214e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
215e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
216e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Node_Alloc_Lock() {
217e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    if defined (_STLP_SGI_THREADS)
218e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__us_rsthread_malloc)
219e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    endif
220e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_Mutex()._M_acquire_lock();
221e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
222e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
223e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  ~_Node_Alloc_Lock() {
224e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    if defined (_STLP_SGI_THREADS)
225e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__us_rsthread_malloc)
226e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    endif
227e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_Mutex()._M_release_lock();
228e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
229e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
230e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
231e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
232e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
233e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottclass _Node_Alloc_Lock {
234e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
235e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Node_Alloc_Lock() { }
236e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  ~_Node_Alloc_Lock() { }
237e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
238e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
239e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
240e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
241e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct _Node_alloc_obj {
242e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Node_alloc_obj * _M_next;
243e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
244e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
245e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
246e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottclass __node_alloc_impl {
247e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static inline size_t _STLP_CALL _S_round_up(size_t __bytes)
248e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { return (((__bytes) + (size_t)_ALIGN-1) & ~((size_t)_ALIGN - 1)); }
249e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
250e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
251e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _STLP_atomic_freelist::item   _Obj;
252e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _STLP_atomic_freelist         _Freelist;
253e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _STLP_atomic_freelist         _ChunkList;
254e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
255e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Header of blocks of memory that have been allocated as part of
256e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // a larger chunk but have not yet been chopped up into nodes.
257e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  struct _FreeBlockHeader : public _STLP_atomic_freelist::item {
258e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    char* _M_end;     // pointer to end of free memory
259e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  };
260e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
261e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Node_alloc_obj       _Obj;
262e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Obj* _STLP_VOLATILE  _Freelist;
263e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Obj*                 _ChunkList;
264e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
265e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
266e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottprivate:
267e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Returns an object of size __n, and optionally adds to size __n free list.
268e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _Obj* _S_refill(size_t __n);
269e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Allocates a chunk for nobjs of size __p_size.  nobjs may be reduced
270e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // if it is inconvenient to allocate the requested number.
271e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char* _S_chunk_alloc(size_t __p_size, int& __nobjs);
272e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Chunk allocation state.
273e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _Freelist _S_free_list[_STLP_NFREELISTS];
274e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Amount of total allocated memory
275e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
276e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _STLP_VOLATILE __add_atomic_t _S_heap_size;
277e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
278e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static size_t _S_heap_size;
279e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
280e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
281e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
282e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // List of blocks of free memory
283e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _STLP_atomic_freelist  _S_free_mem_blocks;
284e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
285e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Start of the current free memory buffer
286e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char* _S_start_free;
287e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // End of the current free memory buffer
288e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char* _S_end_free;
289e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
290e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
291e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
292e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
293e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Methods to report alloc/dealloc calls to the counter system.
294e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
295e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _STLP_VOLATILE __stl_atomic_t _AllocCounter;
296e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
297e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef __stl_atomic_t _AllocCounter;
298e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
299e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _AllocCounter& _STLP_CALL _S_alloc_counter();
300e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void _S_alloc_call();
301e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void _S_dealloc_call();
302e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
303e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottprivate:
304e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Free all the allocated chuncks of memory
305e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void _S_chunk_dealloc();
306e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Beginning of the linked list of allocated chunks of memory
307e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _ChunkList _S_chunks;
308e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif /* _STLP_DO_CLEAN_NODE_ALLOC */
309e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
310e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
311e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* __n must be > 0      */
312e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void* _M_allocate(size_t& __n);
313e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* __p may not be 0 */
314e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void _M_deallocate(void *__p, size_t __n);
315e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
316e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
317e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
318e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid* __node_alloc_impl::_M_allocate(size_t& __n) {
319e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __n = _S_round_up(__n);
320e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
321e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj *__r;
322e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
323e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Acquire the lock here with a constructor call.
324e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // This ensures that it is released in exit or during stack
325e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // unwinding.
326e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Node_Alloc_Lock __lock_instance;
327e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
328e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if ( (__r  = *__my_free_list) != 0 ) {
329e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    *__my_free_list = __r->_M_next;
330e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  } else {
331e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __r = _S_refill(__n);
332e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
333e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
334e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_alloc_call();
335e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
336e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // lock is released here
337e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __r;
338e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
339e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
340e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
341e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
342e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj * __pobj = __STATIC_CAST(_Obj*, __p);
343e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
344e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // acquire lock
345e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Node_Alloc_Lock __lock_instance;
346e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __pobj->_M_next = *__my_free_list;
347e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __pobj;
348e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
349e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
350e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_dealloc_call();
351e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
352e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // lock is released here
353e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
354e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
355e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
356e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    define _STLP_OFFSET sizeof(_Obj)
357e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
358e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    define _STLP_OFFSET 0
359e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
360e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
361e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We allocate memory in large chunks in order to avoid fragmenting     */
362e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* the malloc heap too much.                                            */
363e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that size is properly aligned.                             */
364e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We hold the allocation lock.                                         */
365e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
366e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char* __result;
367e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __total_bytes = _p_size * __nobjs;
368e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __bytes_left = _S_end_free - _S_start_free;
369e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
370e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__bytes_left > 0) {
371e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__bytes_left >= __total_bytes) {
372e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result = _S_start_free;
373e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_start_free += __total_bytes;
374e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return __result;
375e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
376e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
377e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__bytes_left >= _p_size) {
378e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __nobjs = (int)(__bytes_left / _p_size);
379e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __total_bytes = _p_size * __nobjs;
380e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result = _S_start_free;
381e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_start_free += __total_bytes;
382e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return __result;
383e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
384e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
385e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // Try to make use of the left-over piece.
386e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__bytes_left);
387e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = *__my_free_list;
388e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    *__my_free_list = __REINTERPRET_CAST(_Obj*, _S_start_free);
389e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_start_free = _S_end_free = 0;
390e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
391e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
392e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size) + _STLP_OFFSET;
393e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
394e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_TRY {
395e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_start_free = __stlp_new_chunk(__bytes_to_get);
396e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
397e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_EXCEPTIONS)
398e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  catch (const _STLP_STD::bad_alloc&) {
399e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Obj* _STLP_VOLATILE* __my_free_list;
400e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Obj* __p;
401e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // Try to do with what we have.  That can't hurt.
402e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // We do not try smaller requests, since that tends
403e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // to result in disaster on multi-process machines.
404e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
405e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __my_free_list = _S_free_list + _S_FREELIST_INDEX(__i);
406e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __p = *__my_free_list;
407e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if (0 != __p) {
408e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        *__my_free_list = __p -> _M_next;
409e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _S_start_free = __REINTERPRET_CAST(char*, __p);
410e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _S_end_free = _S_start_free + __i;
411e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        return _S_chunk_alloc(_p_size, __nobjs);
412e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // Any leftover piece will eventually make it to the
413e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // right free list.
414e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
415e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
416e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __bytes_to_get = __total_bytes + _STLP_OFFSET;
417e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_start_free = __stlp_new_chunk(__bytes_to_get);
418e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
419e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
420e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
421e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_heap_size += __bytes_to_get >> 4;
422e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
423e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = _S_chunks;
424e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_chunks = __REINTERPRET_CAST(_Obj*, _S_start_free);
425e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
426e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_end_free = _S_start_free + __bytes_to_get;
427e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_start_free += _STLP_OFFSET;
428e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return _S_chunk_alloc(_p_size, __nobjs);
429e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
430e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
431e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Returns an object of size __n, and optionally adds to size __n free list.*/
432e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that __n is properly aligned.                                  */
433e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We hold the allocation lock.                                             */
434e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Node_alloc_obj* __node_alloc_impl::_S_refill(size_t __n) {
435e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  int __nobjs = 20;
436e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char* __chunk = _S_chunk_alloc(__n, __nobjs);
437e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
438e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (1 == __nobjs) return __REINTERPRET_CAST(_Obj*, __chunk);
439e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
440e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
441e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __result;
442e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __current_obj;
443e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __next_obj;
444e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
445e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* Build free list in chunk */
446e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = __REINTERPRET_CAST(_Obj*, __chunk);
447e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __next_obj = __REINTERPRET_CAST(_Obj*, __chunk + __n);
448e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  for (--__nobjs; --__nobjs; ) {
449e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __current_obj = __next_obj;
450e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __next_obj = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __next_obj) + __n);
451e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __current_obj->_M_next = __next_obj;
452e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
453e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __next_obj->_M_next = 0;
454e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
455e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
456e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
457e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
458e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_alloc_call()
459e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ ++_S_alloc_counter(); }
460e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
461e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_dealloc_call() {
462e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __stl_atomic_t &counter = _S_alloc_counter();
463e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (--counter == 0)
464e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { _S_chunk_dealloc(); }
465e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
466e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
467e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We deallocate all the memory chunks      */
468e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_chunk_dealloc() {
469e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj *__pcur = _S_chunks, *__pnext;
470e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  while (__pcur != 0) {
471e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __pnext = __pcur->_M_next;
472e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __stlp_delete_chunck(__pcur);
473e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __pcur = __pnext;
474e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
475e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_chunks = 0;
476e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_start_free = _S_end_free = 0;
477e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_heap_size = 0;
478e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  memset(__REINTERPRET_CAST(char*, __CONST_CAST(_Obj**, &_S_free_list[0])), 0, _STLP_NFREELISTS * sizeof(_Obj*));
479e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
480e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
481e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
482e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
483e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
484e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid* __node_alloc_impl::_M_allocate(size_t& __n) {
485e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __n = _S_round_up(__n);
486e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __r = _S_free_list[_S_FREELIST_INDEX(__n)].pop();
487e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__r  == 0)
488e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { __r = _S_refill(__n); }
489e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
490e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
491e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_alloc_call();
492e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
493e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __r;
494e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
495e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
496e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
497e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_free_list[_S_FREELIST_INDEX(__n)].push(__STATIC_CAST(_Obj*, __p));
498e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
499e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
500e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_dealloc_call();
501e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
502e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
503e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
504e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Returns an object of size __n, and optionally adds additional ones to    */
505e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* freelist of objects of size __n.                                         */
506e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that __n is properly aligned.                                  */
507e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__node_alloc_impl::_Obj* __node_alloc_impl::_S_refill(size_t __n) {
508e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  int __nobjs = 20;
509e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char* __chunk = _S_chunk_alloc(__n, __nobjs);
510e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
511e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__nobjs <= 1)
512e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __REINTERPRET_CAST(_Obj*, __chunk);
513e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
514e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Push all new nodes (minus first one) onto freelist
515e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __result   = __REINTERPRET_CAST(_Obj*, __chunk);
516e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __cur_item = __result;
517e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Freelist* __my_freelist = _S_free_list + _S_FREELIST_INDEX(__n);
518e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  for (--__nobjs; __nobjs != 0; --__nobjs) {
519e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __cur_item  = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __cur_item) + __n);
520e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __my_freelist->push(__cur_item);
521e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
522e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
523e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
524e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
525e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
526e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    define _STLP_OFFSET _ALIGN
527e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
528e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    define _STLP_OFFSET 0
529e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
530e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
531e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We allocate memory in large chunks in order to avoid fragmenting     */
532e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* the malloc heap too much.                                            */
533e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that size is properly aligned.                             */
534e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
535e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
536e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //We are going to add a small memory block to keep all the allocated blocks
537e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //address, we need to do so respecting the memory alignment. The following
538e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //static assert checks that the reserved block is big enough to store a pointer.
539e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_STATIC_ASSERT(sizeof(_Obj) <= _ALIGN)
540e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
541e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char*  __result       = 0;
542e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __add_atomic_t __total_bytes  = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
543e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
544e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _FreeBlockHeader* __block = __STATIC_CAST(_FreeBlockHeader*, _S_free_mem_blocks.pop());
545e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__block != 0) {
546e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // We checked a block out and can now mess with it with impugnity.
547e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // We'll put the remainder back into the list if we're done with it below.
548e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    char*  __buf_start  = __REINTERPRET_CAST(char*, __block);
549e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __add_atomic_t __bytes_left = __block->_M_end - __buf_start;
550e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
551e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if ((__bytes_left < __total_bytes) && (__bytes_left >= __STATIC_CAST(__add_atomic_t, _p_size))) {
552e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // There's enough left for at least one object, but not as much as we wanted
553e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result      = __buf_start;
554e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __nobjs       = (int)(__bytes_left/_p_size);
555e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __total_bytes = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
556e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __bytes_left -= __total_bytes;
557e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __buf_start  += __total_bytes;
558e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
559e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    else if (__bytes_left >= __total_bytes) {
560e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // The block has enough left to satisfy all that was asked for
561e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result      = __buf_start;
562e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __bytes_left -= __total_bytes;
563e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __buf_start  += __total_bytes;
564e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
565e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
566e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__bytes_left != 0) {
567e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // There is still some memory left over in block after we satisfied our request.
568e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if ((__result != 0) && (__bytes_left >= (__add_atomic_t)sizeof(_FreeBlockHeader))) {
569e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // We were able to allocate at least one object and there is still enough
570e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // left to put remainder back into list.
571e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _FreeBlockHeader* __newblock = __REINTERPRET_CAST(_FreeBlockHeader*, __buf_start);
572e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        __newblock->_M_end  = __block->_M_end;
573e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _S_free_mem_blocks.push(__newblock);
574e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
575e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      else {
576e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // We were not able to allocate enough for at least one object.
577e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // Shove into freelist of nearest (rounded-down!) size.
578e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        size_t __rounded_down = _S_round_up(__bytes_left + 1) - (size_t)_ALIGN;
579e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        if (__rounded_down > 0)
580e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push((_Obj*)__buf_start);
581e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
582e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
583e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__result != 0)
584e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return __result;
585e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
586e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
587e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // We couldn't satisfy it from the list of free blocks, get new memory.
588e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __add_atomic_t __bytes_to_get = 2 * __total_bytes +
589e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                                  __STATIC_CAST(__add_atomic_t,
590e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                                                _S_round_up(__STATIC_CAST(__uadd_atomic_t, _STLP_ATOMIC_ADD(&_S_heap_size, 0)))) +
591e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                                  _STLP_OFFSET;
592e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_TRY {
593e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __result = __stlp_new_chunk(__bytes_to_get);
594e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
595e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_EXCEPTIONS)
596e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  catch (const bad_alloc&) {
597e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // Allocation failed; try to canibalize from freelist of a larger object size.
598e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
599e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _Obj* __p  = _S_free_list[_S_FREELIST_INDEX(__i)].pop();
600e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if (0 != __p) {
601e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        if (__i < sizeof(_FreeBlockHeader)) {
602e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          // Not enough to put into list of free blocks, divvy it up here.
603e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          // Use as much as possible for this request and shove remainder into freelist.
604e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          __nobjs = (int)(__i/_p_size);
605e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          __total_bytes = __nobjs * __STATIC_CAST(__add_atomic_t, _p_size);
606e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          size_t __bytes_left = __i - __total_bytes;
607e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          size_t __rounded_down = _S_round_up(__bytes_left+1) - (size_t)_ALIGN;
608e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          if (__rounded_down > 0) {
609e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott            _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push(__REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __p) + __total_bytes));
610e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          }
611e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          return __REINTERPRET_CAST(char*, __p);
612e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        }
613e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        else {
614e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          // Add node to list of available blocks and recursively allocate from it.
615e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          _FreeBlockHeader* __newblock = (_FreeBlockHeader*)__p;
616e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          __newblock->_M_end  = __REINTERPRET_CAST(char*, __p) + __i;
617e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          _S_free_mem_blocks.push(__newblock);
618e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          return _S_chunk_alloc(_p_size, __nobjs);
619e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        }
620e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
621e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
622e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
623e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // We were not able to find something in a freelist, try to allocate a smaller amount.
624e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __bytes_to_get  = __total_bytes + _STLP_OFFSET;
625e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __result = __stlp_new_chunk(__bytes_to_get);
626e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
627e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // This should either throw an exception or remedy the situation.
628e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // Thus we assume it succeeded.
629e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
630e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
631e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Alignment check
632e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_VERBOSE_ASSERT(((__REINTERPRET_CAST(size_t, __result) & __STATIC_CAST(size_t, _ALIGN - 1)) == 0),
633e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                       _StlMsg_DBA_DELETED_TWICE)
634e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_ATOMIC_ADD(&_S_heap_size, __bytes_to_get >> 4);
635e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
636e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
637e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // We have to track the allocated memory chunks for release on exit.
638e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_chunks.push(__REINTERPRET_CAST(_Obj*, __result));
639e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result       += _ALIGN;
640e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __bytes_to_get -= _ALIGN;
641e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
642e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
643e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__bytes_to_get > __total_bytes) {
644e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    // Push excess memory allocated in this chunk into list of free memory blocks
645e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _FreeBlockHeader* __freeblock = __REINTERPRET_CAST(_FreeBlockHeader*, __result + __total_bytes);
646e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __freeblock->_M_end  = __result + __bytes_to_get;
647e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_free_mem_blocks.push(__freeblock);
648e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
649e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
650e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
651e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
652e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
653e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_alloc_call()
654e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ _STLP_ATOMIC_INCREMENT(&_S_alloc_counter()); }
655e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
656e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_dealloc_call() {
657e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_VOLATILE __stl_atomic_t *pcounter = &_S_alloc_counter();
658e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (_STLP_ATOMIC_DECREMENT(pcounter) == 0)
659e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_chunk_dealloc();
660e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
661e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
662e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We deallocate all the memory chunks      */
663e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid __node_alloc_impl::_S_chunk_dealloc() {
664e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Note: The _Node_alloc_helper class ensures that this function
665e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // will only be called when the (shared) library is unloaded or the
666e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // process is shutdown.  It's thus not possible that another thread
667e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // is currently trying to allocate a node (we're not thread-safe here).
668e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  //
669e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
670e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Clear the free blocks and all freelistst.  This makes sure that if
671e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // for some reason more memory is allocated again during shutdown
672e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // (it'd also be really nasty to leave references to deallocated memory).
673e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_free_mem_blocks.clear();
674e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_heap_size      = 0;
675e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
676e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  for (size_t __i = 0; __i < _STLP_NFREELISTS; ++__i) {
677e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_free_list[__i].clear();
678e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
679e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
680e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Detach list of chunks and free them all
681e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Obj* __chunk = _S_chunks.clear();
682e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  while (__chunk != 0) {
683e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Obj* __next = __chunk->_M_next;
684e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __stlp_delete_chunck(__chunk);
685e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __chunk  = __next;
686e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
687e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
688e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
689e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
690e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
691e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
692e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
693e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct __node_alloc_cleaner {
694e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  ~__node_alloc_cleaner()
695e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { __node_alloc_impl::_S_dealloc_call(); }
696e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
697e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
698e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
699e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_VOLATILE __stl_atomic_t& _STLP_CALL
700e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
701e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__stl_atomic_t& _STLP_CALL
702e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
703e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__node_alloc_impl::_S_alloc_counter() {
704e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _AllocCounter _S_counter = 1;
705e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static __node_alloc_cleaner _S_node_alloc_cleaner;
706e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return _S_counter;
707e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
708e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
709e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
710e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
711e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Node_alloc_obj * _STLP_VOLATILE
712e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__node_alloc_impl::_S_free_list[_STLP_NFREELISTS]
713e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
714e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// The 16 zeros are necessary to make version 4.1 of the SunPro
715e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// compiler happy.  Otherwise it appears to allocate too little
716e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// space for the array.
717e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
718e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_atomic_freelist __node_alloc_impl::_S_free_list[_STLP_NFREELISTS];
719e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_atomic_freelist __node_alloc_impl::_S_free_mem_blocks;
720e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
721e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
722e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
723e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar *__node_alloc_impl::_S_start_free = 0;
724e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar *__node_alloc_impl::_S_end_free = 0;
725e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
726e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
727e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
728e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_VOLATILE __add_atomic_t
729e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
730e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottsize_t
731e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
732e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott__node_alloc_impl::_S_heap_size = 0;
733e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
734e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
735e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
736e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_atomic_freelist __node_alloc_impl::_S_chunks;
737e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
738e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Node_alloc_obj* __node_alloc_impl::_S_chunks  = 0;
739e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
740e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
741e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
742e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid * _STLP_CALL __node_alloc::_M_allocate(size_t& __n)
743e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return __node_alloc_impl::_M_allocate(__n); }
744e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
745e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _STLP_CALL __node_alloc::_M_deallocate(void *__p, size_t __n)
746e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ __node_alloc_impl::_M_deallocate(__p, __n); }
747e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
748e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
749e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
750e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  define _STLP_DATA_ALIGNMENT 8
751e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
752e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_MOVE_TO_PRIV_NAMESPACE
753e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
754e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// *******************************************************
755e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// __perthread_alloc implementation
756e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottunion _Pthread_alloc_obj {
757e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  union _Pthread_alloc_obj * __free_list_link;
758e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char __client_data[_STLP_DATA_ALIGNMENT];    /* The client sees this.    */
759e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
760e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
761e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Pthread allocators don't appear to the client to have meaningful
762e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// instances.  We do in fact need to associate some state with each
763e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// thread.  That state is represented by _Pthread_alloc_per_thread_state.
764e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
765e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstruct _Pthread_alloc_per_thread_state {
766e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
767e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  enum { _S_NFREELISTS = _MAX_BYTES / _STLP_DATA_ALIGNMENT };
768e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
769e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Free list link for list of available per thread structures.
770e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // When one of these becomes available for reuse due to thread
771e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // termination, any objects in its free list remain associated
772e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // with it.  The whole structure may then be used by a newly
773e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // created thread.
774e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Pthread_alloc_per_thread_state() : __next(0)
775e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { memset((void *)__CONST_CAST(_Pthread_alloc_obj**, __free_list), 0, (size_t)_S_NFREELISTS * sizeof(__obj *)); }
776e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Returns an object of size __n, and possibly adds to size n free list.
777e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  void *_M_refill(size_t __n);
778e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
779e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS];
780e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Pthread_alloc_per_thread_state *__next;
781e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // this data member is only to be used by per_thread_allocator, which returns memory to the originating thread.
782e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_mutex _M_lock;
783e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
784e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
785e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Pthread-specific allocator.
786e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottclass _Pthread_alloc_impl {
787e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic: // but only for internal use:
788e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_per_thread_state __state_type;
789e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef char value_type;
790e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
791e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Allocates a chunk for nobjs of size size.  nobjs may be reduced
792e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // if it is inconvenient to allocate the requested number.
793e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char *_S_chunk_alloc(size_t __size, size_t &__nobjs, __state_type*);
794e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
795e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  enum {_S_ALIGN = _STLP_DATA_ALIGNMENT};
796e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
797e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static size_t _S_round_up(size_t __bytes)
798e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { return (((__bytes) + (int)_S_ALIGN - 1) & ~((int)_S_ALIGN - 1)); }
799e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static size_t _S_freelist_index(size_t __bytes)
800e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  { return (((__bytes) + (int)_S_ALIGN - 1) / (int)_S_ALIGN - 1); }
801e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
802e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottprivate:
803e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Chunk allocation state. And other shared state.
804e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Protected by _S_chunk_allocator_lock.
805e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static _STLP_STATIC_MUTEX _S_chunk_allocator_lock;
806e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char *_S_start_free;
807e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static char *_S_end_free;
808e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static size_t _S_heap_size;
809e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static __state_type *_S_free_per_thread_states;
810e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static pthread_key_t _S_key;
811e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static bool _S_key_initialized;
812e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Pthread key under which per thread state is stored.
813e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Allocator instances that are currently unclaimed by any thread.
814e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void _S_destructor(void *instance);
815e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Function to be called on thread exit to reclaim per thread
816e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // state.
817e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static __state_type *_S_new_per_thread_state();
818e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
819e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // Return a recycled or new per thread state.
820e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static __state_type *_S_get_per_thread_state();
821e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottprivate:
822e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // ensure that the current thread has an associated
823e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        // per thread state.
824e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  class _M_lock;
825e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  friend class _M_lock;
826e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  class _M_lock {
827e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  public:
828e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _M_lock () { _S_chunk_allocator_lock._M_acquire_lock(); }
829e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    ~_M_lock () { _S_chunk_allocator_lock._M_release_lock(); }
830e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  };
831e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
832e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpublic:
833e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
834e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* n must be > 0      */
835e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void * allocate(size_t& __n);
836e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
837e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* p may not be 0 */
838e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void deallocate(void *__p, size_t __n);
839e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
840e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // boris : versions for per_thread_allocator
841e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* n must be > 0      */
842e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void * allocate(size_t& __n, __state_type* __a);
843e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
844e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* p may not be 0 */
845e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void deallocate(void *__p, size_t __n, __state_type* __a);
846e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
847e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static void * reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
848e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
849e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
850e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* Returns an object of size n, and optionally adds to size n free list.*/
851e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that n is properly aligned.                                */
852e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We hold the allocation lock.                                         */
853e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid *_Pthread_alloc_per_thread_state::_M_refill(size_t __n) {
854e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
855e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __nobjs = 128;
856e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  char * __chunk = _Pthread_alloc_impl::_S_chunk_alloc(__n, __nobjs, this);
857e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * volatile * __my_free_list;
858e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * __result;
859e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * __current_obj, * __next_obj;
860e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __i;
861e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
862e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (1 == __nobjs)  {
863e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __chunk;
864e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
865e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
866e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __my_free_list = __free_list + _Pthread_alloc_impl::_S_freelist_index(__n);
867e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
868e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* Build free list in chunk */
869e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = (__obj *)__chunk;
870e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __next_obj = (__obj *)(__chunk + __n);
871e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  for (__i = 1; ; ++__i) {
872e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __current_obj = __next_obj;
873e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __next_obj = (__obj *)((char *)__next_obj + __n);
874e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__nobjs - 1 == __i) {
875e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __current_obj -> __free_list_link = 0;
876e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      break;
877e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    } else {
878e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __current_obj -> __free_list_link = __next_obj;
879e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
880e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
881e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
882e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
883e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
884e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _Pthread_alloc_impl::_S_destructor(void *__instance) {
885e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _M_lock __lock_instance;  // Need to acquire lock here.
886e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Pthread_alloc_per_thread_state* __s = (_Pthread_alloc_per_thread_state*)__instance;
887e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __s -> __next = _S_free_per_thread_states;
888e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _S_free_per_thread_states = __s;
889e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
890e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
891e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_new_per_thread_state() {
892e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /* lock already held here.  */
893e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (0 != _S_free_per_thread_states) {
894e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Pthread_alloc_per_thread_state *__result = _S_free_per_thread_states;
895e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_free_per_thread_states = _S_free_per_thread_states -> __next;
896e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __result;
897e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
898e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  else {
899e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return new _Pthread_alloc_per_thread_state;
900e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
901e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
902e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
903e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_get_per_thread_state() {
904e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  int __ret_code;
905e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __state_type* __result;
906e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
907e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (_S_key_initialized && (__result = (__state_type*) pthread_getspecific(_S_key)))
908e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __result;
909e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
910e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  /*REFERENCED*/
911e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _M_lock __lock_instance;  // Need to acquire lock here.
912e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (!_S_key_initialized) {
913e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (pthread_key_create(&_S_key, _S_destructor)) {
914e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _STLP_THROW_BAD_ALLOC;  // failed
915e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
916e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _S_key_initialized = true;
917e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
918e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
919e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = _S_new_per_thread_state();
920e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __ret_code = pthread_setspecific(_S_key, __result);
921e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__ret_code) {
922e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__ret_code == ENOMEM) {
923e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _STLP_THROW_BAD_ALLOC;
924e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    } else {
925e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // EINVAL
926e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _STLP_ABORT();
927e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
928e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
929e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
930e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
931e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
932e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We allocate memory in large chunks in order to avoid fragmenting     */
933e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* the malloc heap too much.                                            */
934e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* We assume that size is properly aligned.                             */
935e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar *_Pthread_alloc_impl::_S_chunk_alloc(size_t __p_size, size_t &__nobjs, _Pthread_alloc_per_thread_state *__a) {
936e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
937e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  {
938e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    char * __result;
939e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    size_t __total_bytes;
940e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    size_t __bytes_left;
941e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    /*REFERENCED*/
942e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _M_lock __lock_instance;         // Acquire lock for this routine
943e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
944e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __total_bytes = __p_size * __nobjs;
945e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __bytes_left = _S_end_free - _S_start_free;
946e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    if (__bytes_left >= __total_bytes) {
947e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result = _S_start_free;
948e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_start_free += __total_bytes;
949e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return __result;
950e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    } else if (__bytes_left >= __p_size) {
951e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __nobjs = __bytes_left/__p_size;
952e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __total_bytes = __p_size * __nobjs;
953e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __result = _S_start_free;
954e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_start_free += __total_bytes;
955e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return __result;
956e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    } else {
957e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size);
958e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // Try to make use of the left-over piece.
959e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      if (__bytes_left > 0) {
960e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        __obj * volatile * __my_free_list = __a->__free_list + _S_freelist_index(__bytes_left);
961e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        ((__obj *)_S_start_free) -> __free_list_link = *__my_free_list;
962e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        *__my_free_list = (__obj *)_S_start_free;
963e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
964e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  ifdef _SGI_SOURCE
965e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // Try to get memory that's aligned on something like a
966e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // cache line boundary, so as to avoid parceling out
967e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // parts of the same line to different threads and thus
968e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      // possibly different processors.
969e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      {
970e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        const int __cache_line_size = 128;  // probable upper bound
971e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        __bytes_to_get &= ~(__cache_line_size-1);
972e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        _S_start_free = (char *)memalign(__cache_line_size, __bytes_to_get);
973e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        if (0 == _S_start_free) {
974e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott          _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
975e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott        }
976e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      }
977e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else  /* !SGI_SOURCE */
978e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
979e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
980e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_heap_size += __bytes_to_get >> 4;
981e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      _S_end_free = _S_start_free + __bytes_to_get;
982e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    }
983e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
984e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // lock is released here
985e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return _S_chunk_alloc(__p_size, __nobjs, __a);
986e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
987e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
988e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
989e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* n must be > 0      */
990e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid *_Pthread_alloc_impl::allocate(size_t& __n) {
991e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
992e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * volatile * __my_free_list;
993e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * __result;
994e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __state_type* __a;
995e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
996e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__n > _MAX_BYTES) {
997e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __malloc_alloc::allocate(__n);
998e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
999e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1000e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __n = _S_round_up(__n);
1001e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __a = _S_get_per_thread_state();
1002e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1003e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __my_free_list = __a->__free_list + _S_freelist_index(__n);
1004e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = *__my_free_list;
1005e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__result == 0) {
1006e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    void *__r = __a->_M_refill(__n);
1007e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __r;
1008e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1009e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __result->__free_list_link;
1010e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
1011e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
1012e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1013e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* p may not be 0 */
1014e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _Pthread_alloc_impl::deallocate(void *__p, size_t __n) {
1015e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
1016e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj *__q = (__obj *)__p;
1017e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * volatile * __my_free_list;
1018e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __state_type* __a;
1019e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1020e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__n > _MAX_BYTES) {
1021e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      __malloc_alloc::deallocate(__p, __n);
1022e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott      return;
1023e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1024e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1025e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __a = _S_get_per_thread_state();
1026e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1027e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __my_free_list = __a->__free_list + _S_freelist_index(__n);
1028e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __q -> __free_list_link = *__my_free_list;
1029e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __q;
1030e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
1031e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1032e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// boris : versions for per_thread_allocator
1033e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* n must be > 0      */
1034e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid *_Pthread_alloc_impl::allocate(size_t& __n, __state_type* __a) {
1035e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
1036e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * volatile * __my_free_list;
1037e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * __result;
1038e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1039e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__n > _MAX_BYTES) {
1040e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __malloc_alloc::allocate(__n);
1041e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1042e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __n = _S_round_up(__n);
1043e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1044e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // boris : here, we have to lock per thread state, as we may be getting memory from
1045e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // different thread pool.
1046e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_auto_lock __lock(__a->_M_lock);
1047e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1048e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __my_free_list = __a->__free_list + _S_freelist_index(__n);
1049e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = *__my_free_list;
1050e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__result == 0) {
1051e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    void *__r = __a->_M_refill(__n);
1052e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return __r;
1053e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1054e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __result->__free_list_link;
1055e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
1056e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott};
1057e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1058e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/* p may not be 0 */
1059e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _Pthread_alloc_impl::deallocate(void *__p, size_t __n, __state_type* __a) {
1060e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  typedef _Pthread_alloc_obj __obj;
1061e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj *__q = (__obj *)__p;
1062e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __obj * volatile * __my_free_list;
1063e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1064e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__n > _MAX_BYTES) {
1065e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    __malloc_alloc::deallocate(__p, __n);
1066e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return;
1067e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1068e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1069e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // boris : here, we have to lock per thread state, as we may be returning memory from
1070e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  // different thread.
1071e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _STLP_auto_lock __lock(__a->_M_lock);
1072e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1073e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __my_free_list = __a->__free_list + _S_freelist_index(__n);
1074e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __q -> __free_list_link = *__my_free_list;
1075e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  *__my_free_list = __q;
1076e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
1077e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1078e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid *_Pthread_alloc_impl::reallocate(void *__p, size_t __old_sz, size_t& __new_sz) {
1079e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  void * __result;
1080e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  size_t __copy_sz;
1081e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1082e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (__old_sz > _MAX_BYTES && __new_sz > _MAX_BYTES) {
1083e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return realloc(__p, __new_sz);
1084e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
1085e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1086e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return __p;
1087e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __result = allocate(__new_sz);
1088e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
1089e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  memcpy(__result, __p, __copy_sz);
1090e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  deallocate(__p, __old_sz);
1091e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return __result;
1092e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
1093e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1094e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_free_per_thread_states = 0;
1095e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottpthread_key_t _Pthread_alloc_impl::_S_key = 0;
1096e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_STATIC_MUTEX _Pthread_alloc_impl::_S_chunk_allocator_lock _STLP_MUTEX_INITIALIZER;
1097e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottbool _Pthread_alloc_impl::_S_key_initialized = false;
1098e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar *_Pthread_alloc_impl::_S_start_free = 0;
1099e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottchar *_Pthread_alloc_impl::_S_end_free = 0;
1100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottsize_t _Pthread_alloc_impl::_S_heap_size = 0;
1101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid * _STLP_CALL _Pthread_alloc::allocate(size_t& __n)
1103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return _Pthread_alloc_impl::allocate(__n); }
1104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n)
1105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ _Pthread_alloc_impl::deallocate(__p, __n); }
1106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid * _STLP_CALL _Pthread_alloc::allocate(size_t& __n, __state_type* __a)
1107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return _Pthread_alloc_impl::allocate(__n, __a); }
1108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n, __state_type* __a)
1109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ _Pthread_alloc_impl::deallocate(__p, __n, __a); }
1110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottvoid * _STLP_CALL _Pthread_alloc::reallocate(void *__p, size_t __old_sz, size_t& __new_sz)
1111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return _Pthread_alloc_impl::reallocate(__p, __old_sz, __new_sz); }
1112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_Pthread_alloc_per_thread_state* _STLP_CALL _Pthread_alloc::_S_get_per_thread_state()
1113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return _Pthread_alloc_impl::_S_get_per_thread_state(); }
1114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_MOVE_TO_STD_NAMESPACE
1116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
1118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_END_NAMESPACE
1120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
1121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#undef _S_FREELIST_INDEX
1122