Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/threads/nsThreadUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsThreadUtils.h"
8
#include "mozilla/Attributes.h"
9
#include "mozilla/Likely.h"
10
#include "mozilla/TimeStamp.h"
11
#include "LeakRefPtr.h"
12
#include "nsComponentManagerUtils.h"
13
#include "nsExceptionHandler.h"
14
#include "nsITimer.h"
15
16
#ifdef MOZILLA_INTERNAL_API
17
# include "nsThreadManager.h"
18
#else
19
# include "nsXPCOMCIDInternal.h"
20
# include "nsIThreadManager.h"
21
# include "nsServiceManagerUtils.h"
22
#endif
23
24
#ifdef XP_WIN
25
#include <windows.h>
26
#elif defined(XP_MACOSX)
27
#include <sys/resource.h>
28
#endif
29
30
using namespace mozilla;
31
32
#ifndef XPCOM_GLUE_AVOID_NSPR
33
34
NS_IMPL_ISUPPORTS(IdlePeriod, nsIIdlePeriod)
35
36
NS_IMETHODIMP
37
IdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline)
38
0
{
39
0
  *aIdleDeadline = TimeStamp();
40
0
  return NS_OK;
41
0
}
42
43
// NS_IMPL_NAMED_* relies on the mName field, which is not present on
44
// release or beta. Instead, fall back to using "Runnable" for all
45
// runnables.
46
#ifndef MOZ_COLLECTING_RUNNABLE_TELEMETRY
47
NS_IMPL_ISUPPORTS(Runnable, nsIRunnable)
48
#else
49
NS_IMPL_NAMED_ADDREF(Runnable, mName)
50
NS_IMPL_NAMED_RELEASE(Runnable, mName)
51
NS_IMPL_QUERY_INTERFACE(Runnable, nsIRunnable, nsINamed)
52
#endif
53
54
NS_IMETHODIMP
55
Runnable::Run()
56
0
{
57
0
  // Do nothing
58
0
  return NS_OK;
59
0
}
60
61
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
62
NS_IMETHODIMP
63
Runnable::GetName(nsACString& aName)
64
0
{
65
0
  if (mName) {
66
0
    aName.AssignASCII(mName);
67
0
  } else {
68
0
    aName.Truncate();
69
0
  }
70
0
  return NS_OK;
71
0
}
72
#endif
73
74
NS_IMPL_ISUPPORTS_INHERITED(CancelableRunnable, Runnable,
75
                            nsICancelableRunnable)
76
77
nsresult
78
CancelableRunnable::Cancel()
79
0
{
80
0
  // Do nothing
81
0
  return NS_OK;
82
0
}
83
84
NS_IMPL_ISUPPORTS_INHERITED(IdleRunnable, CancelableRunnable,
85
                            nsIIdleRunnable)
86
87
NS_IMPL_ISUPPORTS_INHERITED(PrioritizableRunnable, Runnable,
88
                            nsIRunnablePriority)
89
90
PrioritizableRunnable::PrioritizableRunnable(already_AddRefed<nsIRunnable>&& aRunnable,
91
                                             uint32_t aPriority)
92
 // Real runnable name is managed by overridding the GetName function.
93
 : Runnable("PrioritizableRunnable")
94
 , mRunnable(std::move(aRunnable))
95
 , mPriority(aPriority)
