分类: LINUX
2011-10-08 16:00:41
Static::InitStaticVars()最后将调用Sampler::InitStatics()函数,此函数主要初始化sampler的采样间隔之类的。到此Static::InitStaticVars介绍完毕,我们返回ThreadCache::InitModule(),接着static::InitStaticVars开始初始化threadcache_allocator,threadcache_allocator的定义是PageHeapAllocator
完成InitModule的解释,我们返回函数inline ThreadCache* ThreadCache::GetCache,由于ptr为null,那么调用: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_列表进行遍历,判断本thread的cache是否已经创建
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,用来标识当当一个thread的thread_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.New,threadcache_allocator是一个PageHeapAllocator