MCPcopy Create free account
hub / github.com/beefytech/Beef / DoAllocWithArena

Function DoAllocWithArena

BeefRT/gperftools/src/base/low_level_alloc.cc:434–497  ·  view source on GitHub ↗

allocates and returns a block of size bytes, to be freed with Free() L < arena->mu

Source from the content-addressed store, hash-verified

432// allocates and returns a block of size bytes, to be freed with Free()
433// L < arena->mu
434static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
435 void *result = 0;
436 if (request != 0) {
437 AllocList *s; // will point to region that satisfies request
438 ArenaLock section(arena);
439 ArenaInit(arena);
440 // round up with header
441 size_t req_rnd = RoundUp(request + sizeof (s->header), arena->roundup);
442 for (;;) { // loop until we find a suitable region
443 // find the minimum levels that a block of this size must have
444 int i = LLA_SkiplistLevels(req_rnd, arena->min_size, false) - 1;
445 if (i < arena->freelist.levels) { // potential blocks exist
446 AllocList *before = &arena->freelist; // predecessor of s
447 while ((s = Next(i, before, arena)) != 0 && s->header.size < req_rnd) {
448 before = s;
449 }
450 if (s != 0) { // we found a region
451 break;
452 }
453 }
454 // we unlock before mmap() both because mmap() may call a callback hook,
455 // and because it may be slow.
456 arena->mu.Unlock();
457 // mmap generous 64K chunks to decrease
458 // the chances/impact of fragmentation:
459 size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16);
460 void *new_pages;
461 if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
462 new_pages = MallocHook::UnhookedMMap(0, new_pages_size,
463 PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
464 } else {
465 new_pages = mmap(0, new_pages_size,
466 PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
467 }
468 RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
469 arena->mu.Lock();
470 s = reinterpret_cast<AllocList *>(new_pages);
471 s->header.size = new_pages_size;
472 // Pretend the block is allocated; call AddToFreelist() to free it.
473 s->header.magic = Magic(kMagicAllocated, &s->header);
474 s->header.arena = arena;
475 AddToFreelist(&s->levels, arena); // insert new region into free list
476 }
477 AllocList *prev[kMaxLevel];
478 LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
479 // s points to the first free region that's big enough
480 if (req_rnd + arena->min_size <= s->header.size) { // big enough to split
481 AllocList *n = reinterpret_cast<AllocList *>
482 (req_rnd + reinterpret_cast<char *>(s));
483 n->header.size = s->header.size - req_rnd;
484 n->header.magic = Magic(kMagicAllocated, &n->header);
485 n->header.arena = arena;
486 s->header.size = req_rnd;
487 AddToFreelist(&n->levels, arena);
488 }
489 s->header.magic = Magic(kMagicAllocated, &s->header);
490 RAW_CHECK(s->header.arena == arena, "");
491 arena->allocation_count++;

Callers 2

AllocMethod · 0.70
AllocWithArenaMethod · 0.70

Calls 11

ArenaInitFunction · 0.70
RoundUpFunction · 0.70
LLA_SkiplistLevelsFunction · 0.70
NextFunction · 0.70
MagicFunction · 0.70
AddToFreelistFunction · 0.70
LLA_SkiplistDeleteFunction · 0.70
mmapFunction · 0.50
UnlockMethod · 0.45
LockMethod · 0.45
LeaveMethod · 0.45

Tested by

no test coverage detected