Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68158
  • 博文数量: 19
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 239
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-08 15:35
文章分类

全部博文(19)

文章存档

2012年(2)

2011年(17)

我的朋友

分类: LINUX

2011-10-08 16:05:27

下面我们来看看FetchFromSpansPopulate两个函数。FetchFromSpans首先判断CentralFreeListnonempty_列表中是否有可用的span如果没有则返回NULL,否则取nonempty_第一个span,然后将span中切出一个obj,并调整span->objects指正,如果span已经被切割干净,那么把这个spannonempty列表中分离出来放入empty列表。

 

void* CentralFreeList::FetchFromSpans() {

  if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL;

  Span* span = nonempty_.next;

 

  ASSERT(span->objects != NULL);

  span->refcount++;

  void* result = span->objects;

  span->objects = *(reinterpret_cast(result));

  if (span->objects == NULL) {

    // Move to empty list

    tcmalloc::DLL_Remove(span);

    tcmalloc::DLL_Prepend(&empty_, span);

    Event(span, 'E', 0);

  }

  counter_--;

  return result;

}

Populate函数通过Static::pageheapNew出需要的空间,首先通过Static::sizemap()->class_to_pagessize转换为npages。然后通过函数Static::pageheap()->Newpageheap获取npages个页面,然后如果span获取成功,那么将他插入pagemap_这颗raidx tree。如果spanNULL那么代表分配失败返回,返回前先获取前面释放的CentralFreeList的锁。如果分配成功,那么将这个span中的page插入pagemap_cache_这个二元组。最后通过一个while循环将整个span拆分成一个个的obj并通过*tail = ptr;     tail = reinterpret_cast(ptr);建立上图的链表。

 

void CentralFreeList::Populate() {

  // Release central list lock while operating on pageheap

  lock_.Unlock();

  const size_t npages = Static::sizemap()->class_to_pages(size_class_);

 

  Span* span;

  {

    SpinLockHolder h(Static::pageheap_lock());

    span = Static::pageheap()->New(npages);

    if (span) Static::pageheap()->RegisterSizeClass(span, size_class_);

  }

  if (span == NULL) {

    MESSAGE("tcmalloc: allocation failed", npages << kPageShift);

    lock_.Lock();

    return;

  }

  ASSERT(span->length == npages);

  // Cache sizeclass info eagerly.  Locking is not necessary.

  // (Instead of being eager, we could just replace any stale info

  // about this span, but that seems to be no better in practice.)

  for (int i = 0; i < npages; i++) {

    Static::pageheap()->CacheSizeClass(span->start + i, size_class_);

  }

 

  // Split the block into pieces and add to the free-list

  // TODO: coloring of objects to avoid cache conflicts?

  void** tail = &span->objects;

  char* ptr = reinterpret_cast(span->start << kPageShift);

  char* limit = ptr + (npages << kPageShift);

  const size_t size = Static::sizemap()->ByteSizeForClass(size_class_);

  int num = 0;

  while (ptr + size <= limit) {

    *tail = ptr;

    tail = reinterpret_cast(ptr);

    ptr += size;

    num++;

  }

  ASSERT(ptr <= limit);

  *tail = NULL;

  span->refcount = 0; // No sub-object in use yet

 

  // Add span to list of non-empty spans

  lock_.Lock();

  tcmalloc::DLL_Prepend(&nonempty_, span);

  counter_ += num;

}

我们在看一下函数= Static::pageheap()->New,其中kMaxPages256

Span* PageHeap::New(Length n) {

  ASSERT(Check());

  ASSERT(n > 0);

 

  // Find first size >= n that has a non-empty list

  for (Length s = n; s < kMaxPages; s++) {//sizenpagefreelist开始查找,如果不符合那么查找比n大的下一个freelist

    Span* ll = &free_[s].normal;// 首先获取normal list,同一个sizespan分为两类,normalreturnnormal就是一切正常的spanreturn代表内存已经返回给系统的span

    // If we're lucky, ll is non-empty, meaning it has a suitable span.

    if (!DLL_IsEmpty(ll)) {//如果normal list为空

      ASSERT(ll->next->location == Span::ON_NORMAL_FREELIST);//通过spanlocation来判断span是怪哉freelist上,如果是,那么用Carve吧这个span切出。如果在normal队列里面分配失败,那么从returned队列里面切出来。

      return Carve(ll->next, n);

    }

    // Alternatively, maybe there's a usable returned span.

    ll = &free_[s].returned;

    if (!DLL_IsEmpty(ll)) {

      ASSERT(ll->next->location == Span::ON_RETURNED_FREELIST);

      return Carve(ll->next, n);

    }

    // Still no luck, so keep looking in larger classes.

  }

如果以上都没有成功,那么我们的祈求AllocLarge从系统分配了

  Span* result = AllocLarge(n);

  if (result != NULL) return result;

 

  // Grow the heap and try again

//继续尝试,首先增长Heap,尝试再次分配。

  if (!GrowHeap(n)) {

    ASSERT(Check());

    return NULL;

  }

 

  return AllocLarge(n);

}

阅读(862) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~