int CentralFreeList::RemoveRange(void **start, void **end, int N) { ASSERT(N > 0); lock_.Lock(); if (N == Static::sizemap()->num_objects_to_move(size_class_) && used_slots_ > 0) { int slot = --used_slots_; ASSERT(slot >= 0); TCEntry *entry = &tc_slots_[slot]; *start = entry->head; *end = entry->tail; lock_.Unlock(); return N; } int result = 0; void* head = NULL; void* tail = NULL; // TODO: Prefetch multiple TCEntries? tail = FetchFromSpansSafe(); if (tail != NULL) { SLL_SetNext(tail, NULL); head = tail; result = 1; while (result < N) { void *t = FetchFromSpans(); if (!t) break; SLL_Push(&head, t); result++; } } lock_.Unlock(); *start = head; *end = tail; return result; }
int CCentralCacheMgr::AllocSpan(int clz) { struct SSpanInfo & spanInfo = m_sSpanList[clz]; PRINT("clz:%d, %s", clz, spanInfo.c_string()); size_t nodeSize = CSizeMap::GetInstance().class_to_size(clz); size_t wantPages = CSizeMap::GetInstance().class_to_pages(clz); size_t allocSize = wantPages << FT_PAGE_BIT; size_t allocNodes = allocSize / nodeSize; void * allocAddr = (void *)CPageMgr::GetInstance().AllocPages(wantPages); PRINT("alloc new spaninfo, %p", allocAddr); struct SSpanNode * spanNode = s_spannode_allocator.AllocNode(); { spanNode->span_addr = allocAddr; spanNode->span_size = allocNodes; spanNode->free_size = allocNodes; RB_NODE_INIT(spanNode->span_node); RB_NODE_INIT(spanNode->alloc_node); size_t start = (size_t)spanNode->span_addr; size_t end = start + allocSize; size_t curr = start; size_t next = curr + nodeSize; while (next < end) { SLL_SetNext((void *)curr, (void *)next); next += nodeSize; curr += nodeSize; } SLL_SetNext((void *)curr, NULL); SLL_SetNext(&spanNode->object_list, spanNode->span_addr); PRINT("%s", spanNode->c_string()); } InsertSpan(clz, spanNode); PRINT("End of allocspan, %s", spanInfo.c_string()); AddAllocPages(wantPages); PRINT("Now, allocate out pages:%zd, bytes:%zd", AllocOutPages(), AllocOutBytes()); }
int CCentralCacheMgr::FetchFromSpan(int clz, int N, void ** start, void ** end) { struct SSpanInfo & spanInfo = m_sSpanList[clz]; PRINT("clazz:%d, wantsize:%d, %s", clz, N, spanInfo.c_string()); if (spanInfo.free_object < N) { AllocSpan(clz); } void *s = NULL, *e = NULL; int needCount = N; bool firstTimeAlloc = true; int allocsize = 0; SSpanNode * spanNode = NULL; rb_node * node = rb_first(&spanInfo.alloc_tree); while (node != NULL) { spanNode = AllocTreeGetObject(node); allocsize = needCount; PRINT("%s", spanNode->c_string()); PRINT("N:%d, needsize:%d", N, needCount); if (spanNode->free_size < allocsize) { allocsize = spanNode->free_size; } SLL_PopRange(&spanNode->object_list, allocsize, &s, &e); spanNode->free_size -= allocsize; needCount -= allocsize; PRINT("%s", spanNode->c_string()); PRINT("N:%d, needsize:%d", N, needCount); if (spanNode->free_size == 0) { RbRemove(&spanInfo.alloc_tree, spanNode, &CCentralCacheMgr::AllocTreeNode); } if (firstTimeAlloc) { firstTimeAlloc = false; *start = s; *end = e; } else { SLL_SetNext(*end, s); *end = e; } if (needCount == 0) { break; } node = rb_first(&spanInfo.alloc_tree); } int allocNum = N - needCount; spanInfo.free_object -= allocNum; PRINT("allocnum:%d, wantsize:%d, start:%p, end:%p", allocNum, N, *start, *end); return allocNum; }