Commit fa78ffbc authored by Andre Pinto's avatar Andre Pinto Committed by Alecs King

Instrument fibers execution

Summary: Add option to setup fibers' instrumentation.

Test Plan: Unit tests

Reviewed By: andrii@fb.com

Subscribers: folly-diffs@, yfeldblum, chalfant

FB internal diff: D1991638

Tasks: 6347990

Signature: t1:1991638:1429144487:3c3586b9943b4cc6bbef0297e48b8bffaf586f0d
parent 2355eee3
...@@ -80,6 +80,7 @@ nobase_follyinclude_HEADERS = \ ...@@ -80,6 +80,7 @@ nobase_follyinclude_HEADERS = \
experimental/fibers/BoostContextCompatibility.h \ experimental/fibers/BoostContextCompatibility.h \
experimental/fibers/EventBaseLoopController.h \ experimental/fibers/EventBaseLoopController.h \
experimental/fibers/EventBaseLoopController-inl.h \ experimental/fibers/EventBaseLoopController-inl.h \
experimental/fibers/ExecutionObserver.h \
experimental/fibers/Fiber.h \ experimental/fibers/Fiber.h \
experimental/fibers/Fiber-inl.h \ experimental/fibers/Fiber-inl.h \
experimental/fibers/FiberManager.h \ experimental/fibers/FiberManager.h \
......
/*
* Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
namespace folly { namespace fibers {
/**
* Observes the execution of a task.
*/
class ExecutionObserver {
public:
virtual ~ExecutionObserver() { }
/**
* Called when a task is about to start executing.
*/
virtual void starting() noexcept = 0;
/**
* Called just after a task stops executing.
*/
virtual void stopped() noexcept = 0;
};
}} // namespace folly::fibers
...@@ -47,6 +47,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -47,6 +47,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
assert(fiber->state_ == Fiber::NOT_STARTED || assert(fiber->state_ == Fiber::NOT_STARTED ||
fiber->state_ == Fiber::READY_TO_RUN); fiber->state_ == Fiber::READY_TO_RUN);
currentFiber_ = fiber; currentFiber_ = fiber;
if (observer_) {
observer_->starting();
}
while (fiber->state_ == Fiber::NOT_STARTED || while (fiber->state_ == Fiber::NOT_STARTED ||
fiber->state_ == Fiber::READY_TO_RUN) { fiber->state_ == Fiber::READY_TO_RUN) {
...@@ -66,6 +69,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -66,6 +69,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
if (fiber->state_ == Fiber::AWAITING) { if (fiber->state_ == Fiber::AWAITING) {
awaitFunc_(*fiber); awaitFunc_(*fiber);
awaitFunc_ = nullptr; awaitFunc_ = nullptr;
if (observer_) {
observer_->stopped();
}
currentFiber_ = nullptr; currentFiber_ = nullptr;
} else if (fiber->state_ == Fiber::INVALID) { } else if (fiber->state_ == Fiber::INVALID) {
assert(fibersActive_ > 0); assert(fibersActive_ > 0);
...@@ -84,6 +90,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -84,6 +90,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
fiber->finallyFunc_ = nullptr; fiber->finallyFunc_ = nullptr;
} }
// Make sure LocalData is not accessible from its destructor // Make sure LocalData is not accessible from its destructor
if (observer_) {
observer_->stopped();
}
currentFiber_ = nullptr; currentFiber_ = nullptr;
fiber->localData_.reset(); fiber->localData_.reset();
...@@ -96,6 +105,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -96,6 +105,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
--fibersAllocated_; --fibersAllocated_;
} }
} else if (fiber->state_ == Fiber::YIELDED) { } else if (fiber->state_ == Fiber::YIELDED) {
if (observer_) {
observer_->stopped();
}
currentFiber_ = nullptr; currentFiber_ = nullptr;
fiber->state_ = Fiber::READY_TO_RUN; fiber->state_ = Fiber::READY_TO_RUN;
yieldedFibers_.push_back(*fiber); yieldedFibers_.push_back(*fiber);
......
...@@ -109,4 +109,8 @@ void FiberManager::remoteReadyInsert(Fiber* fiber) { ...@@ -109,4 +109,8 @@ void FiberManager::remoteReadyInsert(Fiber* fiber) {
} }
} }
void FiberManager::setObserver(ExecutionObserver* observer) {
observer_ = observer;
}
}} }}
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <folly/futures/Try.h> #include <folly/futures/Try.h>
#include <folly/experimental/fibers/BoostContextCompatibility.h> #include <folly/experimental/fibers/BoostContextCompatibility.h>
#include <folly/experimental/fibers/ExecutionObserver.h>
#include <folly/experimental/fibers/Fiber.h> #include <folly/experimental/fibers/Fiber.h>
#include <folly/experimental/fibers/traits.h> #include <folly/experimental/fibers/traits.h>
...@@ -234,6 +235,14 @@ class FiberManager { ...@@ -234,6 +235,14 @@ class FiberManager {
*/ */
void yield(); void yield();
/**
* Setup fibers execution observation/instrumentation. Fiber locals are
* available to observer.
*
* @param observer Fiber's execution observer.
*/
void setObserver(ExecutionObserver* observer);
static FiberManager& getFiberManager(); static FiberManager& getFiberManager();
static FiberManager* getFiberManagerUnsafe(); static FiberManager* getFiberManagerUnsafe();
...@@ -349,6 +358,11 @@ class FiberManager { ...@@ -349,6 +358,11 @@ class FiberManager {
*/ */
std::function<void()> immediateFunc_; std::function<void()> immediateFunc_;
/**
* Fiber's execution observer.
*/
ExecutionObserver* observer_{nullptr};
ExceptionCallback exceptionCallback_; /**< task exception callback */ ExceptionCallback exceptionCallback_; /**< task exception callback */
folly::AtomicLinkedList<Fiber, &Fiber::nextRemoteReady_> remoteReadyQueue_; folly::AtomicLinkedList<Fiber, &Fiber::nextRemoteReady_> remoteReadyQueue_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment