UnderrunHandlerLinux.cpp (2323B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include <mozilla/Atomics.h> 7 #include <mozilla/Sprintf.h> 8 #include <pthread.h> 9 10 #include <cerrno> 11 #include <csignal> 12 13 #include "audio_thread_priority.h" 14 #include "nsDebug.h" 15 16 namespace mozilla { 17 18 Atomic<bool, MemoryOrdering::ReleaseAcquire> gRealtimeLimitReached; 19 20 void UnderrunHandler(int signum) { gRealtimeLimitReached = true; } 21 22 bool SoftRealTimeLimitReached() { return gRealtimeLimitReached; } 23 24 void InstallSoftRealTimeLimitHandler() { 25 struct sigaction action, previous; 26 27 action.sa_handler = UnderrunHandler; 28 sigemptyset(&action.sa_mask); 29 action.sa_flags = 0; 30 31 int rv = sigaction(SIGXCPU, &action, &previous); 32 if (rv != 0) { 33 char buf[256]; 34 SprintfLiteral(buf, "sigaction(SIGXCPU, ...): %s", strerror(errno)); 35 NS_WARNING(buf); 36 return; 37 } 38 39 void* previous_handler = previous.sa_flags == SA_SIGINFO 40 ? reinterpret_cast<void*>(previous.sa_sigaction) 41 : reinterpret_cast<void*>(previous.sa_handler); 42 43 MOZ_ASSERT(previous_handler != UnderrunHandler, 44 "Only install the SIGXCPU handler once per process."); 45 46 if (previous_handler != SIG_DFL && previous_handler != UnderrunHandler) { 47 NS_WARNING( 48 "SIGXCPU handler was already set by something else, dropping real-time " 49 "priority."); 50 rv = sigaction(SIGXCPU, &previous, nullptr); 51 if (rv != 0) { 52 NS_WARNING("Could not restore previous handler for SIGXCPU."); 53 } 54 gRealtimeLimitReached = true; 55 return; 56 } 57 58 gRealtimeLimitReached = false; 59 } 60 61 void DemoteThreadFromRealTime() { 62 atp_thread_info* info = atp_get_current_thread_info(); 63 if (!info) { 64 NS_WARNING("Could not get current thread info when demoting thread."); 65 return; 66 } 67 int rv = atp_demote_thread_from_real_time(info); 68 if (rv) { 69 NS_WARNING("Could not demote thread from real-time."); 70 return; 71 } 72 rv = atp_free_thread_info(info); 73 if (rv) { 74 NS_WARNING("Could not free atp_thread_info struct"); 75 } 76 gRealtimeLimitReached = false; 77 } 78 79 } // namespace mozilla