ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

allocators.cpp
Go to the documentation of this file.
00001 /*
00002  *
00003  * Copyright (c) 1996,1997
00004  * Silicon Graphics Computer Systems, Inc.
00005  *
00006  * Copyright (c) 1997
00007  * Moscow Center for SPARC Technology
00008  *
00009  * Copyright (c) 1999
00010  * Boris Fomitchev
00011  *
00012  * This material is provided "as is", with absolutely no warranty expressed
00013  * or implied. Any use is at your own risk.
00014  *
00015  * Permission to use or copy this software for any purpose is hereby granted
00016  * without fee, provided the above notices are retained on all copies.
00017  * Permission to modify the code and to distribute modified code is granted,
00018  * provided the above notices are retained, and a notice that the code was
00019  * modified is included with the above copyright notice.
00020  *
00021  */
00022 
00023 #include "stlport_prefix.h"
00024 
00025 #include <memory>
00026 
00027 #if defined (__GNUC__) && (defined (__CYGWIN__) || defined (__MINGW32__))
00028 #  include <malloc.h>
00029 #endif
00030 
00031 #if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
00032 #  include <pthread_alloc>
00033 #  include <cerrno>
00034 #endif
00035 
00036 #include <stl/_threads.h>
00037 
00038 #include "lock_free_slist.h"
00039 
00040 #if defined (__WATCOMC__)
00041 #  pragma warning 13 9
00042 #  pragma warning 367 9
00043 #  pragma warning 368 9
00044 #endif
00045 
00046 #if defined (_STLP_SGI_THREADS)
00047   // We test whether threads are in use before locking.
00048   // Perhaps this should be moved into stl_threads.h, but that
00049   // probably makes it harder to avoid the procedure call when
00050   // it isn't needed.
00051 extern "C" {
00052   extern int __us_rsthread_malloc;
00053 }
00054 #endif
00055 
00056 // Specialised debug form of new operator which does not provide "false"
00057 // memory leaks when run with debug CRT libraries.
00058 #if defined (_STLP_MSVC) && (_STLP_MSVC >= 1020 && defined (_STLP_DEBUG_ALLOC)) && !defined (_STLP_WCE)
00059 #  include <crtdbg.h>
00060 inline char* __stlp_new_chunk(size_t __bytes) {
00061   void *__chunk = _STLP_CHECK_NULL_ALLOC(::operator new(__bytes, __FILE__, __LINE__));
00062   return __STATIC_CAST(char*, __chunk);
00063 }
00064 inline void __stlp_delete_chunck(void* __p) { ::operator delete(__p, __FILE__, __LINE__); }
00065 #else
00066 #  ifdef _STLP_NODE_ALLOC_USE_MALLOC
00067 #    include <cstdlib>
00068 inline char* __stlp_new_chunk(size_t __bytes) {
00069   // do not use _STLP_CHECK_NULL_ALLOC, this macro is dedicated to new operator.
00070   void *__chunk = _STLP_VENDOR_CSTD::malloc(__bytes);
00071   if (__chunk == 0) {
00072     _STLP_THROW_BAD_ALLOC;
00073   }
00074   return __STATIC_CAST(char*, __chunk);
00075 }
00076 inline void __stlp_delete_chunck(void* __p) { _STLP_VENDOR_CSTD::free(__p); }
00077 #  else
00078 inline char* __stlp_new_chunk(size_t __bytes)
00079 { return __STATIC_CAST(char*, _STLP_STD::__stl_new(__bytes)); }
00080 inline void __stlp_delete_chunck(void* __p) { _STLP_STD::__stl_delete(__p); }
00081 #  endif
00082 #endif
00083 
00084 /* This is an additional atomic operations to the ones already defined in
00085  * stl/_threads.h, platform should try to support it to improve performance.
00086  * __add_atomic_t _STLP_ATOMIC_ADD(volatile __add_atomic_t* __target, __add_atomic_t __val) :
00087  * does *__target = *__target + __val and returns the old *__target value */
00088 typedef long __add_atomic_t;
00089 typedef unsigned long __uadd_atomic_t;
00090 
00091 #if defined (__GNUC__) && defined (__i386__)
00092 inline long _STLP_atomic_add_gcc_x86(long volatile* p, long addend) {
00093   long result;
00094   __asm__ __volatile__
00095     ("lock; xaddl %1, %0;"
00096     :"=m" (*p), "=r" (result)
00097     :"m"  (*p), "1"  (addend)
00098     :"cc");
00099  return result + addend;
00100 }
00101 #  define _STLP_ATOMIC_ADD(__dst, __val)  _STLP_atomic_add_gcc_x86(__dst, __val)
00102 #elif defined (_STLP_WIN32THREADS)
00103 // The Win32 API function InterlockedExchangeAdd is not available on Windows 95.
00104 #  if !defined (_STLP_WIN95_LIKE)
00105 #    if defined (_STLP_NEW_PLATFORM_SDK)
00106 #      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__dst, __val)
00107 #    else
00108 #      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__CONST_CAST(__add_atomic_t*, __dst), __val)
00109 #    endif
00110 #  endif
00111 #endif
00112 
00113 #if defined (__OS400__)
00114 // dums 02/05/2007: is it really necessary ?
00115 enum { _ALIGN = 16, _ALIGN_SHIFT = 4 };
00116 #else
00117 enum { _ALIGN = 2 * sizeof(void*), _ALIGN_SHIFT = 2 + sizeof(void*) / 4 };
00118 #endif
00119 
00120 #define _S_FREELIST_INDEX(__bytes) ((__bytes - size_t(1)) >> (int)_ALIGN_SHIFT)
00121 
00122 _STLP_BEGIN_NAMESPACE
00123 
00124 // malloc_alloc out-of-memory handling
00125 static __oom_handler_type __oom_handler = __STATIC_CAST(__oom_handler_type, 0);
00126 
00127 #ifdef _STLP_THREADS
00128 _STLP_mutex __oom_handler_lock;
00129 #endif
00130 
00131 void* _STLP_CALL __malloc_alloc::allocate(size_t __n)
00132 {
00133   void *__result = malloc(__n);
00134   if ( 0 == __result ) {
00135     __oom_handler_type __my_malloc_handler;
00136 
00137     for (;;) {
00138       {
00139 #ifdef _STLP_THREADS
00140         _STLP_auto_lock _l( __oom_handler_lock );
00141 #endif
00142         __my_malloc_handler = __oom_handler;
00143       }
00144       if ( 0 == __my_malloc_handler) {
00145         _STLP_THROW_BAD_ALLOC;
00146       }
00147       (*__my_malloc_handler)();
00148       __result = malloc(__n);
00149       if ( __result )
00150         return __result;
00151     }
00152   }
00153   return __result;
00154 }
00155 
00156 __oom_handler_type _STLP_CALL __malloc_alloc::set_malloc_handler(__oom_handler_type __f)
00157 {
00158 #ifdef _STLP_THREADS
00159   _STLP_auto_lock _l( __oom_handler_lock );
00160 #endif
00161   __oom_handler_type __old = __oom_handler;
00162   __oom_handler = __f;
00163   return __old;
00164 }
00165 
00166 // *******************************************************
00167 // Default node allocator.
00168 // With a reasonable compiler, this should be roughly as fast as the
00169 // original STL class-specific allocators, but with less fragmentation.
00170 //
00171 // Important implementation properties:
00172 // 1. If the client request an object of size > _MAX_BYTES, the resulting
00173 //    object will be obtained directly from malloc.
00174 // 2. In all other cases, we allocate an object of size exactly
00175 //    _S_round_up(requested_size).  Thus the client has enough size
00176 //    information that we can return the object to the proper free list
00177 //    without permanently losing part of the object.
00178 //
00179 
00180 #define _STLP_NFREELISTS 16
00181 
00182 #if defined (_STLP_LEAKS_PEDANTIC) && defined (_STLP_USE_DYNAMIC_LIB)
00183 /*
00184  * We can only do cleanup of the node allocator memory pool if we are
00185  * sure that the STLport library is used as a shared one as it guaranties
00186  * the unicity of the node allocator instance. Without that guaranty node
00187  * allocator instances might exchange memory blocks making the implementation
00188  * of a cleaning process much more complicated.
00189  */
00190 #  define _STLP_DO_CLEAN_NODE_ALLOC
00191 #endif
00192 
00193 /* When STLport is used without multi threaded safety we use the node allocator
00194  * implementation with locks as locks becomes no-op. The lock free implementation
00195  * always use system specific atomic operations which are slower than 'normal'
00196  * ones.
00197  */
00198 #if defined (_STLP_THREADS) && \
00199     defined (_STLP_HAS_ATOMIC_FREELIST) && defined (_STLP_ATOMIC_ADD)
00200 /*
00201  * We have an implementation of the atomic freelist (_STLP_atomic_freelist)
00202  * for this architecture and compiler.  That means we can use the non-blocking
00203  * implementation of the node-allocation engine.*/
00204 #  define _STLP_USE_LOCK_FREE_IMPLEMENTATION
00205 #endif
00206 
00207 #if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00208 #  if defined (_STLP_THREADS)
00209 
00210 class _Node_Alloc_Lock {
00211   static _STLP_STATIC_MUTEX& _S_Mutex() {
00212     static _STLP_STATIC_MUTEX mutex _STLP_MUTEX_INITIALIZER;
00213     return mutex;
00214   }
00215 public:
00216   _Node_Alloc_Lock() {
00217 #    if defined (_STLP_SGI_THREADS)
00218     if (__us_rsthread_malloc)
00219 #    endif
00220       _S_Mutex()._M_acquire_lock();
00221   }
00222 
00223   ~_Node_Alloc_Lock() {
00224 #    if defined (_STLP_SGI_THREADS)
00225     if (__us_rsthread_malloc)
00226 #    endif
00227       _S_Mutex()._M_release_lock();
00228   }
00229 };
00230 
00231 #  else
00232 
00233 class _Node_Alloc_Lock {
00234 public:
00235   _Node_Alloc_Lock() { }
00236   ~_Node_Alloc_Lock() { }
00237 };
00238 
00239 #  endif
00240 
00241 struct _Node_alloc_obj {
00242   _Node_alloc_obj * _M_next;
00243 };
00244 #endif
00245 
00246 class __node_alloc_impl {
00247   static inline size_t _STLP_CALL _S_round_up(size_t __bytes)
00248   { return (((__bytes) + (size_t)_ALIGN-1) & ~((size_t)_ALIGN - 1)); }
00249 
00250 #if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00251   typedef _STLP_atomic_freelist::item   _Obj;
00252   typedef _STLP_atomic_freelist         _Freelist;
00253   typedef _STLP_atomic_freelist         _ChunkList;
00254 
00255   // Header of blocks of memory that have been allocated as part of
00256   // a larger chunk but have not yet been chopped up into nodes.
00257   struct _FreeBlockHeader : public _STLP_atomic_freelist::item {
00258     char* _M_end;     // pointer to end of free memory
00259   };
00260 #else
00261   typedef _Node_alloc_obj       _Obj;
00262   typedef _Obj* _STLP_VOLATILE  _Freelist;
00263   typedef _Obj*                 _ChunkList;
00264 #endif
00265 
00266 private:
00267   // Returns an object of size __n, and optionally adds to size __n free list.
00268   static _Obj* _S_refill(size_t __n);
00269   // Allocates a chunk for nobjs of size __p_size.  nobjs may be reduced
00270   // if it is inconvenient to allocate the requested number.
00271   static char* _S_chunk_alloc(size_t __p_size, int& __nobjs);
00272   // Chunk allocation state.
00273   static _Freelist _S_free_list[_STLP_NFREELISTS];
00274   // Amount of total allocated memory
00275 #if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00276   static _STLP_VOLATILE __add_atomic_t _S_heap_size;
00277 #else
00278   static size_t _S_heap_size;
00279 #endif
00280 
00281 #if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00282   // List of blocks of free memory
00283   static _STLP_atomic_freelist  _S_free_mem_blocks;
00284 #else
00285   // Start of the current free memory buffer
00286   static char* _S_start_free;
00287   // End of the current free memory buffer
00288   static char* _S_end_free;
00289 #endif
00290 
00291 #if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00292 public:
00293   // Methods to report alloc/dealloc calls to the counter system.
00294 #  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00295   typedef _STLP_VOLATILE __stl_atomic_t _AllocCounter;
00296 #  else
00297   typedef __stl_atomic_t _AllocCounter;
00298 #  endif
00299   static _AllocCounter& _STLP_CALL _S_alloc_counter();
00300   static void _S_alloc_call();
00301   static void _S_dealloc_call();
00302 
00303 private:
00304   // Free all the allocated chuncks of memory
00305   static void _S_chunk_dealloc();
00306   // Beginning of the linked list of allocated chunks of memory
00307   static _ChunkList _S_chunks;
00308 #endif /* _STLP_DO_CLEAN_NODE_ALLOC */
00309 
00310 public:
00311   /* __n must be > 0      */
00312   static void* _M_allocate(size_t& __n);
00313   /* __p may not be 0 */
00314   static void _M_deallocate(void *__p, size_t __n);
00315 };
00316 
00317 #if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00318 void* __node_alloc_impl::_M_allocate(size_t& __n) {
00319   __n = _S_round_up(__n);
00320   _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
00321   _Obj *__r;
00322 
00323   // Acquire the lock here with a constructor call.
00324   // This ensures that it is released in exit or during stack
00325   // unwinding.
00326   _Node_Alloc_Lock __lock_instance;
00327 
00328   if ( (__r  = *__my_free_list) != 0 ) {
00329     *__my_free_list = __r->_M_next;
00330   } else {
00331     __r = _S_refill(__n);
00332   }
00333 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00334   _S_alloc_call();
00335 #  endif
00336   // lock is released here
00337   return __r;
00338 }
00339 
00340 void __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
00341   _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
00342   _Obj * __pobj = __STATIC_CAST(_Obj*, __p);
00343 
00344   // acquire lock
00345   _Node_Alloc_Lock __lock_instance;
00346   __pobj->_M_next = *__my_free_list;
00347   *__my_free_list = __pobj;
00348 
00349 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00350   _S_dealloc_call();
00351 #  endif
00352   // lock is released here
00353 }
00354 
00355 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00356 #    define _STLP_OFFSET sizeof(_Obj)
00357 #  else
00358 #    define _STLP_OFFSET 0
00359 #  endif
00360 
00361 /* We allocate memory in large chunks in order to avoid fragmenting     */
00362 /* the malloc heap too much.                                            */
00363 /* We assume that size is properly aligned.                             */
00364 /* We hold the allocation lock.                                         */
00365 char* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
00366   char* __result;
00367   size_t __total_bytes = _p_size * __nobjs;
00368   size_t __bytes_left = _S_end_free - _S_start_free;
00369 
00370   if (__bytes_left > 0) {
00371     if (__bytes_left >= __total_bytes) {
00372       __result = _S_start_free;
00373       _S_start_free += __total_bytes;
00374       return __result;
00375     }
00376 
00377     if (__bytes_left >= _p_size) {
00378       __nobjs = (int)(__bytes_left / _p_size);
00379       __total_bytes = _p_size * __nobjs;
00380       __result = _S_start_free;
00381       _S_start_free += __total_bytes;
00382       return __result;
00383     }
00384 
00385     // Try to make use of the left-over piece.
00386     _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__bytes_left);
00387     __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = *__my_free_list;
00388     *__my_free_list = __REINTERPRET_CAST(_Obj*, _S_start_free);
00389     _S_start_free = _S_end_free = 0;
00390   }
00391 
00392   size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size) + _STLP_OFFSET;
00393 
00394   _STLP_TRY {
00395     _S_start_free = __stlp_new_chunk(__bytes_to_get);
00396   }
00397 #if defined (_STLP_USE_EXCEPTIONS)
00398   catch (const _STLP_STD::bad_alloc&) {
00399     _Obj* _STLP_VOLATILE* __my_free_list;
00400     _Obj* __p;
00401     // Try to do with what we have.  That can't hurt.
00402     // We do not try smaller requests, since that tends
00403     // to result in disaster on multi-process machines.
00404     for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
00405       __my_free_list = _S_free_list + _S_FREELIST_INDEX(__i);
00406       __p = *__my_free_list;
00407       if (0 != __p) {
00408         *__my_free_list = __p -> _M_next;
00409         _S_start_free = __REINTERPRET_CAST(char*, __p);
00410         _S_end_free = _S_start_free + __i;
00411         return _S_chunk_alloc(_p_size, __nobjs);
00412         // Any leftover piece will eventually make it to the
00413         // right free list.
00414       }
00415     }
00416     __bytes_to_get = __total_bytes + _STLP_OFFSET;
00417     _S_start_free = __stlp_new_chunk(__bytes_to_get);
00418   }
00419 #endif
00420 
00421   _S_heap_size += __bytes_to_get >> 4;
00422 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00423   __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = _S_chunks;
00424   _S_chunks = __REINTERPRET_CAST(_Obj*, _S_start_free);
00425 #  endif
00426   _S_end_free = _S_start_free + __bytes_to_get;
00427   _S_start_free += _STLP_OFFSET;
00428   return _S_chunk_alloc(_p_size, __nobjs);
00429 }
00430 
00431 /* Returns an object of size __n, and optionally adds to size __n free list.*/
00432 /* We assume that __n is properly aligned.                                  */
00433 /* We hold the allocation lock.                                             */
00434 _Node_alloc_obj* __node_alloc_impl::_S_refill(size_t __n) {
00435   int __nobjs = 20;
00436   char* __chunk = _S_chunk_alloc(__n, __nobjs);
00437 
00438   if (1 == __nobjs) return __REINTERPRET_CAST(_Obj*, __chunk);
00439 
00440   _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
00441   _Obj* __result;
00442   _Obj* __current_obj;
00443   _Obj* __next_obj;
00444 
00445   /* Build free list in chunk */
00446   __result = __REINTERPRET_CAST(_Obj*, __chunk);
00447   *__my_free_list = __next_obj = __REINTERPRET_CAST(_Obj*, __chunk + __n);
00448   for (--__nobjs; --__nobjs; ) {
00449     __current_obj = __next_obj;
00450     __next_obj = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __next_obj) + __n);
00451     __current_obj->_M_next = __next_obj;
00452   }
00453   __next_obj->_M_next = 0;
00454   return __result;
00455 }
00456 
00457 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00458 void __node_alloc_impl::_S_alloc_call()
00459 { ++_S_alloc_counter(); }
00460 
00461 void __node_alloc_impl::_S_dealloc_call() {
00462   __stl_atomic_t &counter = _S_alloc_counter();
00463   if (--counter == 0)
00464   { _S_chunk_dealloc(); }
00465 }
00466 
00467 /* We deallocate all the memory chunks      */
00468 void __node_alloc_impl::_S_chunk_dealloc() {
00469   _Obj *__pcur = _S_chunks, *__pnext;
00470   while (__pcur != 0) {
00471     __pnext = __pcur->_M_next;
00472     __stlp_delete_chunck(__pcur);
00473     __pcur = __pnext;
00474   }
00475   _S_chunks = 0;
00476   _S_start_free = _S_end_free = 0;
00477   _S_heap_size = 0;
00478   memset(__REINTERPRET_CAST(char*, __CONST_CAST(_Obj**, &_S_free_list[0])), 0, _STLP_NFREELISTS * sizeof(_Obj*));
00479 }
00480 #  endif
00481 
00482 #else
00483 
00484 void* __node_alloc_impl::_M_allocate(size_t& __n) {
00485   __n = _S_round_up(__n);
00486   _Obj* __r = _S_free_list[_S_FREELIST_INDEX(__n)].pop();
00487   if (__r  == 0)
00488   { __r = _S_refill(__n); }
00489 
00490 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00491   _S_alloc_call();
00492 #  endif
00493   return __r;
00494 }
00495 
00496 void __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
00497   _S_free_list[_S_FREELIST_INDEX(__n)].push(__STATIC_CAST(_Obj*, __p));
00498 
00499 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00500   _S_dealloc_call();
00501 #  endif
00502 }
00503 
00504 /* Returns an object of size __n, and optionally adds additional ones to    */
00505 /* freelist of objects of size __n.                                         */
00506 /* We assume that __n is properly aligned.                                  */
00507 __node_alloc_impl::_Obj* __node_alloc_impl::_S_refill(size_t __n) {
00508   int __nobjs = 20;
00509   char* __chunk = _S_chunk_alloc(__n, __nobjs);
00510 
00511   if (__nobjs <= 1)
00512     return __REINTERPRET_CAST(_Obj*, __chunk);
00513 
00514   // Push all new nodes (minus first one) onto freelist
00515   _Obj* __result   = __REINTERPRET_CAST(_Obj*, __chunk);
00516   _Obj* __cur_item = __result;
00517   _Freelist* __my_freelist = _S_free_list + _S_FREELIST_INDEX(__n);
00518   for (--__nobjs; __nobjs != 0; --__nobjs) {
00519     __cur_item  = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __cur_item) + __n);
00520     __my_freelist->push(__cur_item);
00521   }
00522   return __result;
00523 }
00524 
00525 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00526 #    define _STLP_OFFSET _ALIGN
00527 #  else
00528 #    define _STLP_OFFSET 0
00529 #  endif
00530 
00531 /* We allocate memory in large chunks in order to avoid fragmenting     */
00532 /* the malloc heap too much.                                            */
00533 /* We assume that size is properly aligned.                             */
00534 char* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
00535 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00536   //We are going to add a small memory block to keep all the allocated blocks
00537   //address, we need to do so respecting the memory alignment. The following
00538   //static assert checks that the reserved block is big enough to store a pointer.
00539   _STLP_STATIC_ASSERT(sizeof(_Obj) <= _ALIGN)
00540 #  endif
00541   char*  __result       = 0;
00542   __add_atomic_t __total_bytes  = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
00543 
00544   _FreeBlockHeader* __block = __STATIC_CAST(_FreeBlockHeader*, _S_free_mem_blocks.pop());
00545   if (__block != 0) {
00546     // We checked a block out and can now mess with it with impugnity.
00547     // We'll put the remainder back into the list if we're done with it below.
00548     char*  __buf_start  = __REINTERPRET_CAST(char*, __block);
00549     __add_atomic_t __bytes_left = __block->_M_end - __buf_start;
00550 
00551     if ((__bytes_left < __total_bytes) && (__bytes_left >= __STATIC_CAST(__add_atomic_t, _p_size))) {
00552       // There's enough left for at least one object, but not as much as we wanted
00553       __result      = __buf_start;
00554       __nobjs       = (int)(__bytes_left/_p_size);
00555       __total_bytes = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
00556       __bytes_left -= __total_bytes;
00557       __buf_start  += __total_bytes;
00558     }
00559     else if (__bytes_left >= __total_bytes) {
00560       // The block has enough left to satisfy all that was asked for
00561       __result      = __buf_start;
00562       __bytes_left -= __total_bytes;
00563       __buf_start  += __total_bytes;
00564     }
00565 
00566     if (__bytes_left != 0) {
00567       // There is still some memory left over in block after we satisfied our request.
00568       if ((__result != 0) && (__bytes_left >= (__add_atomic_t)sizeof(_FreeBlockHeader))) {
00569         // We were able to allocate at least one object and there is still enough
00570         // left to put remainder back into list.
00571         _FreeBlockHeader* __newblock = __REINTERPRET_CAST(_FreeBlockHeader*, __buf_start);
00572         __newblock->_M_end  = __block->_M_end;
00573         _S_free_mem_blocks.push(__newblock);
00574       }
00575       else {
00576         // We were not able to allocate enough for at least one object.
00577         // Shove into freelist of nearest (rounded-down!) size.
00578         size_t __rounded_down = _S_round_up(__bytes_left + 1) - (size_t)_ALIGN;
00579         if (__rounded_down > 0)
00580           _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push((_Obj*)__buf_start);
00581       }
00582     }
00583     if (__result != 0)
00584       return __result;
00585   }
00586 
00587   // We couldn't satisfy it from the list of free blocks, get new memory.
00588   __add_atomic_t __bytes_to_get = 2 * __total_bytes +
00589                                   __STATIC_CAST(__add_atomic_t,
00590                                                 _S_round_up(__STATIC_CAST(__uadd_atomic_t, _STLP_ATOMIC_ADD(&_S_heap_size, 0)))) +
00591                                   _STLP_OFFSET;
00592   _STLP_TRY {
00593     __result = __stlp_new_chunk(__bytes_to_get);
00594   }
00595 #if defined (_STLP_USE_EXCEPTIONS)
00596   catch (const bad_alloc&) {
00597     // Allocation failed; try to canibalize from freelist of a larger object size.
00598     for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
00599       _Obj* __p  = _S_free_list[_S_FREELIST_INDEX(__i)].pop();
00600       if (0 != __p) {
00601         if (__i < sizeof(_FreeBlockHeader)) {
00602           // Not enough to put into list of free blocks, divvy it up here.
00603           // Use as much as possible for this request and shove remainder into freelist.
00604           __nobjs = (int)(__i/_p_size);
00605           __total_bytes = __nobjs * __STATIC_CAST(__add_atomic_t, _p_size);
00606           size_t __bytes_left = __i - __total_bytes;
00607           size_t __rounded_down = _S_round_up(__bytes_left+1) - (size_t)_ALIGN;
00608           if (__rounded_down > 0) {
00609             _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push(__REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __p) + __total_bytes));
00610           }
00611           return __REINTERPRET_CAST(char*, __p);
00612         }
00613         else {
00614           // Add node to list of available blocks and recursively allocate from it.
00615           _FreeBlockHeader* __newblock = (_FreeBlockHeader*)__p;
00616           __newblock->_M_end  = __REINTERPRET_CAST(char*, __p) + __i;
00617           _S_free_mem_blocks.push(__newblock);
00618           return _S_chunk_alloc(_p_size, __nobjs);
00619         }
00620       }
00621     }
00622 
00623     // We were not able to find something in a freelist, try to allocate a smaller amount.
00624     __bytes_to_get  = __total_bytes + _STLP_OFFSET;
00625     __result = __stlp_new_chunk(__bytes_to_get);
00626 
00627     // This should either throw an exception or remedy the situation.
00628     // Thus we assume it succeeded.
00629   }
00630 #endif
00631   // Alignment check
00632   _STLP_VERBOSE_ASSERT(((__REINTERPRET_CAST(size_t, __result) & __STATIC_CAST(size_t, _ALIGN - 1)) == 0),
00633                        _StlMsg_DBA_DELETED_TWICE)
00634   _STLP_ATOMIC_ADD(&_S_heap_size, __bytes_to_get >> 4);
00635 
00636 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00637   // We have to track the allocated memory chunks for release on exit.
00638   _S_chunks.push(__REINTERPRET_CAST(_Obj*, __result));
00639   __result       += _ALIGN;
00640   __bytes_to_get -= _ALIGN;
00641 #  endif
00642 
00643   if (__bytes_to_get > __total_bytes) {
00644     // Push excess memory allocated in this chunk into list of free memory blocks
00645     _FreeBlockHeader* __freeblock = __REINTERPRET_CAST(_FreeBlockHeader*, __result + __total_bytes);
00646     __freeblock->_M_end  = __result + __bytes_to_get;
00647     _S_free_mem_blocks.push(__freeblock);
00648   }
00649   return __result;
00650 }
00651 
00652 #  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00653 void __node_alloc_impl::_S_alloc_call()
00654 { _STLP_ATOMIC_INCREMENT(&_S_alloc_counter()); }
00655 
00656 void __node_alloc_impl::_S_dealloc_call() {
00657   _STLP_VOLATILE __stl_atomic_t *pcounter = &_S_alloc_counter();
00658   if (_STLP_ATOMIC_DECREMENT(pcounter) == 0)
00659     _S_chunk_dealloc();
00660 }
00661 
00662 /* We deallocate all the memory chunks      */
00663 void __node_alloc_impl::_S_chunk_dealloc() {
00664   // Note: The _Node_alloc_helper class ensures that this function
00665   // will only be called when the (shared) library is unloaded or the
00666   // process is shutdown.  It's thus not possible that another thread
00667   // is currently trying to allocate a node (we're not thread-safe here).
00668   //
00669 
00670   // Clear the free blocks and all freelistst.  This makes sure that if
00671   // for some reason more memory is allocated again during shutdown
00672   // (it'd also be really nasty to leave references to deallocated memory).
00673   _S_free_mem_blocks.clear();
00674   _S_heap_size      = 0;
00675 
00676   for (size_t __i = 0; __i < _STLP_NFREELISTS; ++__i) {
00677     _S_free_list[__i].clear();
00678   }
00679 
00680   // Detach list of chunks and free them all
00681   _Obj* __chunk = _S_chunks.clear();
00682   while (__chunk != 0) {
00683     _Obj* __next = __chunk->_M_next;
00684     __stlp_delete_chunck(__chunk);
00685     __chunk  = __next;
00686   }
00687 }
00688 #  endif
00689 
00690 #endif
00691 
00692 #if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00693 struct __node_alloc_cleaner {
00694   ~__node_alloc_cleaner()
00695   { __node_alloc_impl::_S_dealloc_call(); }
00696 };
00697 
00698 #  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00699 _STLP_VOLATILE __stl_atomic_t& _STLP_CALL
00700 #  else
00701 __stl_atomic_t& _STLP_CALL
00702 #  endif
00703 __node_alloc_impl::_S_alloc_counter() {
00704   static _AllocCounter _S_counter = 1;
00705   static __node_alloc_cleaner _S_node_alloc_cleaner;
00706   return _S_counter;
00707 }
00708 #endif
00709 
00710 #if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00711 _Node_alloc_obj * _STLP_VOLATILE
00712 __node_alloc_impl::_S_free_list[_STLP_NFREELISTS]
00713 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
00714 // The 16 zeros are necessary to make version 4.1 of the SunPro
00715 // compiler happy.  Otherwise it appears to allocate too little
00716 // space for the array.
00717 #else
00718 _STLP_atomic_freelist __node_alloc_impl::_S_free_list[_STLP_NFREELISTS];
00719 _STLP_atomic_freelist __node_alloc_impl::_S_free_mem_blocks;
00720 #endif
00721 
00722 #if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00723 char *__node_alloc_impl::_S_start_free = 0;
00724 char *__node_alloc_impl::_S_end_free = 0;
00725 #endif
00726 
00727 #if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00728 _STLP_VOLATILE __add_atomic_t
00729 #else
00730 size_t
00731 #endif
00732 __node_alloc_impl::_S_heap_size = 0;
00733 
00734 #if defined (_STLP_DO_CLEAN_NODE_ALLOC)
00735 #  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
00736 _STLP_atomic_freelist __node_alloc_impl::_S_chunks;
00737 #  else
00738 _Node_alloc_obj* __node_alloc_impl::_S_chunks  = 0;
00739 #  endif
00740 #endif
00741 
00742 void * _STLP_CALL __node_alloc::_M_allocate(size_t& __n)
00743 { return __node_alloc_impl::_M_allocate(__n); }
00744 
00745 void _STLP_CALL __node_alloc::_M_deallocate(void *__p, size_t __n)
00746 { __node_alloc_impl::_M_deallocate(__p, __n); }
00747 
00748 #if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
00749 
00750 #  define _STLP_DATA_ALIGNMENT 8
00751 
00752 _STLP_MOVE_TO_PRIV_NAMESPACE
00753 
00754 // *******************************************************
00755 // __perthread_alloc implementation
00756 union _Pthread_alloc_obj {
00757   union _Pthread_alloc_obj * __free_list_link;
00758   char __client_data[_STLP_DATA_ALIGNMENT];    /* The client sees this.    */
00759 };
00760 
00761 // Pthread allocators don't appear to the client to have meaningful
00762 // instances.  We do in fact need to associate some state with each
00763 // thread.  That state is represented by _Pthread_alloc_per_thread_state.
00764 
00765 struct _Pthread_alloc_per_thread_state {
00766   typedef _Pthread_alloc_obj __obj;
00767   enum { _S_NFREELISTS = _MAX_BYTES / _STLP_DATA_ALIGNMENT };
00768 
00769   // Free list link for list of available per thread structures.
00770   // When one of these becomes available for reuse due to thread
00771   // termination, any objects in its free list remain associated
00772   // with it.  The whole structure may then be used by a newly
00773   // created thread.
00774   _Pthread_alloc_per_thread_state() : __next(0)
00775   { memset((void *)__CONST_CAST(_Pthread_alloc_obj**, __free_list), 0, (size_t)_S_NFREELISTS * sizeof(__obj *)); }
00776   // Returns an object of size __n, and possibly adds to size n free list.
00777   void *_M_refill(size_t __n);
00778 
00779   _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS];
00780   _Pthread_alloc_per_thread_state *__next;
00781   // this data member is only to be used by per_thread_allocator, which returns memory to the originating thread.
00782   _STLP_mutex _M_lock;
00783 };
00784 
00785 // Pthread-specific allocator.
00786 class _Pthread_alloc_impl {
00787 public: // but only for internal use:
00788   typedef _Pthread_alloc_per_thread_state __state_type;
00789   typedef char value_type;
00790 
00791   // Allocates a chunk for nobjs of size size.  nobjs may be reduced
00792   // if it is inconvenient to allocate the requested number.
00793   static char *_S_chunk_alloc(size_t __size, size_t &__nobjs, __state_type*);
00794 
00795   enum {_S_ALIGN = _STLP_DATA_ALIGNMENT};
00796 
00797   static size_t _S_round_up(size_t __bytes)
00798   { return (((__bytes) + (int)_S_ALIGN - 1) & ~((int)_S_ALIGN - 1)); }
00799   static size_t _S_freelist_index(size_t __bytes)
00800   { return (((__bytes) + (int)_S_ALIGN - 1) / (int)_S_ALIGN - 1); }
00801 
00802 private:
00803   // Chunk allocation state. And other shared state.
00804   // Protected by _S_chunk_allocator_lock.
00805   static _STLP_STATIC_MUTEX _S_chunk_allocator_lock;
00806   static char *_S_start_free;
00807   static char *_S_end_free;
00808   static size_t _S_heap_size;
00809   static __state_type *_S_free_per_thread_states;
00810   static pthread_key_t _S_key;
00811   static bool _S_key_initialized;
00812   // Pthread key under which per thread state is stored.
00813   // Allocator instances that are currently unclaimed by any thread.
00814   static void _S_destructor(void *instance);
00815   // Function to be called on thread exit to reclaim per thread
00816   // state.
00817   static __state_type *_S_new_per_thread_state();
00818 public:
00819   // Return a recycled or new per thread state.
00820   static __state_type *_S_get_per_thread_state();
00821 private:
00822         // ensure that the current thread has an associated
00823         // per thread state.
00824   class _M_lock;
00825   friend class _M_lock;
00826   class _M_lock {
00827   public:
00828     _M_lock () { _S_chunk_allocator_lock._M_acquire_lock(); }
00829     ~_M_lock () { _S_chunk_allocator_lock._M_release_lock(); }
00830   };
00831 
00832 public:
00833 
00834   /* n must be > 0      */
00835   static void * allocate(size_t& __n);
00836 
00837   /* p may not be 0 */
00838   static void deallocate(void *__p, size_t __n);
00839 
00840   // boris : versions for per_thread_allocator
00841   /* n must be > 0      */
00842   static void * allocate(size_t& __n, __state_type* __a);
00843 
00844   /* p may not be 0 */
00845   static void deallocate(void *__p, size_t __n, __state_type* __a);
00846 
00847   static void * reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
00848 };
00849 
00850 /* Returns an object of size n, and optionally adds to size n free list.*/
00851 /* We assume that n is properly aligned.                                */
00852 /* We hold the allocation lock.                                         */
00853 void *_Pthread_alloc_per_thread_state::_M_refill(size_t __n) {
00854   typedef _Pthread_alloc_obj __obj;
00855   size_t __nobjs = 128;
00856   char * __chunk = _Pthread_alloc_impl::_S_chunk_alloc(__n, __nobjs, this);
00857   __obj * volatile * __my_free_list;
00858   __obj * __result;
00859   __obj * __current_obj, * __next_obj;
00860   size_t __i;
00861 
00862   if (1 == __nobjs)  {
00863     return __chunk;
00864   }
00865 
00866   __my_free_list = __free_list + _Pthread_alloc_impl::_S_freelist_index(__n);
00867 
00868   /* Build free list in chunk */
00869   __result = (__obj *)__chunk;
00870   *__my_free_list = __next_obj = (__obj *)(__chunk + __n);
00871   for (__i = 1; ; ++__i) {
00872     __current_obj = __next_obj;
00873     __next_obj = (__obj *)((char *)__next_obj + __n);
00874     if (__nobjs - 1 == __i) {
00875       __current_obj -> __free_list_link = 0;
00876       break;
00877     } else {
00878       __current_obj -> __free_list_link = __next_obj;
00879     }
00880   }
00881   return __result;
00882 }
00883 
00884 void _Pthread_alloc_impl::_S_destructor(void *__instance) {
00885   _M_lock __lock_instance;  // Need to acquire lock here.
00886   _Pthread_alloc_per_thread_state* __s = (_Pthread_alloc_per_thread_state*)__instance;
00887   __s -> __next = _S_free_per_thread_states;
00888   _S_free_per_thread_states = __s;
00889 }
00890 
00891 _Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_new_per_thread_state() {
00892   /* lock already held here.  */
00893   if (0 != _S_free_per_thread_states) {
00894     _Pthread_alloc_per_thread_state *__result = _S_free_per_thread_states;
00895     _S_free_per_thread_states = _S_free_per_thread_states -> __next;
00896     return __result;
00897   }
00898   else {
00899     return new _Pthread_alloc_per_thread_state;
00900   }
00901 }
00902 
00903 _Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_get_per_thread_state() {
00904   int __ret_code;
00905   __state_type* __result;
00906 
00907   if (_S_key_initialized && (__result = (__state_type*) pthread_getspecific(_S_key)))
00908     return __result;
00909 
00910   /*REFERENCED*/
00911   _M_lock __lock_instance;  // Need to acquire lock here.
00912   if (!_S_key_initialized) {
00913     if (pthread_key_create(&_S_key, _S_destructor)) {
00914       _STLP_THROW_BAD_ALLOC;  // failed
00915     }
00916     _S_key_initialized = true;
00917   }
00918 
00919   __result = _S_new_per_thread_state();
00920   __ret_code = pthread_setspecific(_S_key, __result);
00921   if (__ret_code) {
00922     if (__ret_code == ENOMEM) {
00923       _STLP_THROW_BAD_ALLOC;
00924     } else {
00925   // EINVAL
00926       _STLP_ABORT();
00927     }
00928   }
00929   return __result;
00930 }
00931 
00932 /* We allocate memory in large chunks in order to avoid fragmenting     */
00933 /* the malloc heap too much.                                            */
00934 /* We assume that size is properly aligned.                             */
00935 char *_Pthread_alloc_impl::_S_chunk_alloc(size_t __p_size, size_t &__nobjs, _Pthread_alloc_per_thread_state *__a) {
00936   typedef _Pthread_alloc_obj __obj;
00937   {
00938     char * __result;
00939     size_t __total_bytes;
00940     size_t __bytes_left;
00941     /*REFERENCED*/
00942     _M_lock __lock_instance;         // Acquire lock for this routine
00943 
00944     __total_bytes = __p_size * __nobjs;
00945     __bytes_left = _S_end_free - _S_start_free;
00946     if (__bytes_left >= __total_bytes) {
00947       __result = _S_start_free;
00948       _S_start_free += __total_bytes;
00949       return __result;
00950     } else if (__bytes_left >= __p_size) {
00951       __nobjs = __bytes_left/__p_size;
00952       __total_bytes = __p_size * __nobjs;
00953       __result = _S_start_free;
00954       _S_start_free += __total_bytes;
00955       return __result;
00956     } else {
00957       size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size);
00958       // Try to make use of the left-over piece.
00959       if (__bytes_left > 0) {
00960         __obj * volatile * __my_free_list = __a->__free_list + _S_freelist_index(__bytes_left);
00961         ((__obj *)_S_start_free) -> __free_list_link = *__my_free_list;
00962         *__my_free_list = (__obj *)_S_start_free;
00963       }
00964 #  ifdef _SGI_SOURCE
00965       // Try to get memory that's aligned on something like a
00966       // cache line boundary, so as to avoid parceling out
00967       // parts of the same line to different threads and thus
00968       // possibly different processors.
00969       {
00970         const int __cache_line_size = 128;  // probable upper bound
00971         __bytes_to_get &= ~(__cache_line_size-1);
00972         _S_start_free = (char *)memalign(__cache_line_size, __bytes_to_get);
00973         if (0 == _S_start_free) {
00974           _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
00975         }
00976       }
00977 #  else  /* !SGI_SOURCE */
00978       _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
00979 #  endif
00980       _S_heap_size += __bytes_to_get >> 4;
00981       _S_end_free = _S_start_free + __bytes_to_get;
00982     }
00983   }
00984   // lock is released here
00985   return _S_chunk_alloc(__p_size, __nobjs, __a);
00986 }
00987 
00988 
00989 /* n must be > 0      */
00990 void *_Pthread_alloc_impl::allocate(size_t& __n) {
00991   typedef _Pthread_alloc_obj __obj;
00992   __obj * volatile * __my_free_list;
00993   __obj * __result;
00994   __state_type* __a;
00995 
00996   if (__n > _MAX_BYTES) {
00997     return __malloc_alloc::allocate(__n);
00998   }
00999 
01000   __n = _S_round_up(__n);
01001   __a = _S_get_per_thread_state();
01002 
01003   __my_free_list = __a->__free_list + _S_freelist_index(__n);
01004   __result = *__my_free_list;
01005   if (__result == 0) {
01006     void *__r = __a->_M_refill(__n);
01007     return __r;
01008   }
01009   *__my_free_list = __result->__free_list_link;
01010   return __result;
01011 };
01012 
01013 /* p may not be 0 */
01014 void _Pthread_alloc_impl::deallocate(void *__p, size_t __n) {
01015   typedef _Pthread_alloc_obj __obj;
01016   __obj *__q = (__obj *)__p;
01017   __obj * volatile * __my_free_list;
01018   __state_type* __a;
01019 
01020   if (__n > _MAX_BYTES) {
01021       __malloc_alloc::deallocate(__p, __n);
01022       return;
01023   }
01024 
01025   __a = _S_get_per_thread_state();
01026 
01027   __my_free_list = __a->__free_list + _S_freelist_index(__n);
01028   __q -> __free_list_link = *__my_free_list;
01029   *__my_free_list = __q;
01030 }
01031 
01032 // boris : versions for per_thread_allocator
01033 /* n must be > 0      */
01034 void *_Pthread_alloc_impl::allocate(size_t& __n, __state_type* __a) {
01035   typedef _Pthread_alloc_obj __obj;
01036   __obj * volatile * __my_free_list;
01037   __obj * __result;
01038 
01039   if (__n > _MAX_BYTES) {
01040     return __malloc_alloc::allocate(__n);
01041   }
01042   __n = _S_round_up(__n);
01043 
01044   // boris : here, we have to lock per thread state, as we may be getting memory from
01045   // different thread pool.
01046   _STLP_auto_lock __lock(__a->_M_lock);
01047 
01048   __my_free_list = __a->__free_list + _S_freelist_index(__n);
01049   __result = *__my_free_list;
01050   if (__result == 0) {
01051     void *__r = __a->_M_refill(__n);
01052     return __r;
01053   }
01054   *__my_free_list = __result->__free_list_link;
01055   return __result;
01056 };
01057 
01058 /* p may not be 0 */
01059 void _Pthread_alloc_impl::deallocate(void *__p, size_t __n, __state_type* __a) {
01060   typedef _Pthread_alloc_obj __obj;
01061   __obj *__q = (__obj *)__p;
01062   __obj * volatile * __my_free_list;
01063 
01064   if (__n > _MAX_BYTES) {
01065     __malloc_alloc::deallocate(__p, __n);
01066     return;
01067   }
01068 
01069   // boris : here, we have to lock per thread state, as we may be returning memory from
01070   // different thread.
01071   _STLP_auto_lock __lock(__a->_M_lock);
01072 
01073   __my_free_list = __a->__free_list + _S_freelist_index(__n);
01074   __q -> __free_list_link = *__my_free_list;
01075   *__my_free_list = __q;
01076 }
01077 
01078 void *_Pthread_alloc_impl::reallocate(void *__p, size_t __old_sz, size_t& __new_sz) {
01079   void * __result;
01080   size_t __copy_sz;
01081 
01082   if (__old_sz > _MAX_BYTES && __new_sz > _MAX_BYTES) {
01083     return realloc(__p, __new_sz);
01084   }
01085 
01086   if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return __p;
01087   __result = allocate(__new_sz);
01088   __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
01089   memcpy(__result, __p, __copy_sz);
01090   deallocate(__p, __old_sz);
01091   return __result;
01092 }
01093 
01094 _Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_free_per_thread_states = 0;
01095 pthread_key_t _Pthread_alloc_impl::_S_key = 0;
01096 _STLP_STATIC_MUTEX _Pthread_alloc_impl::_S_chunk_allocator_lock _STLP_MUTEX_INITIALIZER;
01097 bool _Pthread_alloc_impl::_S_key_initialized = false;
01098 char *_Pthread_alloc_impl::_S_start_free = 0;
01099 char *_Pthread_alloc_impl::_S_end_free = 0;
01100 size_t _Pthread_alloc_impl::_S_heap_size = 0;
01101 
01102 void * _STLP_CALL _Pthread_alloc::allocate(size_t& __n)
01103 { return _Pthread_alloc_impl::allocate(__n); }
01104 void _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n)
01105 { _Pthread_alloc_impl::deallocate(__p, __n); }
01106 void * _STLP_CALL _Pthread_alloc::allocate(size_t& __n, __state_type* __a)
01107 { return _Pthread_alloc_impl::allocate(__n, __a); }
01108 void _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n, __state_type* __a)
01109 { _Pthread_alloc_impl::deallocate(__p, __n, __a); }
01110 void * _STLP_CALL _Pthread_alloc::reallocate(void *__p, size_t __old_sz, size_t& __new_sz)
01111 { return _Pthread_alloc_impl::reallocate(__p, __old_sz, __new_sz); }
01112 _Pthread_alloc_per_thread_state* _STLP_CALL _Pthread_alloc::_S_get_per_thread_state()
01113 { return _Pthread_alloc_impl::_S_get_per_thread_state(); }
01114 
01115 _STLP_MOVE_TO_STD_NAMESPACE
01116 
01117 #endif
01118 
01119 _STLP_END_NAMESPACE
01120 
01121 #undef _S_FREELIST_INDEX

Generated on Sat May 26 2012 04:34:00 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.