proxygen
folly::fibers::StackCache Class Reference

Public Member Functions

 StackCache (size_t stackSize)
 
unsigned char * borrow (size_t size)
 
bool giveBack (unsigned char *limit, size_t size)
 
 ~StackCache ()
 

Static Public Member Functions

static bool isProtected (intptr_t addr)
 

Static Private Member Functions

static size_t pagesize ()
 
static size_t allocSize (size_t size)
 
static folly::Synchronized< std::unordered_set< intptr_t > > & protectedPages ()
 

Private Attributes

folly::SpinLock lock_
 
unsigned char * storage_ {nullptr}
 
size_t allocSize_ {0}
 
std::vector< std::pair< unsigned char *, bool > > freeList_
 

Detailed Description

A cache for kNumGuarded stacks of a given size

Thread safe.

Definition at line 60 of file GuardPageAllocator.cpp.

Constructor & Destructor Documentation

folly::fibers::StackCache::StackCache ( size_t  stackSize)
inlineexplicit

Definition at line 62 of file GuardPageAllocator.cpp.

References allocSize_, freeList_, i, folly::fibers::kNumGuarded, and storage_.

62  : allocSize_(allocSize(stackSize)) {
63  auto p = ::mmap(
64  nullptr,
66  PROT_READ | PROT_WRITE,
67  MAP_PRIVATE | MAP_ANONYMOUS,
68  -1,
69  0);
70  PCHECK(p != (void*)(-1));
71  storage_ = reinterpret_cast<unsigned char*>(p);
72 
73  /* Protect the bottommost page of every stack allocation */
74  for (size_t i = 0; i < kNumGuarded; ++i) {
75  auto allocBegin = storage_ + allocSize_ * i;
76  freeList_.emplace_back(allocBegin, /* protected= */ false);
77  }
78  }
std::vector< std::pair< unsigned char *, bool > > freeList_
constexpr size_t kNumGuarded
static size_t allocSize(size_t size)
folly::fibers::StackCache::~StackCache ( )
inline

Definition at line 132 of file GuardPageAllocator.cpp.

References allocSize_, freeList_, protectedPages(), and storage_.

132  {
133  assert(storage_);
134  protectedPages().withWLock([&](auto& pages) {
135  for (const auto& item : freeList_) {
136  pages.erase(reinterpret_cast<intptr_t>(item.first));
137  }
138  });
139  PCHECK(0 == ::munmap(storage_, allocSize_ * kNumGuarded));
140  }
std::vector< std::pair< unsigned char *, bool > > freeList_
constexpr size_t kNumGuarded
static folly::Synchronized< std::unordered_set< intptr_t > > & protectedPages()

Member Function Documentation

static size_t folly::fibers::StackCache::allocSize ( size_t  size)
inlinestaticprivate

Definition at line 171 of file GuardPageAllocator.cpp.

References pagesize().

Referenced by borrow(), and giveBack().

171  {
172  return pagesize() * ((size + pagesize() - 1) / pagesize() + 1);
173  }
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
unsigned char* folly::fibers::StackCache::borrow ( size_t  size)
inline

Definition at line 80 of file GuardPageAllocator.cpp.

References allocSize(), allocSize_, folly::gen::as(), freeList_, lock_, pagesize(), protectedPages(), folly::size(), and storage_.

