Source code

Revision control

Other Tools

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