15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2008, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat <opensource@google.com>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef TCMALLOC_THREAD_CACHE_H_
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TCMALLOC_THREAD_CACHE_H_
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PTHREAD
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>                    // for pthread_t, pthread_key_t
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>                     // for size_t, NULL
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_STDINT_H
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>                     // for uint32_t, uint64_t
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>                  // for ssize_t
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "common.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "linked_list.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "maybe_threads.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "page_heap_allocator.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sampler.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "static_vars.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "common.h"            // for SizeMap, kMaxSize, etc
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "internal_logging.h"  // for ASSERT, etc
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "linked_list.h"       // for SLL_Pop, SLL_PopRange, etc
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "page_heap_allocator.h"  // for PageHeapAllocator
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sampler.h"           // for Sampler
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "static_vars.h"       // for Static
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tcmalloc {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Even if we have support for thread-local storage in the compiler
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and linker, the OS may not support it.  We need to check that at
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runtime.  Right now, we have to keep a manual set of "bad" OSes.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_TLS)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool kernel_supports_tls;   // defined in thread_cache.cc
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckIfKernelSupportsTLS();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool KernelSupportsTLS() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kernel_supports_tls;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif    // HAVE_TLS
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-------------------------------------------------------------------
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Data kept per thread
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-------------------------------------------------------------------
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadCache {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All ThreadCache objects are kept in a linked list (for stats collection)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadCache* next_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadCache* prev_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init(pthread_t tid);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cleanup();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Accessors (mostly just for printing stats)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int freelist_length(size_t cl) const { return list_[cl].length(); }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Total byte size in cache
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t Size() const { return size_; }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate an object of the given size and class. The size given
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // must be the same as the size of the class in the size map.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* Allocate(size_t size, size_t cl);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Deallocate(void* ptr, size_t size_class);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Scavenge();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetSamplePeriod();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record allocation of "k" bytes.  Return true iff allocation
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be sampled
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SampleAllocation(size_t k);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void         InitModule();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void         InitTSD();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* GetThreadHeap();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* GetCache();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* GetCacheIfPresent();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* CreateCacheIfNecessary();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void         BecomeIdle();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the number of thread heaps in use.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static inline int HeapsInUse();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes to total_bytes the total number of bytes used by all thread heaps.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // class_count must be an array of size kNumClasses.  Writes the number of
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // items on the corresponding freelist.  class_count may be NULL.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The storage of both parameters must be zero intialized.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // REQUIRES: Static::pageheap_lock is held.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void GetThreadStats(uint64_t* total_bytes, uint64_t* class_count);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the total thread cache size to new_size, recomputing the
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // individual thread cache sizes as necessary.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // REQUIRES: Static::pageheap lock is held.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void set_overall_thread_cache_size(size_t new_size);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static size_t overall_thread_cache_size() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return overall_thread_cache_size_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class FreeList {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void*    list_;       // Linked list of nodes
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _LP64
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On 64-bit hardware, manipulating 16-bit values may be slightly slow.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t length_;      // Current length.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t lowater_;     // Low water mark for list length.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t max_length_;  // Dynamic max list length based on usage.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tracks the number of times a deallocation has caused
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // length_ > max_length_.  After the kMaxOverages'th time, max_length_
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // shrinks and length_overages_ is reset to zero.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t length_overages_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we aren't using 64-bit pointers then pack these into less space.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16_t length_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16_t lowater_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16_t max_length_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16_t length_overages_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Init() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list_ = NULL;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_ = 0;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lowater_ = 0;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_length_ = 1;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_overages_ = 0;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return current length of list
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t length() const {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return length_;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return the maximum length of the list.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_length() const {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return max_length_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the maximum length of the list.  If 'new_max' > length(), the
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // client is responsible for removing objects from the list.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void set_max_length(size_t new_max) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_length_ = new_max;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Return the number of times that length() has gone over max_length().
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t length_overages() const {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return length_overages_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void set_length_overages(size_t new_count) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_overages_ = new_count;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Is list empty?
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool empty() const {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return list_ == NULL;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Low-water mark management
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int lowwatermark() const { return lowater_; }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void clear_lowwatermark() { lowater_ = length_; }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Push(void* ptr) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SLL_Push(&list_, ptr);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_++;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* Pop() {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT(list_ != NULL);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_--;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (length_ < lowater_) lowater_ = length_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SLL_Pop(&list_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* Next() {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SLL_Next(&list_);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void PushRange(int N, void *start, void *end) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SLL_PushRange(&list_, start, end);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_ += N;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void PopRange(int N, void **start, void **end) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SLL_PopRange(&list_, N, start, end);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT(length_ >= N);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length_ -= N;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (length_ < lowater_) lowater_ = length_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets and returns an object from the central cache, and, if possible,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // also adds some objects of that size class to this thread cache.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* FetchFromCentralCache(size_t cl, size_t byte_size);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releases some number of items from src.  Adjusts the list's max_length
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to eventually converge on num_objects_to_move(cl).
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ListTooLong(FreeList* src, size_t cl);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releases N items from this thread cache.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReleaseToCentralCache(FreeList* src, size_t cl, int N);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increase max_size_ by reducing unclaimed_cache_space_ or by
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reducing the max_size_ of some other thread.  In both cases,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the delta is kStealAmount.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IncreaseCacheLimit();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same as above but requires Static::pageheap_lock() is held.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IncreaseCacheLimitLocked();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If TLS is available, we also store a copy of the per-thread object
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in a __thread variable since __thread variables are faster to read
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than pthread_getspecific().  We still need pthread_setspecific()
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because __thread variables provide no way to run cleanup code when
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a thread is destroyed.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We also give a hint to the compiler to use the "initial exec" TLS
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // model.  This is faster than the default TLS model, at the cost that
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // you cannot dlopen this library.  (To see the difference, look at
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the CPU use of __tls_get_addr with and without this attribute.)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we don't really use dlopen in google code -- and using dlopen
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on a malloc replacement is asking for trouble in any case -- that's
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a good tradeoff for us.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_TLS
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static __thread ThreadCache* threadlocal_heap_
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifdef HAVE___ATTRIBUTE__
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   __attribute__ ((tls_model ("initial-exec")))
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Thread-specific key.  Initialization here is somewhat tricky
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because some Linux startup code invokes malloc() before it
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is in a good enough state to handle pthread_keycreate().
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Therefore, we use TSD keys only after tsd_inited is set to true.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Until then, we use a slow path to get the heap object.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool tsd_inited_;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static pthread_key_t heap_key_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Linked list of heap objects.  Protected by Static::pageheap_lock.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* thread_heaps_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int thread_heap_count_;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A pointer to one of the objects in thread_heaps_.  Represents
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the next ThreadCache from which a thread over its max_size_ should
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // steal memory limit.  Round-robin through all of the objects in
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread_heaps_.  Protected by Static::pageheap_lock.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* next_memory_steal_;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overall thread cache size.  Protected by Static::pageheap_lock.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static size_t overall_thread_cache_size_;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Global per-thread cache size.  Writes are protected by
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Static::pageheap_lock.  Reads are done without any locking, which should be
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fine as long as size_t can be written atomically and we don't place
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invariants between this variable and other pieces of state.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static volatile size_t per_thread_cache_size_;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Represents overall_thread_cache_size_ minus the sum of max_size_
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // across all ThreadCaches.  Protected by Static::pageheap_lock.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ssize_t unclaimed_cache_space_;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This class is laid out with the most frequently used fields
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first so that hot elements are placed on the same cache line.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t        size_;                  // Combined size of data
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t        max_size_;              // size_ > max_size_ --> Scavenge()
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We sample allocations, biased by the size of the allocation
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Sampler       sampler_;               // A sampler
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeList      list_[kNumClasses];     // Array indexed by size-class
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_t     tid_;                   // Which thread owns it
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool          in_setspecific_;        // In call to pthread_setspecific?
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a new heap. REQUIRES: Static::pageheap_lock is held.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadCache* NewHeap(pthread_t tid);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use only as pthread thread-specific destructor function.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DestroyThreadCache(void* ptr);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DeleteCache(ThreadCache* heap);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void RecomputePerThreadCacheSize();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that this class is cacheline-aligned. This is critical for
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // performance, as false sharing would negate many of the benefits
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of a per-thread cache.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} CACHELINE_ALIGNED;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allocator for thread heaps
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is logically part of the ThreadCache class, but MSVC, at
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// least, does not like using ThreadCache as a template argument
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the class is fully defined.  So we put it outside the class.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern PageHeapAllocator<ThreadCache> threadcache_allocator;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int ThreadCache::HeapsInUse() {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return threadcache_allocator.inuse();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool ThreadCache::SampleAllocation(size_t k) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sampler_.SampleAllocation(k);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void* ThreadCache::Allocate(size_t size, size_t cl) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT(size <= kMaxSize);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT(size == Static::sizemap()->ByteSizeForClass(cl));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeList* list = &list_[cl];
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list->empty()) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FetchFromCentralCache(cl, size);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ -= size;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return list->Pop();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void ThreadCache::Deallocate(void* ptr, size_t cl) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeList* list = &list_[cl];
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ += Static::sizemap()->ByteSizeForClass(cl);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t size_headroom = max_size_ - size_ - 1;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This catches back-to-back frees of allocs in the same size
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // class. A more comprehensive (and expensive) test would be to walk
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the entire freelist. But this might be enough to find some bugs.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT(ptr != list->Next());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list->Push(ptr);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t list_headroom =
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<ssize_t>(list->max_length()) - list->length();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There are two relatively uncommon things that require further work.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the common case we're done, and in that case we need a single branch
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because of the bitwise-or trick that follows.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((list_headroom | size_headroom) < 0) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (list_headroom < 0) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ListTooLong(list, cl);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_ >= max_size_) Scavenge();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline ThreadCache* ThreadCache::GetThreadHeap() {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_TLS
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // __thread is faster, but only when the kernel supports it
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (KernelSupportsTLS())
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return threadlocal_heap_;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<ThreadCache *>(
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      perftools_pthread_getspecific(heap_key_));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline ThreadCache* ThreadCache::GetCache() {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadCache* ptr = NULL;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tsd_inited_) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitModule();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = GetThreadHeap();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ptr == NULL) ptr = CreateCacheIfNecessary();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ptr;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In deletion paths, we do not try to create a thread-cache.  This is
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because we may be in the thread destruction code and may have
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already cleaned up the cache for this thread.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline ThreadCache* ThreadCache::GetCacheIfPresent() {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tsd_inited_) return NULL;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetThreadHeap();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tcmalloc
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // TCMALLOC_THREAD_CACHE_H_
404