80  {
81  std::lock_guard<folly::SpinLock> lg(lock_);
82 
83  assert(storage_);
84 
85  auto as = allocSize(size);
86  if (as != allocSize_ || freeList_.empty()) {
87  return nullptr;
88  }
89 
90  auto p = freeList_.back().first;
91  if (!freeList_.back().second) {
92  PCHECK(0 == ::mprotect(p, pagesize(), PROT_NONE));
93  protectedPages().wlock()->insert(reinterpret_cast<intptr_t>(p));
94  }
95  freeList_.pop_back();
96 
97  /* We allocate minimum number of pages required, plus a guard page.
98  Since we use this for stack storage, requested allocation is aligned
99  at the top of the allocated pages, while the guard page is at the bottom.
100 
101  -- increasing addresses -->
102  Guard page Normal pages
103  |xxxxxxxxxx|..........|..........|
104  <- allocSize_ ------------------->
105  p -^ <- size -------->
106  limit -^
107  */
108  auto limit = p + allocSize_ - size;
109  assert(limit >= p + pagesize());
110  return limit;
111  }
std::vector< std::pair< unsigned char *, bool > > freeList_
static folly::Synchronized< std::unordered_set< intptr_t > > & protectedPages()
static size_t allocSize(size_t size)
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
Collect as()
Definition: Base.h:811
bool folly::fibers::StackCache::giveBack ( unsigned char *  limit,
size_t  size 
)
inline

Definition at line 113 of file GuardPageAllocator.cpp.

References allocSize(), allocSize_, folly::gen::as(), freeList_, folly::fibers::kNumGuarded, lock_, and storage_.

113  {
114  std::lock_guard<folly::SpinLock> lg(lock_);
115 
116  assert(storage_);
117 
118  auto as = allocSize(size);
119  if (std::less_equal<void*>{}(limit, storage_) ||
120  std::less_equal<void*>{}(storage_ + allocSize_ * kNumGuarded, limit)) {
121  /* not mine */
122  return false;
123  }
124 
125  auto p = limit + size - as;
126  assert(as == allocSize_);
127  assert((p - storage_) % allocSize_ == 0);
128  freeList_.emplace_back(p, /* protected= */ true);
129  return true;
130  }
std::vector< std::pair< unsigned char *, bool > > freeList_
constexpr size_t kNumGuarded
static size_t allocSize(size_t size)
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
Collect as()
Definition: Base.h:811
static bool folly::fibers::StackCache::isProtected ( intptr_t  addr)
inlinestatic

Definition at line 142 of file GuardPageAllocator.cpp.

References pagesize(), and protectedPages().

Referenced by protectedPages().

142  {
143  // Use a read lock for reading.
144  return protectedPages().withRLock([&](auto const& pages) {
145  for (const auto& page : pages) {
146  intptr_t pageEnd = intptr_t(page + pagesize());
147  if (page <= addr && addr < pageEnd) {
148  return true;
149  }
150  }
151  return false;
152  });
153  }
static folly::Synchronized< std::unordered_set< intptr_t > > & protectedPages()
ThreadPoolListHook * addr
static size_t folly::fibers::StackCache::pagesize ( )
inlinestaticprivate

Definition at line 165 of file GuardPageAllocator.cpp.

Referenced by allocSize(), borrow(), and isProtected().

165  {
166  static const size_t pagesize = size_t(sysconf(_SC_PAGESIZE));
167  return pagesize;
168  }
static folly::Synchronized<std::unordered_set<intptr_t> >& folly::fibers::StackCache::protectedPages ( )
inlinestaticprivate

Definition at line 175 of file GuardPageAllocator.cpp.

References folly::call_once(), deadlock::info(), and isProtected().

Referenced by borrow(), isProtected(), and ~StackCache().

175  {
176  static auto instance =
178  return *instance;
179  }

Member Data Documentation

size_t folly::fibers::StackCache::allocSize_ {0}
private

Definition at line 158 of file GuardPageAllocator.cpp.

Referenced by borrow(), giveBack(), StackCache(), and ~StackCache().

std::vector<std::pair<unsigned char*, bool> > folly::fibers::StackCache::freeList_
private

LIFO free list. Each pair contains stack pointer and protected flag.

Definition at line 163 of file GuardPageAllocator.cpp.

Referenced by borrow(), giveBack(), StackCache(), and ~StackCache().

folly::SpinLock folly::fibers::StackCache::lock_
private
unsigned char* folly::fibers::StackCache::storage_ {nullptr}
private

Definition at line 157 of file GuardPageAllocator.cpp.

Referenced by borrow(), giveBack(), StackCache(), and ~StackCache().


The documentation for this class was generated from the following file: