Tcmalloc源码简单分析(10)

Static::InitStaticVars()最后将调用Sampler::InitStatics()函数,此函数主要初始化sampler的采样间隔之类的。到此Static::InitStaticVars介绍完毕,我们返回ThreadCache::InitModule(),接着static::InitStaticVars开始初始化threadcache_allocatorthreadcache_allocator的定义是PageHeapAllocator<ThreadCache>,他的初始化函数也是PageHeapAllocator::init,此函数在上面已经解释。初始化结束后,设置phinited1防止多次初始化。

完成InitModule的解释,我们返回函数inline ThreadCache* ThreadCache::GetCache,由于ptrnull,那么调用:CreateCacheIfNecessary创建一个threadcache。代码分析如下

ThreadCache* ThreadCache::CreateCacheIfNecessary() {

  // Initialize per-thread data if necessary

  ThreadCache* heap = NULL;

  {

    SpinLockHolder h(Static::pageheap_lock());

//首先获取整个pageheap的锁

    // Early on in glibc's life, we cannot even call pthread_self()

    pthread_t me;

    if (!tsd_inited_) {

      memset(&me, 0, sizeof(me));//由于尚未初始化不能callll pthread_self,因此将me置为0

    } else {

      me = pthread_self();//如果已经初始化完毕,那么直接调用pthread_self获得tid

    }

 

    // This may be a recursive malloc call from pthread_setspecific()

    // In that case, the heap for this thread has already been created

    // and added to the linked list.  So we search for that first.

    for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) {

      if (h->tid_ == me) {

        heap = h;

        break;

      }

    }

//通过对thread_heaps_列表进行遍历,判断本threadcache是否已经创建

    if (heap == NULL) heap = NewHeap(me);

  }

//如果没有找到,那么调用NewHeap分配一个新的heap

//下面部分没怎么看懂,应该是对pthread_setspecific调用进行特殊处理,防止对malloc的递归call方面。

  // We call pthread_setspecific() outside the lock because it may

  // call malloc() recursively.  We check for the recursive call using

  // the "in_setspecific_" flag so that we can avoid calling

  // pthread_setspecific() if we are already inside pthread_setspecific().

  if (!heap->in_setspecific_ && tsd_inited_) {

    heap->in_setspecific_ = true;

    perftools_pthread_setspecific(heap_key_, heap);

#ifdef HAVE_TLS

    // Also keep a copy in __thread for faster retrieval

    threadlocal_heap_ = heap;

#endif

    heap->in_setspecific_ = false;

  }

  return heap;

}

下面我们分析一下NewHeap函数,NewHeap函数通过threadcache_allocator.New分配一个threadCache,并调用ThreadCache.init进行初始化,并将新生成的heap加入thread_heaps_列表,这里有一个特殊的变量next_memory_steal,用来标识当当一个threadthread_Cache超过max_size_时从哪个cache偷内存,next_memory_steal采用Round-robin方式在各个thread cache中转移。

ThreadCache* ThreadCache::NewHeap(pthread_t tid) {

  // Create the heap and add it to the linked list

  ThreadCache *heap = threadcache_allocator.New();

  heap->Init(tid);

  heap->next_ = thread_heaps_;

  heap->prev_ = NULL;

  if (thread_heaps_ != NULL) {

    thread_heaps_->prev_ = heap;

  } else {

    // This is the only thread heap at the momment.

    ASSERT(next_memory_steal_ == NULL);

    next_memory_steal_ = heap;

  }

  thread_heaps_ = heap;

  thread_heap_count_++;

  return heap;

}

NewHeap中关键的函数是threadcache_allocator.Newthreadcache_allocator是一个PageHeapAllocator<ThreadCache>的对象,他的New函数在前面我们已经分析过了,主要是从threadcache_allocatorfree_list里面切出一个ThreadCache对象并赋值给heap



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值