/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NSPRINTERPOSER_H_ #define NSPRINTERPOSER_H_ #ifdef MOZ_ENABLE_PROFILER_SPS #include "IOInterposer.h" #include "mozilla/Atomics.h" #include "mozilla/TimeStamp.h" #include "prio.h" namespace mozilla { /** * This class provides main thread I/O interposing for NSPR file reads, writes, * and fsyncs. Most methods must be called from the main thread, except for: * Enable * Read * Write * FSync */ class NSPRInterposer MOZ_FINAL : public IOInterposerModule { public: static IOInterposerModule* GetInstance(IOInterposeObserver* aObserver, IOInterposeObserver::Operation aOpsToInterpose); /** * This function must be called from the main thread, and furthermore * it must be called when no other threads are executing in Read, Write, * or FSync. Effectivly this restricts us to calling it only after all other * threads have been stopped during shutdown. */ static void ClearInstance(); ~NSPRInterposer(); void Enable(bool aEnable); private: NSPRInterposer(); bool Init(IOInterposeObserver* aObserver, IOInterposeObserver::Operation aOpsToInterpose); static int32_t PR_CALLBACK Read(PRFileDesc* aFd, void* aBuf, int32_t aAmt); static int32_t PR_CALLBACK Write(PRFileDesc* aFd, const void* aBuf, int32_t aAmt); static PRStatus PR_CALLBACK FSync(PRFileDesc* aFd); static StaticAutoPtr sSingleton; friend class NSPRAutoTimer; IOInterposeObserver* mObserver; PRIOMethods* mFileIOMethods; Atomic mEnabled; PRReadFN mOrigReadFn; PRWriteFN mOrigWriteFn; PRFsyncFN mOrigFSyncFn; }; /** * RAII class for timing the duration of an NSPR I/O call and reporting the * result to the IOInterposeObserver. */ class NSPRAutoTimer { public: NSPRAutoTimer(IOInterposeObserver::Operation aOp) :mOp(aOp), mShouldObserve(NSPRInterposer::sSingleton->mEnabled && NS_IsMainThread()) { if (mShouldObserve) { mStart = mozilla::TimeStamp::Now(); } } ~NSPRAutoTimer() { if (mShouldObserve) { double duration = (mozilla::TimeStamp::Now() - mStart).ToMilliseconds(); NSPRInterposer::sSingleton->mObserver->Observe(mOp, duration, sModuleInfo); } } private: IOInterposeObserver::Operation mOp; bool mShouldObserve; mozilla::TimeStamp mStart; static const char* sModuleInfo; }; } // namespace mozilla #endif // MOZ_ENABLE_PROFILER_SPS #endif // NSPRINTERPOSER_H_