Files
palemoon27/netwerk/cache2/CacheIOThread.cpp
T
roytam1 a291744c7a import changes from `dev' branch of rmottola/Arctic-Fox, and fix --enable-shared-js:
- Bug 1164338 - Move styles markers to be generated in DoProcessRestyles rather than when the Flush_Style queue is flushed. r=smaug,heycam (b8f62d25a)
- pointer style (c8d305ae5)
- Bug 1150783 - Use a special JitFrame to record when LazyLink stubs are on the stack. r=h4writer (999a5d8dd)
- Bug 1050500: Add SpiderMonkey API for reporting JavaScript entry points. r=shu (86b990918)
- Bug 1050500 followup: Annotate js.cpp "Exit()" method as "override". rs=ehsan (023d67749)
- Bug 1050500 - Add callee information to Javascript timeline markers. r=smaug (a5c078bc0)
- Bug 1050500 - add fields to ProfileTimelineStackFrame; r=smaug (7852af842)
- Bug 944164 - Move a bunch of file-related stuff onto an os.file object, creating aliases from the old names, r=jorendorff (a746506c0)
- Bug 1167860 - Make sure unboxed expandos are traced during minor GCs if the original unboxed object is converted to a native, r=terrence. (40552cef4)
- Bug 1168667 - Immediately convert unboxed objects to natives in PreventExtensions, and convert unboxed arrays as well as unboxed plain objects when required, r=jandem. (34e1c1267)
- Bug 1172150 - Remove bogus assert. (r=bz) (1138519fa)
- Bug 1165794 - Correctly handle getter/setters like methods everywhere. r=efaust (69a5cef61)
- Bug 1164778 - Make |super.prop| work inside heavyweight arrow functions. (r=shu) (2eaffe30d)
- Bug 1168750 - SharedStubs: (part2) Rename registers used by baseline stubs for use with shared stubs, r=jandem (db8080b41)
- pointer style (ae0ef8c24)
- fix spaces (0b5a0f55d)
- Bug 1168864 - Use mayResolve hook for addprop stubs. r=bhackett (14f89c938)
- Bug 1166678 - Optimize Array.prototype.slice in Ion, r=jandem. (978215128)
- Bug 1169611 - Rewrite IonBuilder::getPropTryConstant to not require a singleton result. r=bhackett (22c6137ea)
- Bug 1169611 part 2 - Unbox getprop/getelem inputs based on Baseline feedback. r=bhackett (dd3d50088)
- Bug 1148009; [webvr] Move gfx vr code to gfx/vr; r=jrmuizel (d3e0a12c7)
- Bug 1148009; [webvr] Split out gfxVROculus from gfxVR, refactor VRHMDManager; r=jrmuizel (393030b10)
- Bug 1148009; [webvr] Add Quaternion class to Moz2D; r=jrmuizel (85165c87c)
- Bug 1144674; Implement HAL support for ROTATION_VECTOR and GAME_ROTATION_VECTOR sensors; r=snorp (482211f00)
- Bug 1148009; Add support for Cardboard (and other rotation-sensor based VR) in Firefox for Android; r=jrmuizel (d3f78e657)
- Bug 1157835: Remove the MSVC_ENABLE_PGO flag from the build system. r=glandium (a5cc2bb8f)
- Bug 1170534 - Remove Visual Event Tracer. r=dougt (720c1bbc3)
- Bug 1169967 - Add a forward declare for MIRGenerator. r=nbp (81c6d0492)
- Bug 1154435 - [nsDumpUtil] Refine nsDumpUtils::OpenTempFile to make this function more flexible. r=dhylands (ca1e07244)
- Bug 1154435 - [nsGZFileWriter] Add one more mode for writing a GZFile (Create/Append). r=froydnj (d0cc62270)
- Bug 1165456 - Start converting name-resolution code to act upon kinds, not arities. r=shu (1162554f4)
- fix let (3ad7122ea)
- Bug 1165456 - Handle a bunch of simple known-arity kinds, by kind, when resolving nested function names. r=shu (82da03c43)
- Bug 1165456 - Perform name resolution on more nodes by kind, not arity. r=shu (214062efa)
- Bug 1165456 - Perform name resolution on additional nodes by kind. r=shu (c13147c9e)
- Bug 1165456 - More name-resolution conversion for arrays and (tagged) template literals. r=shu (f0cd596e8)
- Bug 1165456 - Extra bits of name-resolution conversion. r=shu (51d1045d7)
- Bug 1165456 - Final bits of name-resolution by kind. r=shu (57fca554e)
- Bug 1165456 - Remove dead code performing name resolution by arity. r=shu (b03db072a)
- pointer style (ab86d2ca7)
- Bug 1149510 - Initialize the MachineState with safe-bad pointers. r=jandem (7d35b51c9)
- Bug 1149510 - Don't try to read the result object when doing in-place debug mode bailout in a for-of loop. (r=jandem) (40c1e23a7)
- Bug 1156115 - Apply Bug 1135629 changes to the non-ion jit. r=nbp (332a21041)
- pointer style (fab908ba9)
- Bug 1155468 - Fix Register::GetName typedef issue with clang. r=jandem (5c7758d85)
- Bug 1176633 - Add more Operand constructors to the none backend. r=nbp (1557fe119)
- Bug 1160672 - Part 1/2 - Import VIXL 1.5-1.6. r=jbramley (c84218fec)
- Bug 1160672 - Part 2/2 - Add Mozilla VIXL modifications. r=dougc (1fd1c7443)
- Bug 1160672 - Follow-up - Add missing </p> tag. no_r=me (f783f0793)
- Bug 1160672 - Follow-up - Comment out unlanded header on a CLOSED TREE. no_r=me (f65a68eed)
- Bug 1166037 - Import ARM64 Baseline changes. r=djvj (5ddb53015)
- Bug 1166527 - Import ARM64 Architecture and Assembler. r=nbp (999380926)
- Bug 1077014 - MacroAssembler API. r=h4writer (78f470fa5)
- Bug 1077014 - ARM assembler support for for-effect atomics. r=mjrosenb (a78d1f786)
- Bug 1077014 - MacroAssembler API, for MIPS. r=rankov (d22cb063c)
- Bug 1077014 - optimize atomics for effect. r=h4writer (5a0bf089c)
- Bug 1170758 - Make non-debug GraphSpewer constructor explicit. r=nbp (2b7c1a90b)
- Bug 1176631 - Predeclare TempAllocator for non-ion platforms. r=nbp (73cd914a7)
2020-09-25 22:09:15 +08:00

354 lines
8.5 KiB
C++

/* 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/. */
#include "CacheIOThread.h"
#include "CacheFileIOManager.h"
#include "nsIRunnable.h"
#include "nsISupportsImpl.h"
#include "nsPrintfCString.h"
#include "nsThreadUtils.h"
#include "mozilla/IOInterposer.h"
namespace mozilla {
namespace net {
CacheIOThread* CacheIOThread::sSelf = nullptr;
NS_IMPL_ISUPPORTS(CacheIOThread, nsIThreadObserver)
CacheIOThread::CacheIOThread()
: mMonitor("CacheIOThread")
, mThread(nullptr)
, mLowestLevelWaiting(LAST_LEVEL)
, mCurrentlyExecutingLevel(0)
, mHasXPCOMEvents(false)
, mRerunCurrentEvent(false)
, mShutdown(false)
, mInsideLoop(true)
{
sSelf = this;
}
CacheIOThread::~CacheIOThread()
{
sSelf = nullptr;
#ifdef DEBUG
for (uint32_t level = 0; level < LAST_LEVEL; ++level) {
MOZ_ASSERT(!mEventQueue[level].Length());
}
#endif
}
nsresult CacheIOThread::Init()
{
mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, 128 * 1024);
if (!mThread)
return NS_ERROR_FAILURE;
return NS_OK;
}
nsresult CacheIOThread::Dispatch(nsIRunnable* aRunnable, uint32_t aLevel)
{
NS_ENSURE_ARG(aLevel < LAST_LEVEL);
// Runnable is always expected to be non-null, hard null-check bellow.
MOZ_ASSERT(aRunnable);
MonitorAutoLock lock(mMonitor);
if (mShutdown && (PR_GetCurrentThread() != mThread))
return NS_ERROR_UNEXPECTED;
return DispatchInternal(aRunnable, aLevel);
}
nsresult CacheIOThread::DispatchAfterPendingOpens(nsIRunnable* aRunnable)
{
// Runnable is always expected to be non-null, hard null-check bellow.
MOZ_ASSERT(aRunnable);
MonitorAutoLock lock(mMonitor);
if (mShutdown && (PR_GetCurrentThread() != mThread))
return NS_ERROR_UNEXPECTED;
// Move everything from later executed OPEN level to the OPEN_PRIORITY level
// where we post the (eviction) runnable.
mEventQueue[OPEN_PRIORITY].AppendElements(mEventQueue[OPEN]);
mEventQueue[OPEN].Clear();
return DispatchInternal(aRunnable, OPEN_PRIORITY);
}
nsresult CacheIOThread::DispatchInternal(nsIRunnable* aRunnable, uint32_t aLevel)
{
if (NS_WARN_IF(!aRunnable))
return NS_ERROR_NULL_POINTER;
mMonitor.AssertCurrentThreadOwns();
mEventQueue[aLevel].AppendElement(aRunnable);
if (mLowestLevelWaiting > aLevel)
mLowestLevelWaiting = aLevel;
mMonitor.NotifyAll();
return NS_OK;
}
bool CacheIOThread::IsCurrentThread()
{
return mThread == PR_GetCurrentThread();
}
bool CacheIOThread::YieldInternal()
{
if (!IsCurrentThread()) {
NS_WARNING("Trying to yield to priority events on non-cache2 I/O thread? "
"You probably do something wrong.");
return false;
}
if (mCurrentlyExecutingLevel == XPCOM_LEVEL) {
// Doesn't make any sense, since this handler is the one
// that would be executed as the next one.
return false;
}
if (!EventsPending(mCurrentlyExecutingLevel))
return false;
mRerunCurrentEvent = true;
return true;
}
nsresult CacheIOThread::Shutdown()
{
{
MonitorAutoLock lock(mMonitor);
mShutdown = true;
mMonitor.NotifyAll();
}
PR_JoinThread(mThread);
mThread = nullptr;
return NS_OK;
}
already_AddRefed<nsIEventTarget> CacheIOThread::Target()
{
nsCOMPtr<nsIEventTarget> target;
target = mXPCOMThread;
if (!target && mThread)
{
MonitorAutoLock lock(mMonitor);
if (!mXPCOMThread)
lock.Wait();
target = mXPCOMThread;
}
return target.forget();
}
// static
void CacheIOThread::ThreadFunc(void* aClosure)
{
PR_SetCurrentThreadName("Cache2 I/O");
mozilla::IOInterposer::RegisterCurrentThread();
CacheIOThread* thread = static_cast<CacheIOThread*>(aClosure);
thread->ThreadFunc();
mozilla::IOInterposer::UnregisterCurrentThread();
}
void CacheIOThread::ThreadFunc()
{
nsCOMPtr<nsIThreadInternal> threadInternal;
{
MonitorAutoLock lock(mMonitor);
// This creates nsThread for this PRThread
nsCOMPtr<nsIThread> xpcomThread = NS_GetCurrentThread();
threadInternal = do_QueryInterface(xpcomThread);
if (threadInternal)
threadInternal->SetObserver(this);
mXPCOMThread.swap(xpcomThread);
lock.NotifyAll();
do {
loopStart:
// Reset the lowest level now, so that we can detect a new event on
// a lower level (i.e. higher priority) has been scheduled while
// executing any previously scheduled event.
mLowestLevelWaiting = LAST_LEVEL;
// Process xpcom events first
while (mHasXPCOMEvents) {
mHasXPCOMEvents = false;
mCurrentlyExecutingLevel = XPCOM_LEVEL;
MonitorAutoUnlock unlock(mMonitor);
bool processedEvent;
nsresult rv;
do {
rv = mXPCOMThread->ProcessNextEvent(false, &processedEvent);
} while (NS_SUCCEEDED(rv) && processedEvent);
}
uint32_t level;
for (level = 0; level < LAST_LEVEL; ++level) {
if (!mEventQueue[level].Length()) {
// no events on this level, go to the next level
continue;
}
LoopOneLevel(level);
// Go to the first (lowest) level again
goto loopStart;
}
if (EventsPending())
continue;
if (mShutdown)
break;
lock.Wait(PR_INTERVAL_NO_TIMEOUT);
if (EventsPending())
continue;
} while (true);
MOZ_ASSERT(!EventsPending());
// This is for correct assertion on XPCOM events dispatch.
mInsideLoop = false;
} // lock
if (threadInternal)
threadInternal->SetObserver(nullptr);
}
static const char* const sLevelTraceName[] = {
"net::cache::io::level(0)",
"net::cache::io::level(1)",
"net::cache::io::level(2)",
"net::cache::io::level(3)",
"net::cache::io::level(4)",
"net::cache::io::level(5)",
"net::cache::io::level(6)",
"net::cache::io::level(7)",
"net::cache::io::level(8)",
"net::cache::io::level(9)",
"net::cache::io::level(10)",
"net::cache::io::level(11)",
"net::cache::io::level(12)"
};
void CacheIOThread::LoopOneLevel(uint32_t aLevel)
{
nsTArray<nsCOMPtr<nsIRunnable> > events;
events.SwapElements(mEventQueue[aLevel]);
uint32_t length = events.Length();
mCurrentlyExecutingLevel = aLevel;
bool returnEvents = false;
uint32_t index;
{
MonitorAutoUnlock unlock(mMonitor);
for (index = 0; index < length; ++index) {
if (EventsPending(aLevel)) {
// Somebody scheduled a new event on a lower level, break and harry
// to execute it! Don't forget to return what we haven't exec.
returnEvents = true;
break;
}
// Drop any previous flagging, only an event on the current level may set
// this flag.
mRerunCurrentEvent = false;
events[index]->Run();
if (mRerunCurrentEvent) {
// The event handler yields to higher priority events and wants to rerun.
returnEvents = true;
break;
}
// Release outside the lock.
events[index] = nullptr;
}
}
if (returnEvents)
mEventQueue[aLevel].InsertElementsAt(0, events.Elements() + index, length - index);
}
bool CacheIOThread::EventsPending(uint32_t aLastLevel)
{
return mLowestLevelWaiting < aLastLevel || mHasXPCOMEvents;
}
NS_IMETHODIMP CacheIOThread::OnDispatchedEvent(nsIThreadInternal *thread)
{
MonitorAutoLock lock(mMonitor);
mHasXPCOMEvents = true;
MOZ_ASSERT(mInsideLoop);
lock.Notify();
return NS_OK;
}
NS_IMETHODIMP CacheIOThread::OnProcessNextEvent(nsIThreadInternal *thread, bool mayWait, uint32_t recursionDepth)
{
return NS_OK;
}
NS_IMETHODIMP CacheIOThread::AfterProcessNextEvent(nsIThreadInternal *thread, uint32_t recursionDepth,
bool eventWasProcessed)
{
return NS_OK;
}
// Memory reporting
size_t CacheIOThread::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
MonitorAutoLock lock(const_cast<CacheIOThread*>(this)->mMonitor);
size_t n = 0;
n += mallocSizeOf(mThread);
for (uint32_t level = 0; level < LAST_LEVEL; ++level) {
n += mEventQueue[level].SizeOfExcludingThis(mallocSizeOf);
// Events referenced by the queues are arbitrary objects we cannot be sure
// are reported elsewhere as well as probably not implementing nsISizeOf
// interface. Deliberatly omitting them from reporting here.
}
return n;
}
size_t CacheIOThread::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // namespace net
} // namespace mozilla