Implement GDB pretty-printers for folly::fibers
authorAndrii Grynenko <andrii@fb.com>
Fri, 1 Apr 2016 00:57:14 +0000 (17:57 -0700)
committerFacebook Github Bot 5 <facebook-github-bot-5-bot@fb.com>
Fri, 1 Apr 2016 01:05:19 +0000 (18:05 -0700)
Summary:This adds basic print functions for FiberManager, Fiber and FiberManager map.
It also adds a global list of fibers to FiberManager. Fibers are only removed from that list on Fiber object destruction, so it shouldn't have any perf impact.

Inspired by tao/server/scripts/fiber_bt.gdb

FiberManager map example:
  (gdb) print_folly_fiber_manager_map
    Global FiberManager map has 2 entries.
      (folly::EventBase*)0x7fffffffdb60 -> (folly::fibers::FiberManager*)0x7ffff5b58480
      (folly::EventBase*)0x7fffffffd930 -> (folly::fibers::FiberManager*)0x7ffff5b58300

FiberManager example:
  (gdb) print_folly_fiber_manager &manager
    (folly::fibers::FiberManager*)0x7fffffffdbe0

    Fibers active: 3
    Fibers allocated: 3
    Fibers pool size: 0
    Active fiber: (folly::fibers::Fiber*)(nil)
    Current fiber: (folly::fibers::Fiber*)(nil)

    Active fibers:
      (folly::fibers::Fiber*)0x7ffff5b5b000   State: Awaiting
      (folly::fibers::Fiber*)0x7ffff5b5b300   State: Awaiting
      (folly::fibers::Fiber*)0x7ffff5b5b600   State: Awaiting

Fiber example: P56244621

Reviewed By: yfeldblum

Differential Revision: D3119616

fb-gh-sync-id: defa27b84aafbd4333b2ca301f07c226f0386f44
fbshipit-source-id: defa27b84aafbd4333b2ca301f07c226f0386f44

folly/experimental/fibers/Fiber.cpp
folly/experimental/fibers/Fiber.h
folly/experimental/fibers/FiberManager.h
folly/experimental/fibers/scripts/utils.gdb [new file with mode: 0644]

index de0e30b8d9dfb42489975724b9bf28d480b0b062..56b0f3ebecc6e88631b6ff3d497407fc77a615d0 100644 (file)
@@ -85,6 +85,8 @@ Fiber::Fiber(FiberManager& fiberManager) :
   auto limit = fiberManager_.stackAllocator_.allocate(size);
 
   fcontext_ = makeContext(limit, size, &Fiber::fiberFuncHelper);
