Skip to content

Commit

Permalink
mempool: Fix refill_page_buffer() on out-of-memory
Browse files Browse the repository at this point in the history
Building OSv with debug memory allocator enabled:

  $ make -j mode=debug conf-preempt=0 conf-debug_memory=1

Causes the guest to enter a busy loop right after JVM starts up:

  $ ./scripts/run.py -d

  [...]

  OpenJDK 64-Bit Server VM warning: Can't detect initial thread stack location - find_vma failed

GDB explains:

  #0  0x00000000003b5c54 in
boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::member_hook_traits<memory::page_range,
boost::intrusive::set_member_hook<boost::intrusive::none,
boost::intrusive::none, boost::intrusive::none, boost::intrusive::none>,
&memory::page_range::member_hook>, memory::addr_cmp, unsigned long, true>
>::private_erase (this=0x1d2f8c8 <memory::free_page_ranges+8>, b=..., e=...,
n=@0x3b40e9: 6179885759521391432) at
../../external/misc.bin/usr/include/boost/intrusive/rbtree.hpp:1417
  #1  0x00000000003b552e in
boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::member_hook_traits<memory::page_range,
boost::intrusive::set_member_hook<boost::intrusive::none,
boost::intrusive::none, boost::intrusive::none, boost::intrusive::none>,
&memory::page_range::member_hook>, memory::addr_cmp, unsigned long, true>
>::erase<memory::page_range, memory::addr_cmp>(memory::page_range const&,
memory::addr_cmp,
boost::intrusive::detail::enable_if_c<!boost::intrusive::detail::is_convertible<memory::addr_cmp,
boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::member_hook_traits<memory::page_range,
boost::intrusive::set_member_hook<boost::intrusive::none,
boost::intrusive::none, boost::intrusive::none, boost::intrusive::none>,
&memory::page_range::member_hook>, memory::addr_cmp, unsigned long, true> >,
true> >::value, void>::type*) (this=0x1d2f8c0 <memory::free_page_ranges>,
key=..., comp=...) at
../../external/misc.bin/usr/include/boost/intrusive/rbtree.hpp:878
  #2  0x00000000003b4c4e in
boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::member_hook_traits<memory::page_range,
boost::intrusive::set_member_hook<boost::intrusive::none,
boost::intrusive::none, boost::intrusive::none, boost::intrusive::none>,
&memory::page_range::member_hook>, memory::addr_cmp, unsigned long, true>
>::erase (this=0x1d2f8c0 <memory::free_page_ranges>, value=...) at
../../external/misc.bin/usr/include/boost/intrusive/rbtree.hpp:856
  #3  0x00000000003b4145 in
boost::intrusive::set_impl<boost::intrusive::setopt<boost::intrusive::detail::member_hook_traits<memory::page_range,
boost::intrusive::set_member_hook<boost::intrusive::none,
boost::intrusive::none, boost::intrusive::none, boost::intrusive::none>,
&memory::page_range::member_hook>, memory::addr_cmp, unsigned long, true>
>::erase (this=0x1d2f8c0 <memory::free_page_ranges>, value=...) at
../../external/misc.bin/usr/include/boost/intrusive/set.hpp:601
  #4  0x00000000003b0130 in memory::refill_page_buffer () at ../../core/mempool.cc:487
  #5  0x00000000003b05f8 in memory::untracked_alloc_page () at ../../core/mempool.cc:569
  #6  0x00000000003b0631 in memory::alloc_page () at ../../core/mempool.cc:577
  #7  0x0000000000367a7c in mmu::populate::small_page (this=0x2000001fd460, ptep=..., offset=0) at ../../core/mmu.cc:456
  #8  0x0000000000365b00 in mmu::page_range_operation::operate_page
(this=0x2000001fd460, huge=false, addr=0xffffe0004ec9b000, offset=0) at
../../core/mmu.cc:438
  #9  0x0000000000365790 in mmu::page_range_operation::operate
(this=0x2000001fd460, start=0xffffe0004ec9b000, size=4096) at
../../core/mmu.cc:387
  #10 0x0000000000366148 in mmu::vpopulate (addr=0xffffe0004ec9b000, size=4096) at ../../core/mmu.cc:657
  #11 0x00000000003b0d8d in dbg::malloc (size=16) at ../../core/mempool.cc:818
  #12 0x00000000003b0f32 in malloc (size=16) at ../../core/mempool.cc:854

Fix the problem by checking if free_page_ranges is empty in
refill_page_buffer(). This fixes the busy loop issue and shows what's
really happening:

  OpenJDK 64-Bit Server VM warning: Can't detect initial thread stack location - find_vma failed
  alloc_page(): out of memory
  Aborted
  • Loading branch information
Pekka Enberg committed Aug 15, 2013
1 parent 9502e85 commit 2149839
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion core/mempool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,10 @@ static void refill_page_buffer()
auto limit = (pbuf.max + 1) / 2;

while (pbuf.nr < limit) {
auto p = &*free_page_ranges.begin();
auto it = free_page_ranges.begin();
if (it == free_page_ranges.end())
break;
auto p = &*it;
auto size = std::min(p->size, (limit - pbuf.nr) * page_size);
p->size -= size;
void* pages = static_cast<void*>(p) + p->size;
Expand Down

0 comments on commit 2149839

Please sign in to comment.