Fix incorrect usages of folly::Synchronized
[folly.git] / folly / fibers / FiberManager.cpp
index 99280e82e7f7f1e5d7194b0232a7466be7974608..3c01ce17245fa0e033a2f41606d257ab81d68d83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "FiberManager.h"
+#include "FiberManagerInternal.h"
 
 #include <signal.h>
 
@@ -25,6 +25,7 @@
 #include <folly/fibers/Fiber.h>
 #include <folly/fibers/LoopController.h>
 
+#include <folly/ConstexprMath.h>
 #include <folly/SingletonThreadLocal.h>
 #include <folly/portability/SysSyscall.h>
 #include <folly/portability/Unistd.h>
 
 #include <dlfcn.h>
 
-static void __asan_enter_fiber_weak(
+static void __sanitizer_start_switch_fiber_weak(
+    void** fake_stack_save,
     void const* fiber_stack_base,
     size_t fiber_stack_extent)
-    __attribute__((__weakref__("__asan_enter_fiber")));
-static void __asan_exit_fiber_weak()
-    __attribute__((__weakref__("__asan_exit_fiber")));
+    __attribute__((__weakref__("__sanitizer_start_switch_fiber")));
+static void __sanitizer_finish_switch_fiber_weak(
+    void* fake_stack_save,
+    void const** old_stack_base,
+    size_t* old_stack_extent)
+    __attribute__((__weakref__("__sanitizer_finish_switch_fiber")));
 static void __asan_unpoison_memory_region_weak(
     void const /* nolint */ volatile* addr,
     size_t size) __attribute__((__weakref__("__asan_unpoison_memory_region")));
 
-typedef void (*AsanEnterFiberFuncPtr)(void const*, size_t);
-typedef void (*AsanExitFiberFuncPtr)();
+typedef void (*AsanStartSwitchStackFuncPtr)(void**, void const*, size_t);
+typedef void (*AsanFinishSwitchStackFuncPtr)(void*, void const**, size_t*);
 typedef void (*AsanUnpoisonMemoryRegionFuncPtr)(
     void const /* nolint */ volatile*,
     size_t);
@@ -52,8 +57,8 @@ typedef void (*AsanUnpoisonMemoryRegionFuncPtr)(
 namespace folly {
 namespace fibers {
 
-static AsanEnterFiberFuncPtr getEnterFiberFunc();
-static AsanExitFiberFuncPtr getExitFiberFunc();
+static AsanStartSwitchStackFuncPtr getStartSwitchStackFunc();
+static AsanFinishSwitchStackFuncPtr getFinishSwitchStackFunc();
 static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc();
 }
 }
@@ -122,6 +127,7 @@ Fiber* FiberManager::getFiber() {
   ++fiberId_;
   bool recordStack = (options_.recordStackEvery != 0) &&
       (fiberId_ % options_.recordStackEvery == 0);
+  fiber->init(recordStack);
   return fiber;
 }
 
@@ -154,6 +160,10 @@ void FiberManager::setObserver(ExecutionObserver* observer) {
   observer_ = observer;
 }
 
+ExecutionObserver* FiberManager::getObserver() {
+  return observer_;
+}
+
 void FiberManager::setPreemptRunner(InlineFunctionRunner* preemptRunner) {
   preemptRunner_ = preemptRunner;
 }
@@ -182,33 +192,48 @@ void FiberManager::FibersPoolResizer::operator()() {
 
 #ifdef FOLLY_SANITIZE_ADDRESS
 
-void FiberManager::registerFiberActivationWithAsan(Fiber* fiber) {
-  auto context = &fiber->fcontext_;
-  void* top = context->stackBase();
-  void* bottom = context->stackLimit();
-  size_t extent = static_cast<char*>(top) - static_cast<char*>(bottom);
-
+void FiberManager::registerStartSwitchStackWithAsan(
+    void** saveFakeStack,
+    const void* stackBottom,
+    size_t stackSize) {
   // Check if we can find a fiber enter function and call it if we find one
-  static AsanEnterFiberFuncPtr fn = getEnterFiberFunc();
+  static AsanStartSwitchStackFuncPtr fn = getStartSwitchStackFunc();
   if (fn == nullptr) {
     LOG(FATAL) << "The version of ASAN in use doesn't support fibers";
   } else {
-    fn(bottom, extent);
+    fn(saveFakeStack, stackBottom, stackSize);
   }
 }
 
-void FiberManager::registerFiberDeactivationWithAsan(Fiber* fiber) {
-  (void)fiber; // currently unused
-
+void FiberManager::registerFinishSwitchStackWithAsan(
+    void* saveFakeStack,
+    const void** saveStackBottom,
+    size_t* saveStackSize) {
   // Check if we can find a fiber exit function and call it if we find one
-  static AsanExitFiberFuncPtr fn = getExitFiberFunc();
+  static AsanFinishSwitchStackFuncPtr fn = getFinishSwitchStackFunc();
   if (fn == nullptr) {
     LOG(FATAL) << "The version of ASAN in use doesn't support fibers";
   } else {
-    fn();
+    fn(saveFakeStack, saveStackBottom, saveStackSize);
   }
 }
 
+void FiberManager::freeFakeStack(void* fakeStack) {
+  static AsanStartSwitchStackFuncPtr fnStart = getStartSwitchStackFunc();
+  static AsanFinishSwitchStackFuncPtr fnFinish = getFinishSwitchStackFunc();
+  if (fnStart == nullptr || fnFinish == nullptr) {
+    LOG(FATAL) << "The version of ASAN in use doesn't support fibers";
+  }
+
+  void* saveFakeStack;
+  const void* stackBottom;
+  size_t stackSize;
+  fnStart(&saveFakeStack, nullptr, 0);
+  fnFinish(fakeStack, &stackBottom, &stackSize);
+  fnStart(nullptr, stackBottom, stackSize);
+  fnFinish(saveFakeStack, nullptr, nullptr);
+}
+
 void FiberManager::unpoisonFiberStack(const Fiber* fiber) {
   auto stack = fiber->getStack();
 
@@ -221,17 +246,18 @@ void FiberManager::unpoisonFiberStack(const Fiber* fiber) {
   }
 }
 
-static AsanEnterFiberFuncPtr getEnterFiberFunc() {
-  AsanEnterFiberFuncPtr fn{nullptr};
+static AsanStartSwitchStackFuncPtr getStartSwitchStackFunc() {
+  AsanStartSwitchStackFuncPtr fn{nullptr};
 
   // Check whether weak reference points to statically linked enter function
-  if (nullptr != (fn = &::__asan_enter_fiber_weak)) {
+  if (nullptr != (fn = &::__sanitizer_start_switch_fiber_weak)) {
     return fn;
   }
 
   // Check whether we can find a dynamically linked enter function
   if (nullptr !=
-      (fn = (AsanEnterFiberFuncPtr)dlsym(RTLD_DEFAULT, "__asan_enter_fiber"))) {
+      (fn = (AsanStartSwitchStackFuncPtr)dlsym(
+           RTLD_DEFAULT, "__sanitizer_start_switch_fiber"))) {
     return fn;
   }
 
@@ -239,17 +265,18 @@ static AsanEnterFiberFuncPtr getEnterFiberFunc() {
   return nullptr;
 }
 
-static AsanExitFiberFuncPtr getExitFiberFunc() {
-  AsanExitFiberFuncPtr fn{nullptr};
+static AsanFinishSwitchStackFuncPtr getFinishSwitchStackFunc() {
+  AsanFinishSwitchStackFuncPtr fn{nullptr};
 
   // Check whether weak reference points to statically linked exit function
-  if (nullptr != (fn = &::__asan_exit_fiber_weak)) {
+  if (nullptr != (fn = &::__sanitizer_finish_switch_fiber_weak)) {
     return fn;
   }
 
   // Check whether we can find a dynamically linked exit function
   if (nullptr !=
-      (fn = (AsanExitFiberFuncPtr)dlsym(RTLD_DEFAULT, "__asan_exit_fiber"))) {
+      (fn = (AsanFinishSwitchStackFuncPtr)dlsym(
+           RTLD_DEFAULT, "__sanitizer_finish_switch_fiber"))) {
     return fn;
   }
 
@@ -266,8 +293,9 @@ static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc() {
   }
 
   // Check whether we can find a dynamically linked unpoison function
-  if (nullptr != (fn = (AsanUnpoisonMemoryRegionFuncPtr)dlsym(
-                      RTLD_DEFAULT, "__asan_unpoison_memory_region"))) {
+  if (nullptr !=
+      (fn = (AsanUnpoisonMemoryRegionFuncPtr)dlsym(
+           RTLD_DEFAULT, "__asan_unpoison_memory_region"))) {
     return fn;
   }
 
@@ -311,7 +339,7 @@ class ScopedAlternateSignalStack {
       return;
     }
 
-    stack_ = folly::make_unique<AltStackBuffer>();
+    stack_ = std::make_unique<AltStackBuffer>();
 
     setAlternateStack(stack_->data(), stack_->size());
   }
@@ -326,7 +354,7 @@ class ScopedAlternateSignalStack {
   using AltStackBuffer = std::array<char, kAltStackSize>;
   std::unique_ptr<AltStackBuffer> stack_;
 };
-}
+} // namespace
 
 void FiberManager::registerAlternateSignalStack() {
   static folly::SingletonThreadLocal<ScopedAlternateSignalStack> singleton;
@@ -335,5 +363,5 @@ void FiberManager::registerAlternateSignalStack() {
   alternateSignalStackRegistered_ = true;
 }
 #endif
-}
-}
+} // namespace fibers
+} // namespace folly