96
0
{
97
#if DEBUG
98
  nsCOMPtr<nsIRunnablePriority> runnablePrio = do_QueryInterface(mRunnable);
99
  MOZ_ASSERT(!runnablePrio);
100
#endif
101
}
102
103
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
104
NS_IMETHODIMP
105
PrioritizableRunnable::GetName(nsACString& aName)
106
0
{
107
0
  // Try to get a name from the underlying runnable.
108
0
  nsCOMPtr<nsINamed> named = do_QueryInterface(mRunnable);
109
0
  if (named) {
110
0
    named->GetName(aName);
111
0
  }
112
0
  return NS_OK;
113
0
}
114
#endif
115
116
NS_IMETHODIMP
117
PrioritizableRunnable::Run()
118
0
{
119
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
120
0
  return mRunnable->Run();
121
0
}
122
123
NS_IMETHODIMP
124
PrioritizableRunnable::GetPriority(uint32_t* aPriority)
125
0
{
126
0
  *aPriority = mPriority;
127
0
  return NS_OK;
128
0
}
129
130
#endif  // XPCOM_GLUE_AVOID_NSPR
131
132
//-----------------------------------------------------------------------------
133
134
nsresult
135
NS_NewNamedThread(const nsACString& aName,
136
                  nsIThread** aResult,
137
                  nsIRunnable* aEvent,
138
                  uint32_t aStackSize)
