unsigned char* borrow(size_t size) { std::lock_guard<folly::SpinLock> lg(lock_); assert(storage_); auto as = allocSize(size); if (as != allocSize_ || freeList_.empty()) { return nullptr; } auto p = freeList_.back().first; if (!freeList_.back().second) { PCHECK(0 == ::mprotect(p, pagesize(), PROT_NONE)); } freeList_.pop_back(); /* We allocate minimum number of pages required, plus a guard page. Since we use this for stack storage, requested allocation is aligned at the top of the allocated pages, while the guard page is at the bottom. -- increasing addresses --> Guard page Normal pages |xxxxxxxxxx|..........|..........| <- allocSize_ -------------------> p -^ <- size --------> limit -^ */ auto limit = p + allocSize_ - size; assert(limit >= p + pagesize()); return limit; }
void TypeManager::createUnion(string* name, vector<pair<string, SType*>> structure) { SUserPtr& item = usrMap[*name]; if (item.get() || !structure.size()) return; auto type = structure[0].second; auto size = allocSize(type); for (auto item : structure) { auto tsize = allocSize(item.second); if (tsize > size) { size = tsize; type = item.second; } } vector<Type*> elements; elements.push_back(*type); item = smart_unionTy(StructType::create(elements, *name), structure, size); }
explicit StackCache(size_t stackSize) : allocSize_(allocSize(stackSize)) { auto p = ::mmap( nullptr, allocSize_ * kNumGuarded, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); PCHECK(p != (void*)(-1)); storage_ = reinterpret_cast<unsigned char*>(p); /* Protect the bottommost page of every stack allocation */ for (size_t i = 0; i < kNumGuarded; ++i) { auto allocBegin = storage_ + allocSize_ * i; freeList_.emplace_back(allocBegin, /* protected= */ false); } }
bool giveBack(unsigned char* limit, size_t size) { std::lock_guard<folly::SpinLock> lg(lock_); assert(storage_); auto as = allocSize(size); auto p = limit + size - as; if (p < storage_ || p >= storage_ + allocSize_ * kNumGuarded) { /* not mine */ return false; } assert(as == allocSize_); assert((p - storage_) % allocSize_ == 0); freeList_.emplace_back(p, /* protected= */ true); return true; }