зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1575883 - Handle SIGXCPU in Gecko. r=kinetik,glandium
This allows installing a SIGXCPU handler, which will simply set an atomic to true when reached. Another function allows querying this atomic. Finally, another function allows demoting the current thread from real-time priority. This is per-process currently, as there is only one audio callback thread that is set to RT scheduling per process, servicing all HTMLMediaElements and MSGs. Whenever any of those go over the soft limit, the thread is demoted. Differential Revision: https://phabricator.services.mozilla.com/D43404 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
2196bcaba6
Коммит
bb8066315b
|
@ -0,0 +1,22 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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 MOZILLA_UNDERRUNHANDLER_H_
|
||||
#define MOZILLA_UNDERRUNHANDLER_H_
|
||||
|
||||
namespace mozilla {
|
||||
// Install an handler on SIGXPCU for the calling thread, that calls
|
||||
// `UnderrunHandler` when the soft real-time limit has been reached. If a
|
||||
// handler was already in place, this does nothing. No-op if not on Linux
|
||||
// Desktop.
|
||||
void InstallSoftRealTimeLimitHandler();
|
||||
// Query whether or not the soft-real-time limit has been reached. Always
|
||||
// false when not on Linux desktop. Can be called from any thread.
|
||||
bool SoftRealTimeLimitReached();
|
||||
// Set the calling thread to a normal scheduling class.
|
||||
void DemoteThreadFromRealTime();
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_UNDERRUNHANDLER_H_
|
|
@ -0,0 +1,77 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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 <csignal>
|
||||
#include <cerrno>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <mozilla/Sprintf.h>
|
||||
#include <mozilla/Atomics.h>
|
||||
#include "audio_thread_priority.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
Atomic<bool, MemoryOrdering::ReleaseAcquire> gRealtimeLimitReached;
|
||||
|
||||
void UnderrunHandler(int signum) { gRealtimeLimitReached = true; }
|
||||
|
||||
bool SoftRealTimeLimitReached() { return gRealtimeLimitReached; }
|
||||
|
||||
void InstallSoftRealTimeLimitHandler() {
|
||||
struct sigaction action, previous;
|
||||
|
||||
action.sa_handler = UnderrunHandler;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
|
||||
int rv = sigaction(SIGXCPU, &action, &previous);
|
||||
if (rv != 0) {
|
||||
char buf[256];
|
||||
SprintfLiteral(buf, "sigaction(SIGXCPU, ...): %s", strerror(errno));
|
||||
NS_WARNING(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
void* previous_handler = previous.sa_flags == SA_SIGINFO
|
||||
? reinterpret_cast<void*>(previous.sa_sigaction)
|
||||
: reinterpret_cast<void*>(previous.sa_handler);
|
||||
|
||||
MOZ_ASSERT(previous_handler != UnderrunHandler,
|
||||
"Only install the SIGXCPU handler once per process.");
|
||||
|
||||
if (previous_handler != SIG_DFL && previous_handler != UnderrunHandler) {
|
||||
NS_WARNING(
|
||||
"SIGXCPU handler was already set by something else, dropping real-time "
|
||||
"priority.");
|
||||
rv = sigaction(SIGXCPU, &previous, nullptr);
|
||||
if (rv != 0) {
|
||||
NS_WARNING("Could not restore previous handler for SIGXCPU.");
|
||||
}
|
||||
gRealtimeLimitReached = true;
|
||||
return;
|
||||
}
|
||||
|
||||
gRealtimeLimitReached = false;
|
||||
}
|
||||
|
||||
void DemoteThreadFromRealTime() {
|
||||
atp_thread_info* info = atp_get_current_thread_info();
|
||||
if (!info) {
|
||||
NS_WARNING("Could not get current thread info when demoting thread.");
|
||||
return;
|
||||
}
|
||||
int rv = atp_demote_thread_from_real_time(info);
|
||||
if (rv) {
|
||||
NS_WARNING("Could not demote thread from real-time.");
|
||||
return;
|
||||
}
|
||||
rv = atp_free_thread_info(info);
|
||||
if (rv) {
|
||||
NS_WARNING("Could not free atp_thread_info struct");
|
||||
}
|
||||
gRealtimeLimitReached = false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,14 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool SoftRealTimeLimitReached() { return false; }
|
||||
|
||||
void InstallSoftRealTimeLimitHandler() {}
|
||||
|
||||
void DemoteThreadFromRealTime() {}
|
||||
|
||||
} // namespace mozilla
|
|
@ -302,6 +302,11 @@ UNIFIED_SOURCES += [
|
|||
'XiphExtradata.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'Linux':
|
||||
UNIFIED_SOURCES += [ 'UnderrunHandlerLinux.cpp' ]
|
||||
else:
|
||||
UNIFIED_SOURCES += [ 'UnderrunHandlerNoop.cpp']
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
EXPORTS.mozilla.audio += [
|
||||
'AudioNotificationReceiver.h',
|
||||
|
|
Загрузка…
Ссылка в новой задаче