139
13
{
140
13
  nsCOMPtr<nsIThread> thread;
141
13
#ifdef MOZILLA_INTERNAL_API
142
13
  nsresult rv =
143
13
    nsThreadManager::get().nsThreadManager::NewNamedThread(aName, aStackSize,
144
13
                                                           getter_AddRefs(thread));
145
#else
146
  nsresult rv;
147
  nsCOMPtr<nsIThreadManager> mgr =
148
    do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
149
  if (NS_WARN_IF(NS_FAILED(rv))) {
150
    return rv;
151
  }
152
153
  rv = mgr->NewNamedThread(aName, aStackSize, getter_AddRefs(thread));
154
#endif
155
13
  if (NS_WARN_IF(NS_FAILED(rv))) {
156
0
    return rv;
157
0
  }
158
13
159
13
  if (aEvent) {
160
10
    rv = thread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
161
10
    if (NS_WARN_IF(NS_FAILED(rv))) {
162
0
      return rv;
163
0
    }
164
13
  }
165
13
166
13
  *aResult = nullptr;
167
13
  thread.swap(*aResult);
168
13
  return NS_OK;
169
13
}
170
171
nsresult
172
NS_NewThread(nsIThread** aResult, nsIRunnable* aEvent, uint32_t aStackSize)
173
0
{
174
0
  return NS_NewNamedThread(NS_LITERAL_CSTRING(""), aResult, aEvent, aStackSize);
175
0
}
176
177
nsresult
178
NS_GetCurrentThread(nsIThread** aResult)
179
128
{
180
128
#ifdef MOZILLA_INTERNAL_API
181
128
  return nsThreadManager::get().nsThreadManager::GetCurrentThread(aResult);
182
#else
183
  nsresult rv;
184
  nsCOMPtr<nsIThreadManager> mgr =
185
    do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
186
  if (NS_WARN_IF(NS_FAILED(rv))) {
187
    return rv;
188
  }
189
  return mgr->GetCurrentThread(aResult);
190
#endif
191
}
192
193
nsresult
194
NS_GetMainThread(nsIThread** aResult)
195
97
{
196
97
#ifdef MOZILLA_INTERNAL_API
197
97
  return nsThreadManager::get().nsThreadManager::GetMainThread(aResult);
198
#else
199
  nsresult rv;
200
  nsCOMPtr<nsIThreadManager> mgr =
201
    do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
202
  if (NS_WARN_IF(NS_FAILED(rv))) {
203
    return rv;
204
  }
205
  return mgr->GetMainThread(aResult);
206
#endif
207
}
208
209
nsresult
210
NS_DispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
211
21
{
212
21
  nsresult rv;
213
21
  nsCOMPtr<nsIRunnable> event(aEvent);
214
21
#ifdef MOZILLA_INTERNAL_API
215
21
  nsIEventTarget* thread = GetCurrentThreadEventTarget();
216
21
  if (!thread) {
217
0
    return NS_ERROR_UNEXPECTED;
218
0
  }
219
#else
220
  nsCOMPtr<nsIThread> thread;
221
  rv = NS_GetCurrentThread(getter_AddRefs(thread));
222
  if (NS_WARN_IF(NS_FAILED(rv))) {
223
    return rv;
224
  }
225
#endif
226
  // To keep us from leaking the runnable if dispatch method fails,
227
21
  // we grab the reference on failures and release it.
228
21
  nsIRunnable* temp = event.get();
229
21
  rv = thread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
230
21
  if (NS_WARN_IF(NS_FAILED(rv))) {
231
0
    // Dispatch() leaked the reference to the event, but due to caller's
232
0
    // assumptions, we shouldn't leak here. And given we are on the same
233
0
    // thread as the dispatch target, it's mostly safe to do it here.
234
0
    NS_RELEASE(temp);
235
0
  }
236
21
  return rv;
237
21
}
238
239
// It is common to call NS_DispatchToCurrentThread with a newly
240
// allocated runnable with a refcount of zero. To keep us from leaking
241
// the runnable if the dispatch method fails, we take a death grip.
242
nsresult
243
NS_DispatchToCurrentThread(nsIRunnable* aEvent)
244
0
{
245
0
  nsCOMPtr<nsIRunnable> event(aEvent);
246
0
  return NS_DispatchToCurrentThread(event.forget());
247
0
}
248
249
nsresult
250
NS_DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDispatchFlags)
251
94
{
252
94
  LeakRefPtr<nsIRunnable> event(std::move(aEvent));
253
94
  nsCOMPtr<nsIThread> thread;
254
94
  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
255
94
  if (NS_WARN_IF(NS_FAILED(rv))) {
256
0
    NS_ASSERTION(false, "Failed NS_DispatchToMainThread() in shutdown; leaking");
257
0
    // NOTE: if you stop leaking here, adjust Promise::MaybeReportRejected(),
258
0
    // which assumes a leak here, or split into leaks and no-leaks versions
259
0
    return rv;
260
0
  }
261
94
  return thread->Dispatch(event.take(), aDispatchFlags);
262
94
}
263
264
// In the case of failure with a newly allocated runnable with a
265
// refcount of zero, we intentionally leak the runnable, because it is
266
// likely that the runnable is being dispatched to the main thread
267
// because it owns main thread only objects, so it is not safe to
268
// release them here.
269
nsresult
270
NS_DispatchToMainThread(nsIRunnable* aEvent, uint32_t aDispatchFlags)
271
4
{
272
4
  nsCOMPtr<nsIRunnable> event(aEvent);
273
4
  return NS_DispatchToMainThread(event.forget(), aDispatchFlags);
274
4
}
275
276
nsresult
277
NS_DelayedDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDelayMs)
278
0
{
279
0
  nsCOMPtr<nsIRunnable> event(aEvent);
280
0
#ifdef MOZILLA_INTERNAL_API
281
0
  nsIEventTarget* thread = GetCurrentThreadEventTarget();
282
0
  if (!thread) {
283
0
    return NS_ERROR_UNEXPECTED;
284
0
  }
285
#else
286
  nsresult rv;
287
  nsCOMPtr<nsIThread> thread;
288
  rv = NS_GetCurrentThread(getter_AddRefs(thread));
289
  if (NS_WARN_IF(NS_FAILED(rv))) {
290
    return rv;
291
  }
292
#endif
293
294
0
  return thread->DelayedDispatch(event.forget(), aDelayMs);
295
0
}
296
297
nsresult
298
NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
299
                        nsIThread* aThread)
