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;
  }
Exemple #2
0
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;
  }