Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2008, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // ---
     31 // Author: Sanjay Ghemawat <opensource (at) google.com>
     32 
     33 #ifndef TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
     34 #define TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
     35 
     36 #include <stddef.h>                     // for NULL, size_t
     37 
     38 #include "common.h"            // for MetaDataAlloc
     39 #include "free_list.h"          // for FL_Push/FL_Pop
     40 #include "internal_logging.h"  // for ASSERT
     41 #include "system-alloc.h"      // for TCMalloc_SystemAddGuard
     42 
     43 namespace tcmalloc {
     44 
     45 // Simple allocator for objects of a specified type.  External locking
     46 // is required before accessing one of these objects.
     47 template <class T>
     48 class PageHeapAllocator {
     49  public:
     50   // We use an explicit Init function because these variables are statically
     51   // allocated and their constructors might not have run by the time some
     52   // other static variable tries to allocate memory.
     53   void Init() {
     54     ASSERT(sizeof(T) <= kAllocIncrement);
     55     inuse_ = 0;
     56     free_area_ = NULL;
     57     free_avail_ = 0;
     58     free_list_ = NULL;
     59     // Reserve some space at the beginning to avoid fragmentation.
     60     Delete(New());
     61   }
     62 
     63   T* New() {
     64     // Consult free list
     65     void* result;
     66     if (free_list_ != NULL) {
     67       result = FL_Pop(&free_list_);
     68     } else {
     69       if (free_avail_ < sizeof(T)) {
     70         // Need more room. We assume that MetaDataAlloc returns
     71         // suitably aligned memory.
     72         free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
     73         if (free_area_ == NULL) {
     74           Log(kCrash, __FILE__, __LINE__,
     75               "FATAL ERROR: Out of memory trying to allocate internal "
     76               "tcmalloc data (bytes, object-size)",
     77               kAllocIncrement, sizeof(T));
     78         }
     79 
     80         // This guard page protects the metadata from being corrupted by a
     81         // buffer overrun. We currently have no mechanism for freeing it, since
     82         // we never release the metadata buffer. If that changes we'll need to
     83         // add something like TCMalloc_SystemRemoveGuard.
     84         size_t guard_size = TCMalloc_SystemAddGuard(free_area_,
     85                                                     kAllocIncrement);
     86         free_area_ += guard_size;
     87         free_avail_ = kAllocIncrement - guard_size;
     88         if (free_avail_ < sizeof(T)) {
     89           Log(kCrash, __FILE__, __LINE__,
     90               "FATAL ERROR: Insufficient memory to guard internal tcmalloc "
     91               "data (%d bytes, object-size %d, guard-size %d)\n",
     92               kAllocIncrement, static_cast<int>(sizeof(T)), guard_size);
     93         }
     94       }
     95       result = free_area_;
     96       free_area_ += sizeof(T);
     97       free_avail_ -= sizeof(T);
     98     }
     99     inuse_++;
    100     return reinterpret_cast<T*>(result);
    101   }
    102 
    103   void Delete(T* p) {
    104     FL_Push(&free_list_, p);
    105     inuse_--;
    106   }
    107 
    108   int inuse() const { return inuse_; }
    109 
    110  private:
    111   // How much to allocate from system at a time
    112   static const int kAllocIncrement = 128 << 10;
    113 
    114   // Free area from which to carve new objects
    115   char* free_area_;
    116   size_t free_avail_;
    117 
    118   // Free list of already carved objects
    119   void* free_list_;
    120 
    121   // Number of allocated but unfreed objects
    122   int inuse_;
    123 };
    124 
    125 }  // namespace tcmalloc
    126 
    127 #endif  // TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
    128