+
+  fiberManager_.allFibers_.push_back(*this);
 }
 
 void Fiber::init(bool recordStackUsed) {
index f29f511571b53e0fa17fcd13df2a58ac8bf143be..39a05fca23c29500f092d98834d3e290a8c832ae 100644 (file)
@@ -181,6 +181,7 @@ class Fiber {
 
   folly::IntrusiveListHook listHook_; /**< list hook for different FiberManager
                                            queues */
+  folly::IntrusiveListHook globalListHook_; /**< list hook for global list */
   pid_t threadId_{0};
 };
 
index 588f8ee402743a22ce5fe8e77153b8a6a258d7f6..d9dfef2b9fa714e47c226a6e67f60291cff237f3 100644 (file)
@@ -341,6 +341,8 @@ class FiberManager : public ::folly::Executor {
   intptr_t deactivateFiber(Fiber* fiber);
 
   typedef folly::IntrusiveList<Fiber, &Fiber::listHook_> FiberTailQueue;
+  typedef folly::IntrusiveList<Fiber, &Fiber::globalListHook_>
+      GlobalFiberTailQueue;
 
   Fiber* activeFiber_{nullptr}; /**< active fiber, nullptr on main context */
   /**
@@ -354,6 +356,8 @@ class FiberManager : public ::folly::Executor {
                                        execution */
   FiberTailQueue fibersPool_;   /**< pool of unitialized Fiber objects */
 
+  GlobalFiberTailQueue allFibers_; /**< list of all Fiber objects owned */
+
   size_t fibersAllocated_{0};   /**< total number of fibers allocated */
   size_t fibersPoolSize_{0};    /**< total number of fibers in the free pool */
   size_t fibersActive_{0};      /**< number of running or blocked fibers */
diff --git a/folly/experimental/fibers/scripts/utils.gdb b/folly/experimental/fibers/scripts/utils.gdb
new file mode 100644 (file)
index 0000000..ada27fe
--- /dev/null
@@ -0,0 +1,99 @@
+# Print given Fiber state
+# arg0 folly::fibers::Fiber*
+define print_folly_fiber_state
+  set $fiber = (folly::fibers::Fiber*)$arg0
+  if $fiber->state_ == folly::fibers::Fiber::INVALID
+    printf "Invalid"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::NOT_STARTED
+    printf "Not started"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::READY_TO_RUN
+    printf "Ready to run"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::RUNNING
+    printf "Running"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::AWAITING
+    printf "Awaiting"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::AWAITING_IMMEDIATE
+    printf "Awaiting immediate"
+  end
+  if $fiber->state_ == folly::fibers::Fiber::YIELDED
+    printf "Yielded"
+  end
+end
+
+# Print given Fiber
+# arg0 folly::fibers::Fiber*
+define print_folly_fiber
+  set $fiber = (folly::fibers::Fiber*)$arg0
+  printf "  (folly::fibers::Fiber*)%p\n\n", $fiber
+
+  printf "  State: "
+  print_folly_fiber_state $fiber
+  printf "\n"
+
+  if $fiber->state_ != folly::fibers::Fiber::INVALID && \
+     $fiber->state_ != folly::fibers::Fiber::NOT_STARTED && \
+     $fiber->state_ != folly::fibers::Fiber::RUNNING
+    printf "  Backtrace:\n"
+    set $frameptr = ((uint64_t*)$fiber->fcontext_.context_)[6]
+    set $k = 0
+    while $frameptr != 0
+      printf "    #%d at %p in ", $k, *((void**)($frameptr+8))
+      set $k = $k + 1
+      info symbol *((void**)($frameptr+8))
+      set $frameptr = *((void**)($frameptr))
+    end
+  end
+end
+
+# Print given FiberManager
+# arg0 folly::fibers::FiberManager*
+define print_folly_fiber_manager
+  set $fiberManager = (folly::fibers::FiberManager*)$arg0
+
+  printf "  (folly::fibers::FiberManager*)%p\n\n", $fiberManager
+  printf "  Fibers active: %d\n", $fiberManager->fibersActive_
+  printf "  Fibers allocated: %d\n", $fiberManager->fibersAllocated_
+  printf "  Fibers pool size: %d\n", $fiberManager->fibersPoolSize_
+  printf "  Active fiber: (folly::fibers::Fiber*)%p\n", \
+         $fiberManager->activeFiber_
+  printf "  Current fiber: (folly::fibers::Fiber*)%p\n", \
+         $fiberManager->currentFiber_
+
+  set $all_fibers = &($fiberManager->allFibers_.data_.root_plus_size_.m_header)
+  set $fiber_hook = $all_fibers->next_
+  printf "\n  Active fibers:\n"
+  while $fiber_hook != $all_fibers
+    set $fiber = (folly::fibers::Fiber*) \
+        ((int64_t)$fiber_hook - \
+         (int64_t)&folly::fibers::Fiber::globalListHook_)
+    if $fiber->state_ != folly::fibers::Fiber::INVALID
+      printf "    (folly::fibers::Fiber*)%p   State: ", $fiber
+      print_folly_fiber_state $fiber
+      printf "\n"
+    end
+    set $fiber_hook = $fiber_hook->next_
+  end
+end
+
+# Print global FiberManager map
+define print_folly_fiber_manager_map
+  set $global_cache=*(('folly::fibers::(anonymous namespace)::GlobalCache'**) \
+      &'folly::fibers::(anonymous namespace)::GlobalCache::instance()::ret')
+  printf "  Global FiberManager map has %d entries.\n", \
+         $global_cache->map_->_M_h->_M_element_count
+
+  set $item = $global_cache->map_->_M_h->_M_before_begin._M_nxt
+  while $item != 0
+    set $evb = ((folly::EventBase**)$item)[1]
+    set $fiberManager = ((folly::fibers::FiberManager**)$item)[2]
+    printf "    (folly::EventBase*)%p -> (folly::fibers::FiberManager*)%p\n", \
+           $evb, $fiberManager
+
+    set $item = $item->_M_nxt
+  end
+end