300
43
{
301
43
  nsresult rv;
302
43
  nsCOMPtr<nsIRunnable> event(aEvent);
303
43
  NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
304
43
  if (!aThread) {
305
0
    return NS_ERROR_UNEXPECTED;
306
0
  }
307
43
  // To keep us from leaking the runnable if dispatch method fails,
308
43
  // we grab the reference on failures and release it.
309
43
  nsIRunnable* temp = event.get();
310
43
  rv = aThread->IdleDispatch(event.forget());
311
43
  if (NS_WARN_IF(NS_FAILED(rv))) {
312
0
    // Dispatch() leaked the reference to the event, but due to caller's
313
0
    // assumptions, we shouldn't leak here. And given we are on the same
314
0
    // thread as the dispatch target, it's mostly safe to do it here.
315
0
    NS_RELEASE(temp);
316
0
  }
317
43
318
43
  return rv;
319
43
}
320
321
nsresult
322
NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
323
42
{
324
42
  return NS_IdleDispatchToThread(std::move(aEvent),
325
42
                                 NS_GetCurrentThread());
326
42
}
327
328
class IdleRunnableWrapper : public IdleRunnable
329
{
330
public:
331
  explicit IdleRunnableWrapper(already_AddRefed<nsIRunnable>&& aEvent)
332
    : mRunnable(std::move(aEvent))
333
1
  {
334
1
  }
335
336
  NS_IMETHOD Run() override
337
0
  {
338
0
    if (!mRunnable) {
339
0
      return NS_OK;
340
0
    }
341
0
    CancelTimer();
342
0
    nsCOMPtr<nsIRunnable> runnable = mRunnable.forget();
343
0
    return runnable->Run();
344
0
  }
345
346
  static void
347
  TimedOut(nsITimer* aTimer, void* aClosure)
348
0
  {
349
0
    RefPtr<IdleRunnableWrapper> runnable =
350
0
      static_cast<IdleRunnableWrapper*>(aClosure);
351
0
    runnable->Run();
352
0
  }
353
354
  void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
355
1
  {
356
1
    MOZ_ASSERT(aTarget);
357
1
    MOZ_ASSERT(!mTimer);
358
1
    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
359
1
                                TimedOut,
360
1
                                this,
361
1
                                aDelay,
362
1
                                nsITimer::TYPE_ONE_SHOT,
363
1
                                "IdleRunnableWrapper::SetTimer",
364
1
                                aTarget);
365
1
  }
366
367
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
368
  NS_IMETHOD GetName(nsACString& aName) override
369
0
  {
370
0
    aName.AssignLiteral("IdleRunnableWrapper");
371
0
    if (nsCOMPtr<nsINamed> named = do_QueryInterface(mRunnable)) {
372
0
      nsAutoCString name;
373
0
      named->GetName(name);
374
0
      if (!name.IsEmpty()) {
375
0
        aName.AppendLiteral(" for ");
376
0
        aName.Append(name);
377
0
      }
378
0
    }
379
0
    return NS_OK;
380
0
  }
381
#endif
382
383
private:
384
  ~IdleRunnableWrapper()
385
0
  {
386
0
    CancelTimer();
387
0
  }
388
389
  void CancelTimer()
390
0
  {
391
0
    if (mTimer) {
392
0
      mTimer->Cancel();
393
0
    }
394
0
  }
395
396
  nsCOMPtr<nsITimer> mTimer;
397
  nsCOMPtr<nsIRunnable> mRunnable;
398
};
399
400
extern nsresult
401
NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
402
                        uint32_t aTimeout,
403
                        nsIThread* aThread)
404
1
{
405
1
  nsCOMPtr<nsIRunnable> event(std::move(aEvent));
406
1
  NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
407
1
408
1
  //XXX Using current thread for now as the nsIEventTarget.
409
1
  nsIEventTarget* target = mozilla::GetCurrentThreadEventTarget();
410
1
  if (!target) {
411
0
    return NS_ERROR_UNEXPECTED;
412
0
  }
413
1
414
1
  nsCOMPtr<nsIIdleRunnable> idleEvent = do_QueryInterface(event);
415
1
416
1
  if (!idleEvent) {
417
1
    idleEvent = new IdleRunnableWrapper(event.forget());
418
1
    event = do_QueryInterface(idleEvent);
419
1
    MOZ_DIAGNOSTIC_ASSERT(event);
420
1
  }
421
1
  idleEvent->SetTimer(aTimeout, target);
422
1
423
1
  return NS_IdleDispatchToThread(event.forget(), aThread);
424
1
}
425
426
extern nsresult
427
NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent,
428
                               uint32_t aTimeout)
429
1
{
430
1
  return NS_IdleDispatchToThread(std::move(aEvent), aTimeout,
431
1
                                 NS_GetCurrentThread());
432
1
}
433
434
#ifndef XPCOM_GLUE_AVOID_NSPR
435
nsresult
436
NS_ProcessPendingEvents(nsIThread* aThread, PRIntervalTime aTimeout)
437
0
{
438
0
  nsresult rv = NS_OK;
439
0
440
0
#ifdef MOZILLA_INTERNAL_API
441
0
  if (!aThread) {
442
0
    aThread = NS_GetCurrentThread();
443
0
    if (NS_WARN_IF(!aThread)) {
444
0
      return NS_ERROR_UNEXPECTED;
445
0
    }
446
0
  }
447
#else
448
  nsCOMPtr<nsIThread> current;
449
  if (!aThread) {
450
    rv = NS_GetCurrentThread(getter_AddRefs(current));
451
    if (NS_WARN_IF(NS_FAILED(rv))) {
452
      return rv;
453
    }
454
    aThread = current.get();
455
  }
456
#endif
457
458
0
  PRIntervalTime start = PR_IntervalNow();
459
0
  for (;;) {
460
0
    bool processedEvent;
461
0
    rv = aThread->ProcessNextEvent(false, &processedEvent);
462
0
    if (NS_FAILED(rv) || !processedEvent) {
463
0
      break;
464
0
    }
465
0
    if (PR_IntervalNow() - start > aTimeout) {
466
0
      break;
467
0
    }
468
0
  }
469
0
  return rv;
470
0
}
471
#endif // XPCOM_GLUE_AVOID_NSPR
472
473
inline bool
474
hasPendingEvents(nsIThread* aThread)
475
0
{
476
0
  bool val;
477
0
  return NS_SUCCEEDED(aThread->HasPendingEvents(&val)) && val;
478
0
}
479
480
bool
481
NS_HasPendingEvents(nsIThread* aThread)
482
0
{
483
0
  if (!aThread) {
484
#ifndef MOZILLA_INTERNAL_API
485
    nsCOMPtr<nsIThread> current;
486
    NS_GetCurrentThread(getter_AddRefs(current));
487
    return hasPendingEvents(current);
488
#else
489
    aThread = NS_GetCurrentThread();
490
0
    if (NS_WARN_IF(!aThread)) {
491
0
      return false;
492
0
    }
493
0
#endif
494
0
  }
495
0
  return hasPendingEvents(aThread);
496
0
}
497
498
bool
499
NS_ProcessNextEvent(nsIThread* aThread, bool aMayWait)
500
40
{
501
40
#ifdef MOZILLA_INTERNAL_API
502
40
  if (!aThread) {
503
0
    aThread = NS_GetCurrentThread();
504
0
    if (NS_WARN_IF(!aThread)) {
505
0
      return false;
506
0
    }
507
40
  }
508
#else
509
  nsCOMPtr<nsIThread> current;
510
  if (!aThread) {
511
    NS_GetCurrentThread(getter_AddRefs(current));
512
    if (NS_WARN_IF(!current)) {
513
      return false;
514
    }
515
    aThread = current.get();
516
  }
517
#endif
518
40
  bool val;
519
40
  return NS_SUCCEEDED(aThread->ProcessNextEvent(aMayWait, &val)) && val;
520
40
}
521
522
void
523
NS_SetCurrentThreadName(const char* aName)
524
72
{
525
72
  PR_SetCurrentThreadName(aName);
526
72
  CrashReporter::SetCurrentThreadName(aName);
527
72
}
528
529
#ifdef MOZILLA_INTERNAL_API
530
nsIThread*
531
NS_GetCurrentThread()
532
130
{
533
130
  return nsThreadManager::get().GetCurrentThread();
534
130
}
535
536
537
nsIThread*
538
NS_GetCurrentThreadNoCreate()
539
49
{
540
49
  if (nsThreadManager::get().IsNSThread()) {
541
13
    return NS_GetCurrentThread();
542
13
  }
543
36
  return nullptr;
544
36
}
545
#endif
546
547
// nsThreadPoolNaming
548
nsCString
549
nsThreadPoolNaming::GetNextThreadName(const nsACString& aPoolName)
550
0
{
551
0
  nsCString name(aPoolName);
552
0
  name.AppendLiteral(" #");
553
0
  name.AppendInt(++mCounter, 10); // The counter is declared as atomic
554
0
  return name;
555
0
}
556
557
// nsAutoLowPriorityIO
558
nsAutoLowPriorityIO::nsAutoLowPriorityIO()
559
0
{
560
#if defined(XP_WIN)
561
  lowIOPrioritySet = SetThreadPriority(GetCurrentThread(),
562
                                       THREAD_MODE_BACKGROUND_BEGIN);
563
#elif defined(XP_MACOSX)
564
  oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);
565
  lowIOPrioritySet = oldPriority != -1 &&
566
                     setiopolicy_np(IOPOL_TYPE_DISK,
567
                                    IOPOL_SCOPE_THREAD,
568
                                    IOPOL_THROTTLE) != -1;
569
#else
570
  lowIOPrioritySet = false;
571
0
#endif
572
0
}
573
574
nsAutoLowPriorityIO::~nsAutoLowPriorityIO()
575
0
{
576
#if defined(XP_WIN)
577
  if (MOZ_LIKELY(lowIOPrioritySet)) {
578
    // On Windows the old thread priority is automatically restored
579
    SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
580
  }
581
#elif defined(XP_MACOSX)
582
  if (MOZ_LIKELY(lowIOPrioritySet)) {
583
    setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, oldPriority);
584
  }
585
#endif
586
}
587
588
namespace mozilla {
589
590
nsIEventTarget*
591
GetCurrentThreadEventTarget()
592
125
{
593
125
  nsCOMPtr<nsIThread> thread;
594
125
  nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
595
125
  if (NS_FAILED(rv)) {
596
0
    return nullptr;
597
0
  }
598
125
599
125
  return thread->EventTarget();
600
125
}
601
602
nsIEventTarget*
603
GetMainThreadEventTarget()
604
0
{
605
0
  nsCOMPtr<nsIThread> thread;
606
0
  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
607
0
  if (NS_FAILED(rv)) {
608
0
    return nullptr;
609
0
  }
610
0
611
0
  return thread->EventTarget();
612
0
}
613
614
nsISerialEventTarget*
615
GetCurrentThreadSerialEventTarget()
616
0
{
617
0
  nsCOMPtr<nsIThread> thread;
618
0
  nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
619
0
  if (NS_FAILED(rv)) {
620
0
    return nullptr;
621
0
  }
622
0
623
0
  return thread->SerialEventTarget();
624
0
}
625
626
nsISerialEventTarget*
627
GetMainThreadSerialEventTarget()
628
0
{
629
0
  nsCOMPtr<nsIThread> thread;
630
0
  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
631
0
  if (NS_FAILED(rv)) {
632
0
    return nullptr;
633
0
  }
634
0
635
0
  return thread->SerialEventTarget();
636
0
}
637
638
} // namespace mozilla
639
640
bool
641
nsIEventTarget::IsOnCurrentThread()
642
13
{
643
13
  if (mVirtualThread) {
644
13
    return mVirtualThread == GetCurrentVirtualThread();
645
13
  }
646
0
  return IsOnCurrentThreadInfallible();
647
0
}