From 1d0967ab3c25f843064667beabd4e68c6b4a6511 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Tue, 7 Apr 2026 15:26:28 -0400 Subject: [PATCH 1/9] Issue #3027 - completely remove all remaining usages of dbus-glib from our tree --- config/system-headers | 2 - dom/gamepad/moz.build | 2 - hal/moz.build | 2 - ipc/dbus/moz.build | 2 - .../webrtc/trunk/build/install-build-deps.sh | 6 +- media/webrtc/trunk/build/linux/system.gyp | 21 - media/webrtc/trunk/webrtc/BUILD.gn | 15 - media/webrtc/trunk/webrtc/base/BUILD.gn | 4 - media/webrtc/trunk/webrtc/base/base.gyp | 12 - media/webrtc/trunk/webrtc/base/dbus.cc | 400 ------------------ media/webrtc/trunk/webrtc/base/dbus.h | 168 -------- .../webrtc/trunk/webrtc/base/dbus_unittest.cc | 232 ---------- .../webrtc/base/libdbusglibsymboltable.cc | 24 -- .../webrtc/base/libdbusglibsymboltable.h | 56 --- media/webrtc/trunk/webrtc/build/common.gypi | 12 - media/webrtc/trunk/webrtc/build/webrtc.gni | 3 - netwerk/wifi/moz.build | 2 +- old-configure.in | 1 - testing/docker/base-test/Dockerfile | 1 - testing/docker/centos6-build/system-setup.sh | 4 - testing/docker/firefox-snap/snapcraft.yaml.in | 1 - .../recipes/ubuntu1204-test-system-setup.sh | 1 - .../recipes/ubuntu1604-test-system-setup.sh | 1 - .../builds/releng_base_linux_32_builds.py | 2 +- .../releng_sub_linux_configs/32_artifact.py | 2 +- .../32_debug_artifact.py | 2 +- testing/mozharness/configs/hazards/common.py | 2 +- .../mozharness/configs/single_locale/linux.py | 2 +- toolkit/library/moz.build | 2 +- toolkit/xre/moz.build | 1 - uriloader/exthandler/moz.build | 1 - 31 files changed, 10 insertions(+), 976 deletions(-) delete mode 100644 media/webrtc/trunk/webrtc/base/dbus.cc delete mode 100644 media/webrtc/trunk/webrtc/base/dbus.h delete mode 100644 media/webrtc/trunk/webrtc/base/dbus_unittest.cc delete mode 100644 media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.cc delete mode 100644 media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.h diff --git a/config/system-headers b/config/system-headers index 1ad701fe03..3bc25a459e 100644 --- a/config/system-headers +++ b/config/system-headers @@ -335,8 +335,6 @@ curses.h cxxabi.h DateTimeUtils.h dbus/dbus.h -dbus/dbus-glib.h -dbus/dbus-glib-lowlevel.h ddeml.h Debug.h dem.h diff --git a/dom/gamepad/moz.build b/dom/gamepad/moz.build index eabd460fc2..9a3fbe4cfe 100644 --- a/dom/gamepad/moz.build +++ b/dom/gamepad/moz.build @@ -77,6 +77,4 @@ if CONFIG['MOZ_GAMEPAD']: ] CFLAGS += CONFIG['GLIB_CFLAGS'] - CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] CXXFLAGS += CONFIG['GLIB_CFLAGS'] - CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] diff --git a/hal/moz.build b/hal/moz.build index fefd56fcf1..9943a090d2 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -99,6 +99,4 @@ if CONFIG['MOZ_GAMEPAD']: ] CFLAGS += CONFIG['GLIB_CFLAGS'] -CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] CXXFLAGS += CONFIG['GLIB_CFLAGS'] -CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] diff --git a/ipc/dbus/moz.build b/ipc/dbus/moz.build index 81626d1108..8a60affa66 100644 --- a/ipc/dbus/moz.build +++ b/ipc/dbus/moz.build @@ -27,6 +27,4 @@ FINAL_LIBRARY = 'xul' if CONFIG['MOZ_ENABLE_DBUS']: CFLAGS += CONFIG['MOZ_DBUS_CFLAGS'] - CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS'] - CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] diff --git a/media/webrtc/trunk/build/install-build-deps.sh b/media/webrtc/trunk/build/install-build-deps.sh index b77e23a6d9..7da5b923a2 100644 --- a/media/webrtc/trunk/build/install-build-deps.sh +++ b/media/webrtc/trunk/build/install-build-deps.sh @@ -58,7 +58,7 @@ chromeos_dev_list="libbluetooth-dev libpulse-dev" # Packages need for development dev_list="apache2.2-bin bison curl elfutils fakeroot flex g++ gperf language-pack-fr libapache2-mod-php5 libasound2-dev libbz2-dev - libcairo2-dev libcups2-dev libcurl4-gnutls-dev libdbus-glib-1-dev + libcairo2-dev libcups2-dev libcurl4-gnutls-dev libelf-dev libgconf2-dev libgl1-mesa-dev libglib2.0-dev libglu1-mesa-dev libgnome-keyring-dev libgtk2.0-dev libkrb5-dev libnspr4-dev libnss3-dev libpam0g-dev libsctp-dev @@ -80,7 +80,7 @@ fi chromeos_lib_list="libpulse0 libbz2-1.0 libcurl4-gnutls-dev" # Full list of required run-time libraries -lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2 libdbus-glib-1-2 +lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2 libexpat1 libfontconfig1 libfreetype6 libglib2.0-0 libgnome-keyring0 libgtk2.0-0 libpam0g libpango1.0-0 libpcre3 libpixman-1-0 libpng12-0 libstdc++6 libsqlite3-0 libudev0 libx11-6 libxau6 libxcb1 @@ -89,7 +89,7 @@ lib_list="libatk1.0-0 libc6 libasound2 libcairo2 libcups2 libdbus-glib-1-2 $chromeos_lib_list" # Debugging symbols for all of the run-time libraries -dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg libdbus-glib-1-2-dbg +dbg_list="libatk1.0-dbg libc6-dbg libcairo2-dbg libfontconfig1-dbg libglib2.0-0-dbg libgtk2.0-0-dbg libpango1.0-0-dbg libpcre3-dbg libpixman-1-0-dbg libsqlite3-0-dbg diff --git a/media/webrtc/trunk/build/linux/system.gyp b/media/webrtc/trunk/build/linux/system.gyp index e36e558a8b..78bc380d49 100644 --- a/media/webrtc/trunk/build/linux/system.gyp +++ b/media/webrtc/trunk/build/linux/system.gyp @@ -112,27 +112,6 @@ ], }, ], # targets - }, { # chromeos==1 - 'targets': [ - { - # TODO(satorux): Remove this once dbus-glib clients are gone. - 'target_name': 'dbus-glib', - 'type': 'none', - 'direct_dependent_settings': { - 'cflags': [ - ' - # is still not found even if the execution of - # build/config/linux/pkg-config.py dbus-glib-1 returns correct include - # dirs on Linux. - all_dependent_configs = [ "dbus-glib" ] - } - if (build_with_chromium) { defines += [ "LOGGING_INSIDE_WEBRTC" ] } else { diff --git a/media/webrtc/trunk/webrtc/base/BUILD.gn b/media/webrtc/trunk/webrtc/base/BUILD.gn index 5201a69bef..aa88dda4c2 100644 --- a/media/webrtc/trunk/webrtc/base/BUILD.gn +++ b/media/webrtc/trunk/webrtc/base/BUILD.gn @@ -403,10 +403,6 @@ static_library("rtc_base") { if (is_linux) { sources += [ - "dbus.cc", - "dbus.h", - "libdbusglibsymboltable.cc", - "libdbusglibsymboltable.h", "linuxfdwalk.c", "linuxfdwalk.h", ] diff --git a/media/webrtc/trunk/webrtc/base/base.gyp b/media/webrtc/trunk/webrtc/base/base.gyp index e7c6c90307..546ba7b62a 100644 --- a/media/webrtc/trunk/webrtc/base/base.gyp +++ b/media/webrtc/trunk/webrtc/base/base.gyp @@ -137,8 +137,6 @@ 'criticalsection.h', 'cryptstring.cc', 'cryptstring.h', - 'dbus.cc', - 'dbus.h', 'diskcache.cc', 'diskcache.h', 'diskcache_win32.cc', @@ -178,8 +176,6 @@ # 'latebindingsymboltable.cc.def', 'latebindingsymboltable.h', # 'latebindingsymboltable.h.def', - 'libdbusglibsymboltable.cc', - 'libdbusglibsymboltable.h', 'linux.cc', 'linux.h', 'linuxfdwalk.c', @@ -389,8 +385,6 @@ 'callback.h', # 'callback.h.pump', 'constructormagic.h', - 'dbus.cc', - 'dbus.h', 'diskcache_win32.cc', 'diskcache_win32.h', 'filelock.cc', @@ -406,8 +400,6 @@ # 'latebindingsymboltable.cc.def', 'latebindingsymboltable.h', # 'latebindingsymboltable.h.def', - 'libdbusglibsymboltable.cc', - 'libdbusglibsymboltable.h', 'linuxfdwalk.c', 'linuxfdwalk.h', 'x11windowpicker.cc', @@ -634,10 +626,6 @@ }, }, { 'sources!': [ - 'dbus.cc', - 'dbus.h', - 'libdbusglibsymboltable.cc', - 'libdbusglibsymboltable.h', 'linuxfdwalk.c', ], }], diff --git a/media/webrtc/trunk/webrtc/base/dbus.cc b/media/webrtc/trunk/webrtc/base/dbus.cc deleted file mode 100644 index 312bad0509..0000000000 --- a/media/webrtc/trunk/webrtc/base/dbus.cc +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifdef HAVE_DBUS_GLIB - -#include "webrtc/base/dbus.h" - -#include - -#include "webrtc/base/logging.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -// Avoid static object construction/destruction on startup/shutdown. -static pthread_once_t g_dbus_init_once = PTHREAD_ONCE_INIT; -static LibDBusGlibSymbolTable *g_dbus_symbol = NULL; - -// Releases DBus-Glib symbols. -static void ReleaseDBusGlibSymbol() { - if (g_dbus_symbol != NULL) { - delete g_dbus_symbol; - g_dbus_symbol = NULL; - } -} - -// Loads DBus-Glib symbols. -static void InitializeDBusGlibSymbol() { - // This is thread safe. - if (NULL == g_dbus_symbol) { - g_dbus_symbol = new LibDBusGlibSymbolTable(); - - // Loads dbus-glib - if (NULL == g_dbus_symbol || !g_dbus_symbol->Load()) { - LOG(LS_WARNING) << "Failed to load dbus-glib symbol table."; - ReleaseDBusGlibSymbol(); - } else { - // Nothing we can do if atexit() failed. Just ignore its returned value. - atexit(ReleaseDBusGlibSymbol); - } - } -} - -inline static LibDBusGlibSymbolTable *GetSymbols() { - return DBusMonitor::GetDBusGlibSymbolTable(); -} - -// Implementation of class DBusSigMessageData -DBusSigMessageData::DBusSigMessageData(DBusMessage *message) - : TypedMessageData(message) { - GetSymbols()->dbus_message_ref()(data()); -} - -DBusSigMessageData::~DBusSigMessageData() { - GetSymbols()->dbus_message_unref()(data()); -} - -// Implementation of class DBusSigFilter - -// Builds a DBus filter string from given DBus path, interface and member. -std::string DBusSigFilter::BuildFilterString(const std::string &path, - const std::string &interface, - const std::string &member) { - std::string ret(DBUS_TYPE "='" DBUS_SIGNAL "'"); - if (!path.empty()) { - ret += ("," DBUS_PATH "='"); - ret += path; - ret += "'"; - } - if (!interface.empty()) { - ret += ("," DBUS_INTERFACE "='"); - ret += interface; - ret += "'"; - } - if (!member.empty()) { - ret += ("," DBUS_MEMBER "='"); - ret += member; - ret += "'"; - } - return ret; -} - -// Forwards the message to the given instance. -DBusHandlerResult DBusSigFilter::DBusCallback(DBusConnection *dbus_conn, - DBusMessage *message, - void *instance) { - ASSERT(instance); - if (instance) { - return static_cast(instance)->Callback(message); - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -// Posts a message to caller thread. -DBusHandlerResult DBusSigFilter::Callback(DBusMessage *message) { - if (caller_thread_) { - caller_thread_->Post(this, DSM_SIGNAL, new DBusSigMessageData(message)); - } - // Don't "eat" the message here. Let it pop up. - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -// From MessageHandler. -void DBusSigFilter::OnMessage(Message *message) { - if (message != NULL && DSM_SIGNAL == message->message_id) { - DBusSigMessageData *msg = - static_cast(message->pdata); - if (msg) { - ProcessSignal(msg->data()); - delete msg; - } - } -} - -// Definition of private class DBusMonitoringThread. -// It creates a worker-thread to listen signals on DBus. The worker-thread will -// be running in a priate GMainLoop forever until either Stop() has been invoked -// or it hits an error. -class DBusMonitor::DBusMonitoringThread : public rtc::Thread { - public: - explicit DBusMonitoringThread(DBusMonitor *monitor, - GMainContext *context, - GMainLoop *mainloop, - std::vector *filter_list) - : monitor_(monitor), - context_(context), - mainloop_(mainloop), - connection_(NULL), - idle_source_(NULL), - filter_list_(filter_list) { - ASSERT(monitor_); - ASSERT(context_); - ASSERT(mainloop_); - ASSERT(filter_list_); - } - - virtual ~DBusMonitoringThread() { - Stop(); - } - - // Override virtual method of Thread. Context: worker-thread. - virtual void Run() { - ASSERT(NULL == connection_); - - // Setup DBus connection and start monitoring. - monitor_->OnMonitoringStatusChanged(DMS_INITIALIZING); - if (!Setup()) { - LOG(LS_ERROR) << "DBus monitoring setup failed."; - monitor_->OnMonitoringStatusChanged(DMS_FAILED); - CleanUp(); - return; - } - monitor_->OnMonitoringStatusChanged(DMS_RUNNING); - g_main_loop_run(mainloop_); - monitor_->OnMonitoringStatusChanged(DMS_STOPPED); - - // Done normally. Clean up DBus connection. - CleanUp(); - return; - } - - // Override virtual method of Thread. Context: caller-thread. - virtual void Stop() { - ASSERT(NULL == idle_source_); - // Add an idle source and let the gmainloop quit on idle. - idle_source_ = g_idle_source_new(); - if (idle_source_) { - g_source_set_callback(idle_source_, &Idle, this, NULL); - g_source_attach(idle_source_, context_); - } else { - LOG(LS_ERROR) << "g_idle_source_new() failed."; - QuitGMainloop(); // Try to quit anyway. - } - - Thread::Stop(); // Wait for the thread. - } - - private: - // Registers all DBus filters. - void RegisterAllFilters() { - ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()( - connection_)); - - for (std::vector::iterator it = filter_list_->begin(); - it != filter_list_->end(); ++it) { - DBusSigFilter *filter = (*it); - if (!filter) { - LOG(LS_ERROR) << "DBusSigFilter list corrupted."; - continue; - } - - GetSymbols()->dbus_bus_add_match()( - GetSymbols()->dbus_g_connection_get_connection()(connection_), - filter->filter().c_str(), NULL); - - if (!GetSymbols()->dbus_connection_add_filter()( - GetSymbols()->dbus_g_connection_get_connection()(connection_), - &DBusSigFilter::DBusCallback, filter, NULL)) { - LOG(LS_ERROR) << "dbus_connection_add_filter() failed." - << "Filter: " << filter->filter(); - continue; - } - } - } - - // Unregisters all DBus filters. - void UnRegisterAllFilters() { - ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()( - connection_)); - - for (std::vector::iterator it = filter_list_->begin(); - it != filter_list_->end(); ++it) { - DBusSigFilter *filter = (*it); - if (!filter) { - LOG(LS_ERROR) << "DBusSigFilter list corrupted."; - continue; - } - GetSymbols()->dbus_connection_remove_filter()( - GetSymbols()->dbus_g_connection_get_connection()(connection_), - &DBusSigFilter::DBusCallback, filter); - } - } - - // Sets up the monitoring thread. - bool Setup() { - g_main_context_push_thread_default(context_); - - // Start connection to dbus. - // If dbus daemon is not running, returns false immediately. - connection_ = GetSymbols()->dbus_g_bus_get_private()(monitor_->type_, - context_, NULL); - if (NULL == connection_) { - LOG(LS_ERROR) << "dbus_g_bus_get_private() unable to get connection."; - return false; - } - if (NULL == GetSymbols()->dbus_g_connection_get_connection()(connection_)) { - LOG(LS_ERROR) << "dbus_g_connection_get_connection() returns NULL. " - << "DBus daemon is probably not running."; - return false; - } - - // Application don't exit if DBus daemon die. - GetSymbols()->dbus_connection_set_exit_on_disconnect()( - GetSymbols()->dbus_g_connection_get_connection()(connection_), FALSE); - - // Connect all filters. - RegisterAllFilters(); - - return true; - } - - // Cleans up the monitoring thread. - void CleanUp() { - if (idle_source_) { - // We did an attach() with the GSource, so we need to destroy() it. - g_source_destroy(idle_source_); - // We need to unref() the GSource to end the last reference we got. - g_source_unref(idle_source_); - idle_source_ = NULL; - } - if (connection_) { - if (GetSymbols()->dbus_g_connection_get_connection()(connection_)) { - UnRegisterAllFilters(); - GetSymbols()->dbus_connection_close()( - GetSymbols()->dbus_g_connection_get_connection()(connection_)); - } - GetSymbols()->dbus_g_connection_unref()(connection_); - connection_ = NULL; - } - g_main_loop_unref(mainloop_); - mainloop_ = NULL; - g_main_context_unref(context_); - context_ = NULL; - } - - // Handles callback on Idle. We only add this source when ready to stop. - static gboolean Idle(gpointer data) { - static_cast(data)->QuitGMainloop(); - return TRUE; - } - - // We only hit this when ready to quit. - void QuitGMainloop() { - g_main_loop_quit(mainloop_); - } - - DBusMonitor *monitor_; - - GMainContext *context_; - GMainLoop *mainloop_; - DBusGConnection *connection_; - GSource *idle_source_; - - std::vector *filter_list_; -}; - -// Implementation of class DBusMonitor - -// Returns DBus-Glib symbol handle. Initialize it first if hasn't. -LibDBusGlibSymbolTable *DBusMonitor::GetDBusGlibSymbolTable() { - // This is multi-thread safe. - pthread_once(&g_dbus_init_once, InitializeDBusGlibSymbol); - - return g_dbus_symbol; -}; - -// Creates an instance of DBusMonitor -DBusMonitor *DBusMonitor::Create(DBusBusType type) { - if (NULL == DBusMonitor::GetDBusGlibSymbolTable()) { - return NULL; - } - return new DBusMonitor(type); -} - -DBusMonitor::DBusMonitor(DBusBusType type) - : type_(type), - status_(DMS_NOT_INITIALIZED), - monitoring_thread_(NULL) { - ASSERT(type_ == DBUS_BUS_SYSTEM || type_ == DBUS_BUS_SESSION); -} - -DBusMonitor::~DBusMonitor() { - StopMonitoring(); -} - -bool DBusMonitor::AddFilter(DBusSigFilter *filter) { - if (monitoring_thread_) { - return false; - } - if (!filter) { - return false; - } - filter_list_.push_back(filter); - return true; -} - -bool DBusMonitor::StartMonitoring() { - if (!monitoring_thread_) { - g_type_init(); - // g_thread_init API is deprecated since glib 2.31.0, see release note: - // http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html -#if !GLIB_CHECK_VERSION(2, 31, 0) - g_thread_init(NULL); -#endif - GetSymbols()->dbus_g_thread_init()(); - - GMainContext *context = g_main_context_new(); - if (NULL == context) { - LOG(LS_ERROR) << "g_main_context_new() failed."; - return false; - } - - GMainLoop *mainloop = g_main_loop_new(context, FALSE); - if (NULL == mainloop) { - LOG(LS_ERROR) << "g_main_loop_new() failed."; - g_main_context_unref(context); - return false; - } - - monitoring_thread_ = new DBusMonitoringThread(this, context, mainloop, - &filter_list_); - if (monitoring_thread_ == NULL) { - LOG(LS_ERROR) << "Failed to create DBus monitoring thread."; - g_main_context_unref(context); - g_main_loop_unref(mainloop); - return false; - } - monitoring_thread_->Start(); - } - return true; -} - -bool DBusMonitor::StopMonitoring() { - if (monitoring_thread_) { - monitoring_thread_->Stop(); - monitoring_thread_ = NULL; - } - return true; -} - -DBusMonitor::DBusMonitorStatus DBusMonitor::GetStatus() { - return status_; -} - -void DBusMonitor::OnMonitoringStatusChanged(DBusMonitorStatus status) { - status_ = status; -} - -#undef LATE - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB diff --git a/media/webrtc/trunk/webrtc/base/dbus.h b/media/webrtc/trunk/webrtc/base/dbus.h deleted file mode 100644 index fb90638bc3..0000000000 --- a/media/webrtc/trunk/webrtc/base/dbus.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_DBUS_H_ -#define WEBRTC_BASE_DBUS_H_ - -#ifdef HAVE_DBUS_GLIB - -#include - -#include -#include - -#include "webrtc/base/libdbusglibsymboltable.h" -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -#define DBUS_TYPE "type" -#define DBUS_SIGNAL "signal" -#define DBUS_PATH "path" -#define DBUS_INTERFACE "interface" -#define DBUS_MEMBER "member" - -#ifdef CHROMEOS -#define CROS_PM_PATH "/" -#define CROS_PM_INTERFACE "org.chromium.PowerManager" -#define CROS_SIG_POWERCHANGED "PowerStateChanged" -#define CROS_VALUE_SLEEP "mem" -#define CROS_VALUE_RESUME "on" -#else -#define UP_PATH "/org/freedesktop/UPower" -#define UP_INTERFACE "org.freedesktop.UPower" -#define UP_SIG_SLEEPING "Sleeping" -#define UP_SIG_RESUMING "Resuming" -#endif // CHROMEOS - -// Wraps a DBus messages. -class DBusSigMessageData : public TypedMessageData { - public: - explicit DBusSigMessageData(DBusMessage *message); - ~DBusSigMessageData(); -}; - -// DBusSigFilter is an abstract class that defines the interface of DBus -// signal handling. -// The subclasses implement ProcessSignal() for various purposes. -// When a DBus signal comes, a DSM_SIGNAL message is posted to the caller thread -// which will then invokes ProcessSignal(). -class DBusSigFilter : protected MessageHandler { - public: - enum DBusSigMessage { DSM_SIGNAL }; - - // This filter string should ususally come from BuildFilterString() - explicit DBusSigFilter(const std::string &filter) - : caller_thread_(Thread::Current()), filter_(filter) { - } - - // Builds a DBus monitor filter string from given DBus path, interface, and - // member. - // See http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html - static std::string BuildFilterString(const std::string &path, - const std::string &interface, - const std::string &member); - - // Handles callback on DBus messages by DBus system. - static DBusHandlerResult DBusCallback(DBusConnection *dbus_conn, - DBusMessage *message, - void *instance); - - // Handles callback on DBus messages to each DBusSigFilter instance. - DBusHandlerResult Callback(DBusMessage *message); - - // From MessageHandler. - virtual void OnMessage(Message *message); - - // Returns the DBus monitor filter string. - const std::string &filter() const { return filter_; } - - private: - // On caller thread. - virtual void ProcessSignal(DBusMessage *message) = 0; - - Thread *caller_thread_; - const std::string filter_; -}; - -// DBusMonitor is a class for DBus signal monitoring. -// -// The caller-thread calls AddFilter() first to add the signals that it wants to -// monitor and then calls StartMonitoring() to start the monitoring. -// This will create a worker-thread which listens on DBus connection and sends -// DBus signals back through the callback. -// The worker-thread will be running forever until either StopMonitoring() is -// called from the caller-thread or the worker-thread hit some error. -// -// Programming model: -// 1. Caller-thread: Creates an object of DBusMonitor. -// 2. Caller-thread: Calls DBusMonitor::AddFilter() one or several times. -// 3. Caller-thread: StartMonitoring(). -// ... -// 4. Worker-thread: DBus signal recieved. Post a message to caller-thread. -// 5. Caller-thread: DBusFilterBase::ProcessSignal() is invoked. -// ... -// 6. Caller-thread: StopMonitoring(). -// -// Assumption: -// AddFilter(), StartMonitoring(), and StopMonitoring() methods are called by -// a single thread. Hence, there is no need to make them thread safe. -class DBusMonitor { - public: - // Status of DBus monitoring. - enum DBusMonitorStatus { - DMS_NOT_INITIALIZED, // Not initialized. - DMS_INITIALIZING, // Initializing the monitoring thread. - DMS_RUNNING, // Monitoring. - DMS_STOPPED, // Not monitoring. Stopped normally. - DMS_FAILED, // Not monitoring. Failed. - }; - - // Returns the DBus-Glib symbol table. - // We should only use this function to access DBus-Glib symbols. - static LibDBusGlibSymbolTable *GetDBusGlibSymbolTable(); - - // Creates an instance of DBusMonitor. - static DBusMonitor *Create(DBusBusType type); - ~DBusMonitor(); - - // Adds a filter to DBusMonitor. - bool AddFilter(DBusSigFilter *filter); - - // Starts DBus message monitoring. - bool StartMonitoring(); - - // Stops DBus message monitoring. - bool StopMonitoring(); - - // Gets the status of DBus monitoring. - DBusMonitorStatus GetStatus(); - - private: - // Forward declaration. Defined in the .cc file. - class DBusMonitoringThread; - - explicit DBusMonitor(DBusBusType type); - - // Updates status_ when monitoring status has changed. - void OnMonitoringStatusChanged(DBusMonitorStatus status); - - DBusBusType type_; - DBusMonitorStatus status_; - DBusMonitoringThread *monitoring_thread_; - std::vector filter_list_; -}; - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB - -#endif // WEBRTC_BASE_DBUS_H_ diff --git a/media/webrtc/trunk/webrtc/base/dbus_unittest.cc b/media/webrtc/trunk/webrtc/base/dbus_unittest.cc deleted file mode 100644 index 505ddbbc8d..0000000000 --- a/media/webrtc/trunk/webrtc/base/dbus_unittest.cc +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2011 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifdef HAVE_DBUS_GLIB - -#include "webrtc/base/dbus.h" -#include "webrtc/base/gunit.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -#define SIG_NAME "NameAcquired" - -static const uint32 kTimeoutMs = 5000U; - -class DBusSigFilterTest : public DBusSigFilter { - public: - // DBusSigFilterTest listens on DBus service itself for "NameAcquired" signal. - // This signal should be received when the application connects to DBus - // service and gains ownership of a name. - // http://dbus.freedesktop.org/doc/dbus-specification.html - DBusSigFilterTest() - : DBusSigFilter(GetFilter()), - message_received_(false) { - } - - bool MessageReceived() { - return message_received_; - } - - private: - static std::string GetFilter() { - return rtc::DBusSigFilter::BuildFilterString("", "", SIG_NAME); - } - - // Implement virtual method of DBusSigFilter. On caller thread. - virtual void ProcessSignal(DBusMessage *message) { - EXPECT_TRUE(message != NULL); - message_received_ = true; - } - - bool message_received_; -}; - -TEST(DBusMonitorTest, StartStopStartStop) { - DBusSigFilterTest filter; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter)); - - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_NOT_INITIALIZED); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_RUNNING); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -// DBusMonitorTest listens on DBus service itself for "NameAcquired" signal. -// This signal should be received when the application connects to DBus -// service and gains ownership of a name. -// This test is to make sure that we capture the "NameAcquired" signal. -TEST(DBusMonitorTest, ReceivedNameAcquiredSignal) { - DBusSigFilterTest filter; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter)); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_TRUE_WAIT(filter.MessageReceived(), kTimeoutMs); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -TEST(DBusMonitorTest, ConcurrentMonitors) { - DBusSigFilterTest filter1; - rtc::scoped_ptr monitor1; - monitor1.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor1) { - EXPECT_TRUE(monitor1->AddFilter(&filter1)); - DBusSigFilterTest filter2; - rtc::scoped_ptr monitor2; - monitor2.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - EXPECT_TRUE(monitor2->AddFilter(&filter2)); - - EXPECT_TRUE(monitor1->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor1->GetStatus(), kTimeoutMs); - EXPECT_TRUE(monitor2->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor2->GetStatus(), kTimeoutMs); - - EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs); - EXPECT_TRUE(monitor2->StopMonitoring()); - EXPECT_EQ(monitor2->GetStatus(), DBusMonitor::DMS_STOPPED); - - EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs); - EXPECT_TRUE(monitor1->StopMonitoring()); - EXPECT_EQ(monitor1->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -TEST(DBusMonitorTest, ConcurrentFilters) { - DBusSigFilterTest filter1; - DBusSigFilterTest filter2; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter1)); - EXPECT_TRUE(monitor->AddFilter(&filter2)); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - - EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs); - EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs); - - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -TEST(DBusMonitorTest, NoAddFilterIfRunning) { - DBusSigFilterTest filter1; - DBusSigFilterTest filter2; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter1)); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_FALSE(monitor->AddFilter(&filter2)); - - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -TEST(DBusMonitorTest, AddFilterAfterStop) { - DBusSigFilterTest filter1; - DBusSigFilterTest filter2; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter1)); - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - - EXPECT_TRUE(monitor->AddFilter(&filter2)); - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs); - EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs); - EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs); - EXPECT_TRUE(monitor->StopMonitoring()); - EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED); - } else { - LOG(LS_WARNING) << "DBus Monitor not started. Skipping test."; - } -} - -TEST(DBusMonitorTest, StopRightAfterStart) { - DBusSigFilterTest filter; - rtc::scoped_ptr monitor; - monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM)); - if (monitor) { - EXPECT_TRUE(monitor->AddFilter(&filter)); - - EXPECT_TRUE(monitor->StartMonitoring()); - EXPECT_TRUE(monitor->StopMonitoring()); - - // Stop the monitoring thread right after it had been started. - // If the monitoring thread got a chance to receive a DBus signal, it would - // post a message to the main thread and signal the main thread wakeup. - // This message will be cleaned out automatically when the filter get - // destructed. Here we also consume the wakeup signal (if there is one) so - // that the testing (main) thread is reset to a clean state. - rtc::Thread::Current()->ProcessMessages(1); - } else { - LOG(LS_WARNING) << "DBus Monitor not started."; - } -} - -TEST(DBusSigFilter, BuildFilterString) { - EXPECT_EQ(DBusSigFilter::BuildFilterString("", "", ""), - (DBUS_TYPE "='" DBUS_SIGNAL "'")); - EXPECT_EQ(DBusSigFilter::BuildFilterString("p", "", ""), - (DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p'")); - EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i", ""), - (DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p'," - DBUS_INTERFACE "='i'")); - EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i","m"), - (DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p'," - DBUS_INTERFACE "='i'," DBUS_MEMBER "='m'")); -} - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB diff --git a/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.cc b/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.cc deleted file mode 100644 index ad51064bc5..0000000000 --- a/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifdef HAVE_DBUS_GLIB - -#include "webrtc/base/libdbusglibsymboltable.h" - -namespace rtc { - -#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME -#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST -#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so.2" -#include "webrtc/base/latebindingsymboltable.cc.def" - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB diff --git a/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.h b/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.h deleted file mode 100644 index b87b4c1744..0000000000 --- a/media/webrtc/trunk/webrtc/base/libdbusglibsymboltable.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ -#define WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ - -#ifdef HAVE_DBUS_GLIB - -#include -#include - -#include "webrtc/base/latebindingsymboltable.h" - -namespace rtc { - -#define LIBDBUS_GLIB_CLASS_NAME LibDBusGlibSymbolTable -// The libdbus-glib symbols we need, as an X-Macro list. -// This list must contain precisely every libdbus-glib function that is used in -// dbus.cc. -#define LIBDBUS_GLIB_SYMBOLS_LIST \ - X(dbus_bus_add_match) \ - X(dbus_connection_add_filter) \ - X(dbus_connection_close) \ - X(dbus_connection_remove_filter) \ - X(dbus_connection_set_exit_on_disconnect) \ - X(dbus_g_bus_get) \ - X(dbus_g_bus_get_private) \ - X(dbus_g_connection_get_connection) \ - X(dbus_g_connection_unref) \ - X(dbus_g_thread_init) \ - X(dbus_message_get_interface) \ - X(dbus_message_get_member) \ - X(dbus_message_get_path) \ - X(dbus_message_get_type) \ - X(dbus_message_iter_get_arg_type) \ - X(dbus_message_iter_get_basic) \ - X(dbus_message_iter_init) \ - X(dbus_message_ref) \ - X(dbus_message_unref) - -#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME -#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST -#include "webrtc/base/latebindingsymboltable.h.def" - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB - -#endif // WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ diff --git a/media/webrtc/trunk/webrtc/build/common.gypi b/media/webrtc/trunk/webrtc/build/common.gypi index 97bf78628e..edcea5a425 100644 --- a/media/webrtc/trunk/webrtc/build/common.gypi +++ b/media/webrtc/trunk/webrtc/build/common.gypi @@ -107,9 +107,6 @@ 'build_openmax_dl%': 1, 'build_opus%': 1, - # Disable by default - 'have_dbus_glib%': 0, - # Enable to use the Mozilla internal settings. 'build_with_mozilla%': 0, @@ -205,14 +202,6 @@ 'WEBRTC_MOZILLA_BUILD', ], }], - ['have_dbus_glib==1', { - 'defines': [ - 'HAVE_DBUS_GLIB', - ], - 'cflags': [ - '= $DBUS_VERSION) - PKG_CHECK_MODULES(MOZ_DBUS_GLIB, dbus-glib-1 >= $DBUS_VERSION) AC_DEFINE(MOZ_ENABLE_DBUS) fi fi diff --git a/testing/docker/base-test/Dockerfile b/testing/docker/base-test/Dockerfile index dd0bf77feb..32471e350a 100644 --- a/testing/docker/base-test/Dockerfile +++ b/testing/docker/base-test/Dockerfile @@ -44,7 +44,6 @@ RUN apt-get update && apt-get install -y --force-yes \ libcanberra-pulse \ libcurl4-openssl-dev \ libdbus-1-dev \ - libdbus-glib-1-dev \ libdrm-intel1:i386 \ libdrm-nouveau1a:i386 \ libdrm-radeon1:i386 \ diff --git a/testing/docker/centos6-build/system-setup.sh b/testing/docker/centos6-build/system-setup.sh index ddb529eed7..458db2b7dd 100644 --- a/testing/docker/centos6-build/system-setup.sh +++ b/testing/docker/centos6-build/system-setup.sh @@ -50,10 +50,6 @@ install check-devel.i686 install check-devel.x86_64 install check.i686 install check.x86_64 -install dbus-glib-devel.i686 -install dbus-glib-devel.x86_64 -install dbus-glib.i686 -install dbus-glib.x86_64 install fontconfig-devel.i686 install fontconfig-devel.x86_64 install fontconfig.i686 diff --git a/testing/docker/firefox-snap/snapcraft.yaml.in b/testing/docker/firefox-snap/snapcraft.yaml.in index 9448c104db..0c1d67cd41 100644 --- a/testing/docker/firefox-snap/snapcraft.yaml.in +++ b/testing/docker/firefox-snap/snapcraft.yaml.in @@ -29,7 +29,6 @@ parts: source: source stage-packages: - libxt6 - - libdbus-glib-1-2 - libasound2 - libpulse0 - libgl1-mesa-dri diff --git a/testing/docker/recipes/ubuntu1204-test-system-setup.sh b/testing/docker/recipes/ubuntu1204-test-system-setup.sh index 4edcf00a12..1a7efce475 100644 --- a/testing/docker/recipes/ubuntu1204-test-system-setup.sh +++ b/testing/docker/recipes/ubuntu1204-test-system-setup.sh @@ -44,7 +44,6 @@ apt_packages+=('libasound2-plugins:i386') apt_packages+=('libcanberra-pulse') apt_packages+=('libcurl4-openssl-dev') apt_packages+=('libdbus-1-dev') -apt_packages+=('libdbus-glib-1-dev') apt_packages+=('libdrm-intel1:i386') apt_packages+=('libdrm-nouveau1a:i386') apt_packages+=('libdrm-radeon1:i386') diff --git a/testing/docker/recipes/ubuntu1604-test-system-setup.sh b/testing/docker/recipes/ubuntu1604-test-system-setup.sh index b58ee7cb18..0a00cf47ec 100644 --- a/testing/docker/recipes/ubuntu1604-test-system-setup.sh +++ b/testing/docker/recipes/ubuntu1604-test-system-setup.sh @@ -37,7 +37,6 @@ apt_packages+=('libasound2-dev') apt_packages+=('libcanberra-pulse') apt_packages+=('libcurl4-openssl-dev') apt_packages+=('libdbus-1-dev') -apt_packages+=('libdbus-glib-1-dev') apt_packages+=('libgconf2-dev') apt_packages+=('libgstreamer-plugins-base0.10-dev') apt_packages+=('libgstreamer0.10-dev') diff --git a/testing/mozharness/configs/builds/releng_base_linux_32_builds.py b/testing/mozharness/configs/builds/releng_base_linux_32_builds.py index 393cf8983e..e7d6b2fe5d 100644 --- a/testing/mozharness/configs/builds/releng_base_linux_32_builds.py +++ b/testing/mozharness/configs/builds/releng_base_linux_32_builds.py @@ -134,7 +134,7 @@ config = { # -devel packages dependencies. So manually install the dependencies # of the above packages. 'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686', - 'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686', + 'check-devel.i686', 'dbus-devel.i686', 'fontconfig-devel.i686', 'glib2-devel.i686', 'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686', 'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686', diff --git a/testing/mozharness/configs/builds/releng_sub_linux_configs/32_artifact.py b/testing/mozharness/configs/builds/releng_sub_linux_configs/32_artifact.py index f016d56069..7d36640842 100644 --- a/testing/mozharness/configs/builds/releng_sub_linux_configs/32_artifact.py +++ b/testing/mozharness/configs/builds/releng_sub_linux_configs/32_artifact.py @@ -90,7 +90,7 @@ config = { # -devel packages dependencies. So manually install the dependencies # of the above packages. 'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686', - 'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686', + 'check-devel.i686', 'dbus-devel.i686', 'fontconfig-devel.i686', 'glib2-devel.i686', 'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686', 'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686', diff --git a/testing/mozharness/configs/builds/releng_sub_linux_configs/32_debug_artifact.py b/testing/mozharness/configs/builds/releng_sub_linux_configs/32_debug_artifact.py index 88ff8450a3..ae4de07176 100644 --- a/testing/mozharness/configs/builds/releng_sub_linux_configs/32_debug_artifact.py +++ b/testing/mozharness/configs/builds/releng_sub_linux_configs/32_debug_artifact.py @@ -96,7 +96,7 @@ config = { # -devel packages dependencies. So manually install the dependencies # of the above packages. 'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686', - 'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686', + 'check-devel.i686', 'dbus-devel.i686', 'fontconfig-devel.i686', 'glib2-devel.i686', 'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686', 'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686', diff --git a/testing/mozharness/configs/hazards/common.py b/testing/mozharness/configs/hazards/common.py index f8d751044e..bfe4a36449 100644 --- a/testing/mozharness/configs/hazards/common.py +++ b/testing/mozharness/configs/hazards/common.py @@ -58,7 +58,7 @@ config = { "gmp-devel", "nspr", "nspr-devel", # For building the browser - "dbus-devel", "dbus-glib-devel", "hal-devel", + "dbus-devel", "hal-devel", "libICE-devel", "libIDL-devel", # For mach resource-usage diff --git a/testing/mozharness/configs/single_locale/linux.py b/testing/mozharness/configs/single_locale/linux.py index 3aa2c03494..a32a52d077 100644 --- a/testing/mozharness/configs/single_locale/linux.py +++ b/testing/mozharness/configs/single_locale/linux.py @@ -92,7 +92,7 @@ config = { # -devel packages dependencies. So manually install the dependencies # of the above packages. 'ORBit2-devel.i686', 'atk-devel.i686', 'cairo-devel.i686', - 'check-devel.i686', 'dbus-devel.i686', 'dbus-glib-devel.i686', + 'check-devel.i686', 'dbus-devel.i686', 'fontconfig-devel.i686', 'glib2-devel.i686', 'hal-devel.i686', 'libICE-devel.i686', 'libIDL-devel.i686', 'libSM-devel.i686', 'libXau-devel.i686', 'libXcomposite-devel.i686', diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index ff7ff5561e..664241bb28 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -218,7 +218,7 @@ if CONFIG['MOZ_SNDIO']: ] if CONFIG['MOZ_ENABLE_DBUS']: - OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS'] + OS_LIBS += CONFIG['MOZ_DBUS_LIBS'] if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3': diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build index 4072fe134f..216d866317 100644 --- a/toolkit/xre/moz.build +++ b/toolkit/xre/moz.build @@ -134,7 +134,6 @@ if CONFIG['MOZ_ENABLE_XREMOTE']: CXXFLAGS += CONFIG['TK_CFLAGS'] CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS'] -CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS'] diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build index 127e4da2bd..633c56e26d 100644 --- a/uriloader/exthandler/moz.build +++ b/uriloader/exthandler/moz.build @@ -122,4 +122,3 @@ if CONFIG['MOZ_ENABLE_DBUS']: if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): CXXFLAGS += CONFIG['TK_CFLAGS'] - CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] From 9454fcf5392692675f99e941653256a09273674a Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Thu, 16 Apr 2026 12:03:33 -0400 Subject: [PATCH 2/9] Issue #3050 - Backport 1379814: Prevent HelperThreads master-task deadlock --- js/src/vm/HelperThreads.cpp | 107 +++++++++++++++++++++++------------- js/src/vm/HelperThreads.h | 2 +- 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index b264b3bb9c..ca5b3020a5 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -860,19 +860,30 @@ GlobalHelperThreadState::waitForAllThreads() template bool -GlobalHelperThreadState::checkTaskThreadLimit(size_t maxThreads) const +GlobalHelperThreadState::checkTaskThreadLimit(size_t maxThreads, bool isMaster) const { if (maxThreads >= threadCount) return true; size_t count = 0; + size_t idle = 0; for (auto& thread : *threads) { - if (thread.currentTask.isSome() && thread.currentTask->is()) - count++; + if (thread.currentTask.isSome()) { + if (thread.currentTask->is()) + count++; + } else { + idle++; + } if (count >= maxThreads) return false; } + // At least the current thread is idle. + MOZ_ASSERT(idle > 0); + + if (isMaster && idle <= 1) + return false; + return true; } @@ -1091,7 +1102,8 @@ GlobalHelperThreadState::pendingIonCompileHasSufficientPriority( bool GlobalHelperThreadState::canStartParseTask(const AutoLockHelperThreadState& lock) { - return !parseWorklist(lock).empty() && checkTaskThreadLimit(maxParseThreads()); + return !parseWorklist(lock).empty() && + checkTaskThreadLimit(maxParseThreads(), /* isMaster = */ true); } bool @@ -1892,49 +1904,68 @@ HelperThread::threadLoop() while (true) { MOZ_ASSERT(idle()); - // Block until a task is available. Save the value of whether we are - // going to do an Ion compile, in case the value returned by the method - // changes. - bool ionCompile = false; + js::oom::ThreadType task; while (true) { if (terminate) return; - if ((ionCompile = HelperThreadState().pendingIonCompileHasSufficientPriority(lock)) || - HelperThreadState().canStartWasmCompile(lock) || - HelperThreadState().canStartPromiseTask(lock) || - HelperThreadState().canStartParseTask(lock) || - HelperThreadState().canStartCompressionTask(lock) || - HelperThreadState().canStartGCHelperTask(lock) || - HelperThreadState().canStartGCParallelTask(lock)) - { + + // Select the task type to run. Task priority is determined + // exclusively here. + // + // The selectors may depend on the HelperThreadState not changing + // between task selection and task execution, in particular, on new + // tasks not being added (because of the lifo structure of the work + // lists). Unlocking the HelperThreadState between task selection + // and execution is not well-defined. + if (HelperThreadState().canStartGCParallelTask(lock)) + task = js::oom::THREAD_TYPE_GCPARALLEL; + else if (HelperThreadState().canStartGCHelperTask(lock)) + task = js::oom::THREAD_TYPE_GCHELPER; + else if (HelperThreadState().pendingIonCompileHasSufficientPriority(lock)) + task = js::oom::THREAD_TYPE_ION; + else if (HelperThreadState().canStartWasmCompile(lock)) + task = js::oom::THREAD_TYPE_ASMJS; + else if (HelperThreadState().canStartPromiseTask(lock)) + task = js::oom::THREAD_TYPE_PROMISE_TASK; + else if (HelperThreadState().canStartParseTask(lock)) + task = js::oom::THREAD_TYPE_PARSE; + else if (HelperThreadState().canStartCompressionTask(lock)) + task = js::oom::THREAD_TYPE_COMPRESS; + else + task = js::oom::THREAD_TYPE_NONE; + + if (task != js::oom::THREAD_TYPE_NONE) break; - } + HelperThreadState().wait(lock, GlobalHelperThreadState::PRODUCER); } - if (ionCompile) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_ION); - handleIonWorkload(lock); - } else if (HelperThreadState().canStartWasmCompile(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_ASMJS); - handleWasmWorkload(lock); - } else if (HelperThreadState().canStartPromiseTask(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_PROMISE_TASK); - handlePromiseTaskWorkload(lock); - } else if (HelperThreadState().canStartParseTask(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_PARSE); - handleParseWorkload(lock, stackLimit); - } else if (HelperThreadState().canStartCompressionTask(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_COMPRESS); - handleCompressionWorkload(lock); - } else if (HelperThreadState().canStartGCHelperTask(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_GCHELPER); - handleGCHelperWorkload(lock); - } else if (HelperThreadState().canStartGCParallelTask(lock)) { - js::oom::SetThreadType(js::oom::THREAD_TYPE_GCPARALLEL); + js::oom::SetThreadType(task); + switch (task) { + case js::oom::THREAD_TYPE_GCPARALLEL: handleGCParallelWorkload(lock); - } else { + break; + case js::oom::THREAD_TYPE_GCHELPER: + handleGCHelperWorkload(lock); + break; + case js::oom::THREAD_TYPE_ION: + handleIonWorkload(lock); + break; + case js::oom::THREAD_TYPE_ASMJS: + handleWasmWorkload(lock); + break; + case js::oom::THREAD_TYPE_PROMISE_TASK: + handlePromiseTaskWorkload(lock); + break; + case js::oom::THREAD_TYPE_PARSE: + handleParseWorkload(lock, stackLimit); + break; + case js::oom::THREAD_TYPE_COMPRESS: + handleCompressionWorkload(lock); + break; + default: MOZ_CRASH("No task to perform"); } + js::oom::SetThreadType(js::oom::THREAD_TYPE_NONE); } } diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index ebd4c9b9cb..5a1cc02e9a 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -256,7 +256,7 @@ class GlobalHelperThreadState void waitForAllThreads(); template - bool checkTaskThreadLimit(size_t maxThreads) const; + bool checkTaskThreadLimit(size_t maxThreads, bool isMaster = false) const; private: From 52b3fada95088f6150ef5f0527e17a420146fbbe Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Thu, 16 Apr 2026 12:10:10 -0400 Subject: [PATCH 3/9] Issue #3050 - Backport 1431353: Remove off-thread parse thread limit --- js/src/vm/HelperThreads.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index ca5b3020a5..6d86db53d6 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -927,11 +927,7 @@ GlobalHelperThreadState::maxParseThreads() const if (IsHelperThreadSimulatingOOM(js::oom::THREAD_TYPE_PARSE)) return 1; - // Don't allow simultaneous off thread parses, to reduce contention on the - // atoms table. Note that wasm compilation depends on this to avoid - // stalling the helper thread, as off thread parse tasks can trigger and - // block on other off thread wasm compilation tasks. - return 1; + return threadCount; } size_t From dd64525180d4a00facf709411a7ed06196c2d656 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Fri, 17 Apr 2026 22:19:38 -0400 Subject: [PATCH 4/9] Issue #3049 - backport libffi loongarch support --- config/external/ffi/moz.build | 2 + js/ffi.configure | 7 +- js/src/ctypes/libffi/src/loongarch64/ffi.c | 600 ++++++++++++++++++ .../ctypes/libffi/src/loongarch64/ffitarget.h | 81 +++ js/src/ctypes/libffi/src/loongarch64/sysv.S | 327 ++++++++++ 5 files changed, 1015 insertions(+), 2 deletions(-) create mode 100644 js/src/ctypes/libffi/src/loongarch64/ffi.c create mode 100644 js/src/ctypes/libffi/src/loongarch64/ffitarget.h create mode 100644 js/src/ctypes/libffi/src/loongarch64/sysv.S diff --git a/config/external/ffi/moz.build b/config/external/ffi/moz.build index 8710ebab7a..543d07a975 100644 --- a/config/external/ffi/moz.build +++ b/config/external/ffi/moz.build @@ -101,6 +101,8 @@ else: ASFLAGS += ['-no-integrated-as'] elif CONFIG['FFI_TARGET'] == 'AARCH64': ffi_srcs = ('sysv.S', 'ffi.c') + elif CONFIG['FFI_TARGET'] == 'LOONGARCH64': + ffi_srcs = ('ffi.c', 'sysv.S') elif CONFIG['FFI_TARGET'] == 'X86': ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S') elif CONFIG['FFI_TARGET'] == 'X86_64': diff --git a/js/ffi.configure b/js/ffi.configure index 96b6ad6d69..641105e78a 100644 --- a/js/ffi.configure +++ b/js/ffi.configure @@ -6,7 +6,7 @@ @depends(target) def force_system_ffi(target): # Pre-emptively move to system ffi for non-tier one platforms. - if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'): + if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64', 'loongarch64'): return True imply_option('--with-system-ffi', force_system_ffi, "target") @@ -27,7 +27,7 @@ add_old_configure_assignment('MOZ_SYSTEM_FFI', depends_if(system_ffi)(lambda _: # Target selection, based on ffi/configure.ac. @depends_when(target, when=building_ffi) def ffi_target(target): - if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'): + if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64', 'loongarch64'): die('Building libffi from the tree is not supported on this platform. ' 'Use --with-system-ffi instead.') @@ -50,6 +50,9 @@ def ffi_target(target): elif target.cpu == 'aarch64': target_dir = 'aarch64' target_name = 'AARCH64' + elif target.cpu == 'loongarch64': + target_dir = 'loongarch64' + target_name = 'LOONGARCH64' else: target_dir = 'x86' target_name = target.cpu.upper() diff --git a/js/src/ctypes/libffi/src/loongarch64/ffi.c b/js/src/ctypes/libffi/src/loongarch64/ffi.c new file mode 100644 index 0000000000..234afba673 --- /dev/null +++ b/js/src/ctypes/libffi/src/loongarch64/ffi.c @@ -0,0 +1,600 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2022 Xu Chenghua + 2022 Cheng Lulu + Based on RISC-V port + + LoongArch Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include + +#include +#include + +#if defined(__loongarch_soft_float) +# define ABI_FRLEN 0 +#elif defined(__loongarch_single_float) +# define ABI_FRLEN 32 +# define ABI_FLOAT float +#elif defined(__loongarch_double_float) +# define ABI_FRLEN 64 +# define ABI_FLOAT double +#else +#error unsupported LoongArch floating-point ABI +#endif + +#define NARGREG 8 +#define STKALIGN 16 +#define MAXCOPYARG (2 * sizeof (double)) + +/* call_context registers + - 8 floating point parameter/result registers. + - 8 integer parameter/result registers. + - 2 registers used by the assembly code to in-place construct its own + stack frame + - frame register + - return register +*/ +typedef struct call_context +{ + ABI_FLOAT fa[8]; + size_t a[10]; +} call_context; + +typedef struct call_builder +{ + call_context *aregs; + int used_integer; + int used_float; + size_t *used_stack; + size_t *stack; + size_t next_struct_area; +} call_builder; + +/* Integer (not pointer) less than ABI GRLEN. */ +/* FFI_TYPE_INT does not appear to be used. */ +#if __SIZEOF_POINTER__ == 8 +# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT64) +#else +# define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT32) +#endif + +#if ABI_FRLEN +typedef struct float_struct_info +{ + char as_elements; + char type1; + char offset2; + char type2; +} float_struct_info; + +#if ABI_FRLEN >= 64 +# define IS_FLOAT(type) ((type) >= FFI_TYPE_FLOAT && (type) <= FFI_TYPE_DOUBLE) +#else +# define IS_FLOAT(type) ((type) == FFI_TYPE_FLOAT) +#endif + +static ffi_type ** +flatten_struct (ffi_type *in, ffi_type **out, ffi_type **out_end) +{ + int i; + + if (out == out_end) + return out; + if (in->type != FFI_TYPE_STRUCT) + *(out++) = in; + else + for (i = 0; in->elements[i]; i++) + out = flatten_struct (in->elements[i], out, out_end); + return out; +} + +/* Structs with at most two fields after flattening, one of which is of + floating point type, are passed in multiple registers if sufficient + registers are available. */ +static float_struct_info +struct_passed_as_elements (call_builder *cb, ffi_type *top) +{ + float_struct_info ret = {0, 0, 0, 0}; + ffi_type *fields[3]; + int num_floats, num_ints; + int num_fields = flatten_struct (top, fields, fields + 3) - fields; + + if (num_fields == 1) + { + if (IS_FLOAT (fields[0]->type)) + { + ret.as_elements = 1; + ret.type1 = fields[0]->type; + } + } + else if (num_fields == 2) + { + num_floats = IS_FLOAT (fields[0]->type) + IS_FLOAT (fields[1]->type); + num_ints = IS_INT (fields[0]->type) + IS_INT (fields[1]->type); + if (num_floats == 0 || num_floats + num_ints != 2) + return ret; + if (cb->used_float + num_floats > NARGREG + || cb->used_integer + (2 - num_floats) > NARGREG) + return ret; + if (!IS_FLOAT (fields[0]->type) && !IS_FLOAT (fields[1]->type)) + return ret; + + ret.type1 = fields[0]->type; + ret.type2 = fields[1]->type; + ret.offset2 = ALIGN (fields[0]->size, fields[1]->alignment); + ret.as_elements = 1; + } + return ret; +} +#endif + +/* Allocates a single register, float register, or GRLEN-sized stack slot to a + datum. */ +static void +marshal_atom (call_builder *cb, int type, void *data) +{ + size_t value = 0; + switch (type) + { + case FFI_TYPE_UINT8: + value = *(uint8_t *) data; + break; + case FFI_TYPE_SINT8: + value = *(int8_t *) data; + break; + case FFI_TYPE_UINT16: + value = *(uint16_t *) data; + break; + case FFI_TYPE_SINT16: + value = *(int16_t *) data; + break; + /* 32-bit quantities are always sign-extended in the ABI. */ + case FFI_TYPE_UINT32: + value = *(int32_t *) data; + break; + case FFI_TYPE_SINT32: + value = *(int32_t *) data; + break; +#if __SIZEOF_POINTER__ == 8 + case FFI_TYPE_UINT64: + value = *(uint64_t *) data; + break; + case FFI_TYPE_SINT64: + value = *(int64_t *) data; + break; +#endif + case FFI_TYPE_POINTER: + value = *(size_t *) data; + break; + +#if ABI_FRLEN >= 32 + case FFI_TYPE_FLOAT: + *(float *)(cb->aregs->fa + cb->used_float++) = *(float *) data; + return; +#endif +#if ABI_FRLEN >= 64 + case FFI_TYPE_DOUBLE: + (cb->aregs->fa[cb->used_float++]) = *(double *) data; + return; +#endif + default: + FFI_ASSERT (0); + break; + } + + if (cb->used_integer == NARGREG) + *cb->used_stack++ = value; + else + cb->aregs->a[cb->used_integer++] = value; +} + +static void +unmarshal_atom (call_builder *cb, int type, void *data) +{ + size_t value; + switch (type) + { +#if ABI_FRLEN >= 32 + case FFI_TYPE_FLOAT: + *(float *) data = *(float *)(cb->aregs->fa + cb->used_float++); + return; +#endif +#if ABI_FRLEN >= 64 + case FFI_TYPE_DOUBLE: + *(double *) data = cb->aregs->fa[cb->used_float++]; + return; +#endif + } + + if (cb->used_integer == NARGREG) + value = *cb->used_stack++; + else + value = cb->aregs->a[cb->used_integer++]; + + switch (type) + { + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: +#if __SIZEOF_POINTER__ == 8 + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: +#endif + case FFI_TYPE_POINTER: + *(ffi_arg *)data = value; + break; + default: + FFI_ASSERT (0); + break; + } +} + +/* Allocate and copy a structure that is passed by value on the stack and + return a pointer to it. */ +static void * +allocate_and_copy_struct_to_stack (call_builder *cb, void *data, + ffi_type *type) +{ + size_t dest = cb->next_struct_area - type->size; + + dest = ALIGN_DOWN (dest, type->alignment); + cb->next_struct_area = dest; + + return memcpy ((char *)cb->stack + dest, data, type->size); +} + +/* Adds an argument to a call, or a not by reference return value. */ +static void +marshal (call_builder *cb, ffi_type *type, int var, void *data) +{ + size_t realign[2]; + +#if ABI_FRLEN + if (!var && type->type == FFI_TYPE_STRUCT) + { + float_struct_info fsi = struct_passed_as_elements (cb, type); + if (fsi.as_elements) + { + marshal_atom (cb, fsi.type1, data); + if (fsi.offset2) + marshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2); + return; + } + } + + if (!var && cb->used_float < NARGREG + && IS_FLOAT (type->type)) + { + marshal_atom (cb, type->type, data); + return; + } + + double promoted; + if (var && type->type == FFI_TYPE_FLOAT) + { + /* C standard requires promoting float -> double for variable arg. */ + promoted = *(float *) data; + type = &ffi_type_double; + data = &promoted; + } +#endif + + if (type->size > 2 * __SIZEOF_POINTER__) + /* Pass by reference. */ + { + allocate_and_copy_struct_to_stack (cb, data, type); + data = (char *)cb->stack + cb->next_struct_area; + marshal_atom (cb, FFI_TYPE_POINTER, &data); + } + else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER) + marshal_atom (cb, type->type, data); + else + { + /* Overlong integers, soft-float floats, and structs without special + float handling are treated identically from this point on. */ + + /* Variadics are aligned even in registers. */ + if (type->alignment > __SIZEOF_POINTER__) + { + if (var) + cb->used_integer = ALIGN (cb->used_integer, 2); + cb->used_stack + = (size_t *) ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__); + } + + memcpy (realign, data, type->size); + if (type->size > 0) + marshal_atom (cb, FFI_TYPE_POINTER, realign); + if (type->size > __SIZEOF_POINTER__) + marshal_atom (cb, FFI_TYPE_POINTER, realign + 1); + } +} + +/* For arguments passed by reference returns the pointer, otherwise the arg + is copied (up to MAXCOPYARG bytes). */ +static void * +unmarshal (call_builder *cb, ffi_type *type, int var, void *data) +{ + size_t realign[2]; + void *pointer; + +#if ABI_FRLEN + if (!var && type->type == FFI_TYPE_STRUCT) + { + float_struct_info fsi = struct_passed_as_elements (cb, type); + if (fsi.as_elements) + { + unmarshal_atom (cb, fsi.type1, data); + if (fsi.offset2) + unmarshal_atom (cb, fsi.type2, ((char *) data) + fsi.offset2); + return data; + } + } + + if (!var && cb->used_float < NARGREG + && IS_FLOAT (type->type)) + { + unmarshal_atom (cb, type->type, data); + return data; + } + + if (var && type->type == FFI_TYPE_FLOAT) + { + int m = cb->used_integer; + void *promoted + = m < NARGREG ? cb->aregs->a + m : cb->used_stack + m - NARGREG + 1; + *(float *) promoted = *(double *) promoted; + } +#endif + + if (type->size > 2 * __SIZEOF_POINTER__) + { + /* Pass by reference. */ + unmarshal_atom (cb, FFI_TYPE_POINTER, (char *) &pointer); + return pointer; + } + else if (IS_INT (type->type) || type->type == FFI_TYPE_POINTER) + { + unmarshal_atom (cb, type->type, data); + return data; + } + else + { + /* Overlong integers, soft-float floats, and structs without special + float handling are treated identically from this point on. */ + + /* Variadics are aligned even in registers. */ + if (type->alignment > __SIZEOF_POINTER__) + { + if (var) + cb->used_integer = ALIGN (cb->used_integer, 2); + cb->used_stack + = (size_t *) ALIGN (cb->used_stack, 2 * __SIZEOF_POINTER__); + } + + if (type->size > 0) + unmarshal_atom (cb, FFI_TYPE_POINTER, realign); + if (type->size > __SIZEOF_POINTER__) + unmarshal_atom (cb, FFI_TYPE_POINTER, realign + 1); + memcpy (data, realign, type->size); + return data; + } +} + +static int +passed_by_ref (call_builder *cb, ffi_type *type, int var) +{ +#if ABI_FRLEN + if (!var && type->type == FFI_TYPE_STRUCT) + { + float_struct_info fsi = struct_passed_as_elements (cb, type); + if (fsi.as_elements) + return 0; + } +#endif + + return type->size > 2 * __SIZEOF_POINTER__; +} + +/* Perform machine dependent cif processing. */ +ffi_status +ffi_prep_cif_machdep (ffi_cif *cif) +{ + cif->loongarch_nfixedargs = cif->nargs; + return FFI_OK; +} + +/* Perform machine dependent cif processing when we have a variadic + function. */ +ffi_status +ffi_prep_cif_machdep_var (ffi_cif *cif, unsigned int nfixedargs, + unsigned int ntotalargs) +{ + cif->loongarch_nfixedargs = nfixedargs; + return FFI_OK; +} + +/* Low level routine for calling functions. */ +extern void ffi_call_asm (void *stack, struct call_context *regs, + void (*fn) (void), void *closure) FFI_HIDDEN; + +static void +ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + /* This is a conservative estimate, assuming a complex return value and + that all remaining arguments are long long / __int128 */ + size_t arg_bytes = cif->bytes; + size_t rval_bytes = 0; + if (rvalue == NULL && cif->rtype->size > 2 * __SIZEOF_POINTER__) + rval_bytes = ALIGN (cif->rtype->size, STKALIGN); + size_t alloc_size = arg_bytes + rval_bytes + sizeof (call_context); + + /* The assembly code will deallocate all stack data at lower addresses + than the argument region, so we need to allocate the frame and the + return value after the arguments in a single allocation. */ + /* Argument region must be 16-byte aligned in LP64 ABIs. */ + size_t alloc_base = ALIGN (alloca (alloc_size + STKALIGN - 1), STKALIGN); + + if (rval_bytes) + rvalue = (void *) (alloc_base + arg_bytes); + + call_builder cb; + cb.used_float = cb.used_integer = 0; + cb.aregs = (call_context *) (alloc_base + arg_bytes + rval_bytes); + cb.used_stack = (void *) alloc_base; + cb.stack = (void *) alloc_base; + cb.next_struct_area = arg_bytes; + + int return_by_ref = passed_by_ref (&cb, cif->rtype, 0); + if (return_by_ref) + cb.aregs->a[cb.used_integer++] = (size_t)rvalue; + + int i; + for (i = 0; i < cif->nargs; i++) + marshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs, + avalue[i]); + + ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure); + + cb.used_float = cb.used_integer = 0; + if (!return_by_ref && rvalue) + unmarshal (&cb, cif->rtype, 0, rvalue); +} + +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + +extern void ffi_closure_asm (void) FFI_HIDDEN; + +ffi_status +ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, void *codeloc) +{ + uint32_t *tramp = (uint32_t *) &closure->tramp[0]; + uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm; + + if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI) + return FFI_BAD_ABI; + +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + ffi_tramp_set_parms (closure->ftramp, ffi_closure_asm, closure); + goto out; + } +#endif + + /* Fill the dynamic trampoline. We will call ffi_closure_inner with codeloc, + not closure, but as long as the memory is readable it should work. */ + tramp[0] = 0x1800000c; /* pcaddi $t0, 0 (i.e. $t0 <- tramp) */ + tramp[1] = 0x28c0418d; /* ld.d $t1, $t0, 16 */ + tramp[2] = 0x4c0001a0; /* jirl $zero, $t1, 0 */ + tramp[3] = 0x03400000; /* nop */ + tramp[4] = fn; + tramp[5] = fn >> 32; + + __builtin___clear_cache (codeloc, codeloc + FFI_TRAMPOLINE_SIZE); + +#if defined(FFI_EXEC_STATIC_TRAMP) +out: +#endif + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + return FFI_OK; +} + +/* Called by the assembly code with aregs pointing to saved argument registers + and stack pointing to the stacked arguments. Return values passed in + registers will be reloaded from aregs. */ +void FFI_HIDDEN +ffi_closure_inner (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, size_t *stack, call_context *aregs) +{ + void **avalue = alloca (cif->nargs * sizeof (void *)); + /* Storage for arguments which will be copied by unmarshal(). We could + theoretically avoid the copies in many cases and use at most 128 bytes + of memory, but allocating disjoint storage for each argument is + simpler. */ + char *astorage = alloca (cif->nargs * MAXCOPYARG); + void *rvalue; + call_builder cb; + int return_by_ref; + int i; + + cb.aregs = aregs; + cb.used_integer = cb.used_float = 0; + cb.used_stack = stack; + + return_by_ref = passed_by_ref (&cb, cif->rtype, 0); + if (return_by_ref) + unmarshal (&cb, &ffi_type_pointer, 0, &rvalue); + else + rvalue = alloca (cif->rtype->size); + + for (i = 0; i < cif->nargs; i++) + avalue[i] + = unmarshal (&cb, cif->arg_types[i], i >= cif->loongarch_nfixedargs, + astorage + i * MAXCOPYARG); + + fun (cif, rvalue, avalue, user_data); + + if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) + { + cb.used_integer = cb.used_float = 0; + marshal (&cb, cif->rtype, 0, rvalue); + } +} + +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *tramp_size = 16; + /* A mapping size of 64K is chosen to cover the page sizes of 4K, 16K, and + 64K. */ + *map_size = 1 << 16; + return &trampoline_code_table; +} +#endif diff --git a/js/src/ctypes/libffi/src/loongarch64/ffitarget.h b/js/src/ctypes/libffi/src/loongarch64/ffitarget.h new file mode 100644 index 0000000000..f7d90c5773 --- /dev/null +++ b/js/src/ctypes/libffi/src/loongarch64/ffitarget.h @@ -0,0 +1,81 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2022 Xu Chenghua + 2022 Cheng Lulu + + Target configuration macros for LoongArch. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error \ + "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +#ifndef __loongarch__ +#error \ + "libffi was configured for a LoongArch target but this does not appear to be a LoongArch compiler." +#endif + +#ifndef LIBFFI_ASM + +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi +{ + FFI_FIRST_ABI = 0, + FFI_LP64S, + FFI_LP64F, + FFI_LP64D, + FFI_LAST_ABI, + +#if defined(__loongarch64) +#if defined(__loongarch_soft_float) + FFI_DEFAULT_ABI = FFI_LP64S +#elif defined(__loongarch_single_float) + FFI_DEFAULT_ABI = FFI_LP64F +#elif defined(__loongarch_double_float) + FFI_DEFAULT_ABI = FFI_LP64D +#else +#error unsupported LoongArch floating-point ABI +#endif +#else +#error unsupported LoongArch base architecture +#endif +} ffi_abi; + +#endif /* LIBFFI_ASM */ + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_NATIVE_RAW_API 0 +#define FFI_EXTRA_CIF_FIELDS \ + unsigned loongarch_nfixedargs; \ + unsigned loongarch_unused; +#define FFI_TARGET_SPECIFIC_VARIADIC +#endif diff --git a/js/src/ctypes/libffi/src/loongarch64/sysv.S b/js/src/ctypes/libffi/src/loongarch64/sysv.S new file mode 100644 index 0000000000..aa7bde2c1e --- /dev/null +++ b/js/src/ctypes/libffi/src/loongarch64/sysv.S @@ -0,0 +1,327 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2022 Xu Chenghua + 2022 Cheng Lulu + + LoongArch Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include +#include + +/* Define aliases so that we can handle all ABIs uniformly. */ + +#if __SIZEOF_POINTER__ == 8 +# define PTRS 8 +# define LARG ld.d +# define SARG st.d +#else +# define PTRS 4 +# define LARG ld.w +# define SARG st.w +#endif + +#if defined(__loongarch_single_float) +# define FLTS 4 +# define FLD fld.w +# define FST fst.w +#elif defined(__loongarch_double_float) +# define FLTS 8 +# define FLARG fld.d +# define FSARG fst.d +#elif defined(__loongarch_soft_float) +# define FLTS 0 +#else +#error unsupported LoongArch floating-point ABI +#endif + + .text + .globl ffi_call_asm + .type ffi_call_asm, @function + .hidden ffi_call_asm +/* struct call_context + { + ABI_FLOAT fa[8]; + size_t a[10]; + } + + - 8 floating point parameter/result registers (fa[0] - fa[7]) + - 8 integer parameter/result registers (a[0] - a[7]) + - 2 registers used by the assembly code to in-place construct its own stack + frame. + - frame pointer (a[8]) + - return address (a[9]) + + void ffi_call_asm (size_t *stackargs, struct call_context *regargs, + void (*fn)(void), void *closure); */ + +#define FRAME_LEN (8 * FLTS + 10 * PTRS) + +ffi_call_asm: + .cfi_startproc + + /* We are NOT going to set up an ordinary stack frame. In order to pass + the stacked args to the called function, we adjust our stack pointer + to a0, which is in the _caller's_ alloca area. We establish our own + stack frame at the end of the call_context. + + Anything below the arguments will be freed at this point, although + we preserve the call_context so that it can be read back in the + caller. */ + + .cfi_def_cfa 5, FRAME_LEN # Interim CFA based on a1. + SARG $fp, $a1, FRAME_LEN - 2*PTRS + .cfi_offset 22, -2*PTRS + SARG $ra, $a1, FRAME_LEN - 1*PTRS + .cfi_offset 1, -1*PTRS + + addi.d $fp, $a1, FRAME_LEN + move $sp, $a0 + .cfi_def_cfa 22, 0 # Our frame is fully set up. + + # Load arguments. + move $t1, $a2 + move $t2, $a3 + +#if FLTS + FLARG $fa0, $fp, -FRAME_LEN+0*FLTS + FLARG $fa1, $fp, -FRAME_LEN+1*FLTS + FLARG $fa2, $fp, -FRAME_LEN+2*FLTS + FLARG $fa3, $fp, -FRAME_LEN+3*FLTS + FLARG $fa4, $fp, -FRAME_LEN+4*FLTS + FLARG $fa5, $fp, -FRAME_LEN+5*FLTS + FLARG $fa6, $fp, -FRAME_LEN+6*FLTS + FLARG $fa7, $fp, -FRAME_LEN+7*FLTS +#endif + + LARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS + LARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS + LARG $a2, $fp, -FRAME_LEN+8*FLTS+2*PTRS + LARG $a3, $fp, -FRAME_LEN+8*FLTS+3*PTRS + LARG $a4, $fp, -FRAME_LEN+8*FLTS+4*PTRS + LARG $a5, $fp, -FRAME_LEN+8*FLTS+5*PTRS + LARG $a6, $fp, -FRAME_LEN+8*FLTS+6*PTRS + LARG $a7, $fp, -FRAME_LEN+8*FLTS+7*PTRS + + /* Call */ + jirl $ra, $t1, 0 + +#if FLTS + /* Save return values - only a0/a1 (fa0/fa1) are used. */ + FSARG $fa0, $fp, -FRAME_LEN+0*FLTS + FSARG $fa1, $fp, -FRAME_LEN+1*FLTS +#endif + + SARG $a0, $fp, -FRAME_LEN+8*FLTS+0*PTRS + SARG $a1, $fp, -FRAME_LEN+8*FLTS+1*PTRS + + /* Restore and return. */ + addi.d $sp, $fp, -FRAME_LEN + .cfi_def_cfa 3, FRAME_LEN + LARG $ra, $fp, -1*PTRS + .cfi_restore 1 + LARG $fp, $fp, -2*PTRS + .cfi_restore 22 + jr $ra + .cfi_endproc + .size ffi_call_asm, .-ffi_call_asm + + +/* ffi_closure_asm. Expects address of the passed-in ffi_closure in t0. + void ffi_closure_inner (ffi_cif *cif, + void (*fun)(ffi_cif *, void *, void **, void *), + void *user_data, + size_t *stackargs, struct call_context *regargs) */ + + .globl ffi_closure_asm + .hidden ffi_closure_asm + .type ffi_closure_asm, @function + +ffi_closure_asm: + .cfi_startproc + addi.d $sp, $sp, -FRAME_LEN + .cfi_def_cfa_offset FRAME_LEN + + /* Make a frame. */ + SARG $fp, $sp, FRAME_LEN - 2*PTRS + .cfi_offset 22, -2*PTRS + SARG $ra, $sp, FRAME_LEN - 1*PTRS + .cfi_offset 1, -1*PTRS + addi.d $fp, $sp, FRAME_LEN + + /* Save arguments. */ +#if FLTS + FSARG $fa0, $sp, 0*FLTS + FSARG $fa1, $sp, 1*FLTS + FSARG $fa2, $sp, 2*FLTS + FSARG $fa3, $sp, 3*FLTS + FSARG $fa4, $sp, 4*FLTS + FSARG $fa5, $sp, 5*FLTS + FSARG $fa6, $sp, 6*FLTS + FSARG $fa7, $sp, 7*FLTS +#endif + + SARG $a0, $sp, 8*FLTS+0*PTRS + SARG $a1, $sp, 8*FLTS+1*PTRS + SARG $a2, $sp, 8*FLTS+2*PTRS + SARG $a3, $sp, 8*FLTS+3*PTRS + SARG $a4, $sp, 8*FLTS+4*PTRS + SARG $a5, $sp, 8*FLTS+5*PTRS + SARG $a6, $sp, 8*FLTS+6*PTRS + SARG $a7, $sp, 8*FLTS+7*PTRS + + /* Enter C */ + LARG $a0, $t0, FFI_TRAMPOLINE_SIZE+0*PTRS + LARG $a1, $t0, FFI_TRAMPOLINE_SIZE+1*PTRS + LARG $a2, $t0, FFI_TRAMPOLINE_SIZE+2*PTRS + addi.d $a3, $sp, FRAME_LEN + move $a4, $sp + + bl ffi_closure_inner + + /* Return values. */ +#if FLTS + FLARG $fa0, $sp, 0*FLTS + FLARG $fa1, $sp, 1*FLTS +#endif + + LARG $a0, $sp, 8*FLTS+0*PTRS + LARG $a1, $sp, 8*FLTS+1*PTRS + + /* Restore and return. */ + LARG $ra, $sp, FRAME_LEN-1*PTRS + .cfi_restore 1 + LARG $fp, $sp, FRAME_LEN-2*PTRS + .cfi_restore 22 + addi.d $sp, $sp, FRAME_LEN + .cfi_def_cfa_offset 0 + jr $ra + .cfi_endproc + .size ffi_closure_asm, .-ffi_closure_asm + +/* Static trampoline code table, in which each element is a trampoline. + + The trampoline clobbers t0 and t1, but we don't save them on the stack + because our psABI explicitly says they are scratch registers, at least for + ELF. Our dynamic trampoline is already clobbering them anyway. + + The trampoline has two parameters - target code to jump to and data for + the target code. The trampoline extracts the parameters from its parameter + block (see tramp_table_map()). The trampoline saves the data address in + t0 and jumps to the target code. As ffi_closure_asm() already expects the + data address to be in t0, we don't need a "ffi_closure_asm_alt". */ + +#if defined(FFI_EXEC_STATIC_TRAMP) + .align 16 + .globl trampoline_code_table + .hidden trampoline_code_table + .type trampoline_code_table, @function + +trampoline_code_table: + + .rept 65536 / 16 + pcaddu12i $t1, 16 # 65536 >> 12 + ld.d $t0, $t1, 0 + ld.d $t1, $t1, 8 + jirl $zero, $t1, 0 + .endr + .size trampoline_code_table, .-trampoline_code_table + + .align 2 +#endif + +/* ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2. + void ffi_closure_inner (ffi_cif *cif, + void (*fun)(ffi_cif *, void *, void **, void *), + void *user_data, + size_t *stackargs, struct call_context *regargs) */ + + .globl ffi_go_closure_asm + .hidden ffi_go_closure_asm + .type ffi_go_closure_asm, @function + +ffi_go_closure_asm: + .cfi_startproc + addi.d $sp, $sp, -FRAME_LEN + .cfi_def_cfa_offset FRAME_LEN + + /* Make a frame. */ + SARG $fp, $sp, FRAME_LEN - 2*PTRS + .cfi_offset 22, -2*PTRS + SARG $ra, $sp, FRAME_LEN - 1*PTRS + .cfi_offset 1, -1*PTRS + addi.d $fp, $sp, FRAME_LEN + + /* Save arguments. */ +#if FLTS + FSARG $fa0, $sp, 0*FLTS + FSARG $fa1, $sp, 1*FLTS + FSARG $fa2, $sp, 2*FLTS + FSARG $fa3, $sp, 3*FLTS + FSARG $fa4, $sp, 4*FLTS + FSARG $fa5, $sp, 5*FLTS + FSARG $fa6, $sp, 6*FLTS + FSARG $fa7, $sp, 7*FLTS +#endif + + SARG $a0, $sp, 8*FLTS+0*PTRS + SARG $a1, $sp, 8*FLTS+1*PTRS + SARG $a2, $sp, 8*FLTS+2*PTRS + SARG $a3, $sp, 8*FLTS+3*PTRS + SARG $a4, $sp, 8*FLTS+4*PTRS + SARG $a5, $sp, 8*FLTS+5*PTRS + SARG $a6, $sp, 8*FLTS+6*PTRS + SARG $a7, $sp, 8*FLTS+7*PTRS + + /* Enter C */ + LARG $a0, $t2, 1*PTRS + LARG $a1, $t2, 2*PTRS + move $a2, $t2 + addi.d $a3, $sp, FRAME_LEN + move $a4, $sp + + bl ffi_closure_inner + + /* Return values. */ +#if FLTS + FLARG $fa0, $sp, 0*FLTS + FLARG $fa1, $sp, 1*FLTS +#endif + + LARG $a0, $sp, 8*FLTS+0*PTRS + LARG $a1, $sp, 8*FLTS+1*PTRS + + /* Restore and return. */ + LARG $ra, $sp, FRAME_LEN-1*PTRS + .cfi_restore 1 + LARG $fp, $sp, FRAME_LEN-2*PTRS + .cfi_restore 22 + addi.d $sp, $sp, FRAME_LEN + .cfi_def_cfa_offset 0 + jr $ra + .cfi_endproc + .size ffi_go_closure_asm, .-ffi_go_closure_asm + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",%progbits +#endif From e98a43e46c8f6a15d188f2aa8b6f13b700cb1127 Mon Sep 17 00:00:00 2001 From: Jeremy Andrews Date: Sat, 18 Apr 2026 16:37:30 -0500 Subject: [PATCH 5/9] Issue #3038 - Fix ARM assembler issues in libpixman. Probably not strictly related to Python 3 changes, but small enough that expanding the scope to general UXP build issues on Debian won't be too bad an idea, since the issue was reported there anyway. Likely related to binutils updates reporter mentioned. --- gfx/cairo/libpixman/src/pixman-arm-simd-asm.S | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S index a74a0a8f34..959a0ba798 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S +++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S @@ -818,13 +818,13 @@ generate_composite_function \ .macro over_white_8888_8888_ca_1pixel_tail mvn TMP0, WK1 teq WK1, WK1, asr #32 - bne 01f - bcc 03f + bne 1f + bcc 3f mov WK3, WK1 - b 02f -01: over_white_8888_8888_ca_combine WK1, WK3 -02: pixst , 4, 3, DST -03: + b 2f +1: over_white_8888_8888_ca_combine WK1, WK3 +2: pixst , 4, 3, DST +3: .endm .macro over_white_8888_8888_ca_2pixels_head @@ -835,21 +835,21 @@ generate_composite_function \ pixld , 8, 3, DST mvn TMP0, WK1 teq WK1, WK1, asr #32 - bne 01f + bne 1f movcs WK3, WK1 - bcs 02f + bcs 2f teq WK2, #0 - beq 05f - b 02f -01: over_white_8888_8888_ca_combine WK1, WK3 -02: mvn TMP0, WK2 + beq 5f + b 2f +1: over_white_8888_8888_ca_combine WK1, WK3 +2: mvn TMP0, WK2 teq WK2, WK2, asr #32 - bne 03f + bne 3f movcs WK4, WK2 - b 04f -03: over_white_8888_8888_ca_combine WK2, WK4 -04: pixst , 8, 3, DST -05: + b 4f +3: over_white_8888_8888_ca_combine WK2, WK4 +4: pixst , 8, 3, DST +5: .endm .macro over_white_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload @@ -1065,9 +1065,9 @@ generate_composite_function \ .if offset != 0 ldrb ORIG_W, [SRC, #offset] .endif - beq 01f + beq 1f teq STRIDE_M, #0xFF - beq 02f + beq 2f .endif uxtb16 SCRATCH, d /* rb_dest */ uxtb16 d, d, ror #8 /* ag_dest */ @@ -1077,13 +1077,13 @@ generate_composite_function \ uxtab16 d, d, d, ror #8 mov SCRATCH, SCRATCH, ror #8 sel d, SCRATCH, d - b 02f + b 2f .if offset == 0 48: /* Last mov d,#0 of the set - used as part of shortcut for * source values all 0 */ .endif -01: mov d, #0 -02: +1: mov d, #0 +2: .endm .macro in_reverse_8888_8888_tail numbytes, reg1, reg2, reg3, reg4 From 662d60c5bf372cb174da8b254550f4bab4eb3b59 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 22 Apr 2026 07:51:47 +0200 Subject: [PATCH 6/9] [NSS] ensure permittedSubtrees don't match wildcards that could be outside the permitted tree. --- .../gtests/mozpkix_gtest/pkixnames_tests.cpp | 39 +++++++++++ security/nss/lib/mozpkix/lib/pkixnames.cpp | 68 ++++++++++++------- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp b/security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp index e90c63b6b4..4ca4a90e08 100644 --- a/security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp +++ b/security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp @@ -2082,6 +2082,45 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] = Result::ERROR_BAD_DER, Result::ERROR_BAD_DER }, + // Wildcard SANs have subtle outcomes. + { ByteString(), DNSName("*.example.com"), + GeneralSubtree(DNSName(".example.com")), + Success, + Result::ERROR_CERT_NOT_IN_NAME_SPACE + }, + { ByteString(), DNSName("*.example.com"), + GeneralSubtree(DNSName("example.com")), + Success, + Result::ERROR_CERT_NOT_IN_NAME_SPACE + }, + // A certificate with a wildcard SAN entry like `*.example.com` can't be + // issued by a CA with a DNSName name constraint entry like `foo.example.com` + // in either the permitted or excluded subtrees. If in the permitted subtree, + // the certificate would be valid for `bar.example.com`, which would violate + // the constraint. If in the excluded subtree, the certificate would be valid + // for `foo.example.com`, which would violate the constraint. + { ByteString(), DNSName("*.example.com"), + GeneralSubtree(DNSName("foo.example.com")), + Result::ERROR_CERT_NOT_IN_NAME_SPACE, + Result::ERROR_CERT_NOT_IN_NAME_SPACE + }, + { ByteString(), DNSName("*.foo.example.com"), + GeneralSubtree(DNSName("example.com")), + Success, + Result::ERROR_CERT_NOT_IN_NAME_SPACE + }, + { ByteString(), DNSName("*.example.com"), + GeneralSubtree(DNSName("foo.example.org")), + Result::ERROR_CERT_NOT_IN_NAME_SPACE, + Success + }, + // `*invalid.example.com` is an invalid presented DNSID. + { ByteString(), DNSName("*invalid.example.com"), + GeneralSubtree(DNSName("invalid.example.com")), + Result::ERROR_BAD_DER, + Result::ERROR_BAD_DER + }, + ///////////////////////////////////////////////////////////////////////////// // Basic IP Address constraints (non-CN-ID) diff --git a/security/nss/lib/mozpkix/lib/pkixnames.cpp b/security/nss/lib/mozpkix/lib/pkixnames.cpp index 2956000636..70faf199ae 100644 --- a/security/nss/lib/mozpkix/lib/pkixnames.cpp +++ b/security/nss/lib/mozpkix/lib/pkixnames.cpp @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Copyright 2014 Mozilla Contributors + * Copyright 2026 Moonchild Productions * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -170,6 +171,12 @@ enum class IDRole NameConstraint = 2, }; +enum class NameConstraintsSubtrees : uint8_t +{ + permittedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0, + excludedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1 +}; + enum class AllowWildcards { No = 0, Yes = 1 }; // DNSName constraints implicitly allow subdomain matching when there is no @@ -182,16 +189,22 @@ enum class AllowDotlessSubdomainMatches { No = 0, Yes = 1 }; bool IsValidDNSID(Input hostname, IDRole idRole, AllowWildcards allowWildcards); +// `subtreesType` is relevant only when `referenceDNSIDRole` is +// `IDRole::NameConstraint`. Result MatchPresentedDNSIDWithReferenceDNSID( Input presentedDNSID, AllowWildcards allowWildcards, AllowDotlessSubdomainMatches allowDotlessSubdomainMatches, IDRole referenceDNSIDRole, + /*optional*/ const NameConstraintsSubtrees* subtreesType, Input referenceDNSID, /*out*/ bool& matches); +// `subtreesType` is relevant only when `referenceDNSIDRole` is +// `IDRole::NameConstraint`. Result MatchPresentedRFC822NameWithReferenceRFC822Name( Input presentedRFC822Name, IDRole referenceRFC822NameRole, + /*optional*/ const NameConstraintsSubtrees* subtreesType, Input referenceRFC822Name, /*out*/ bool& matches); } // namespace @@ -210,7 +223,7 @@ MatchPresentedDNSIDWithReferenceDNSID(Input presentedDNSID, return MatchPresentedDNSIDWithReferenceDNSID( presentedDNSID, AllowWildcards::Yes, AllowDotlessSubdomainMatches::Yes, IDRole::ReferenceID, - referenceDNSID, matches); + nullptr, referenceDNSID, matches); } // Verify that the given end-entity cert, which is assumed to have been already @@ -694,7 +707,7 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType, rv = MatchPresentedDNSIDWithReferenceDNSID( presentedID, AllowWildcards::Yes, AllowDotlessSubdomainMatches::Yes, IDRole::ReferenceID, - referenceID, foundMatch); + nullptr, referenceID, foundMatch); break; case GeneralNameType::iPAddress: @@ -704,7 +717,7 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType, case GeneralNameType::rfc822Name: rv = MatchPresentedRFC822NameWithReferenceRFC822Name( - presentedID, IDRole::ReferenceID, referenceID, foundMatch); + presentedID, IDRole::ReferenceID, nullptr, referenceID, foundMatch); break; case GeneralNameType::directoryName: @@ -730,12 +743,6 @@ MatchPresentedIDWithReferenceID(GeneralNameType presentedIDType, return Success; } -enum class NameConstraintsSubtrees : uint8_t -{ - permittedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0, - excludedSubtrees = der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1 -}; - Result CheckPresentedIDConformsToNameConstraintsSubtrees( GeneralNameType presentedIDType, Input presentedID, @@ -849,7 +856,7 @@ CheckPresentedIDConformsToNameConstraintsSubtrees( rv = MatchPresentedDNSIDWithReferenceDNSID( presentedID, AllowWildcards::Yes, AllowDotlessSubdomainMatches::Yes, IDRole::NameConstraint, - base, matches); + &subtreesType, base, matches); if (rv != Success) { return rv; } @@ -874,7 +881,7 @@ CheckPresentedIDConformsToNameConstraintsSubtrees( case GeneralNameType::rfc822Name: rv = MatchPresentedRFC822NameWithReferenceRFC822Name( - presentedID, IDRole::NameConstraint, base, matches); + presentedID, IDRole::NameConstraint, &subtreesType, base, matches); if (rv != Success) { return rv; } @@ -1057,6 +1064,7 @@ MatchPresentedDNSIDWithReferenceDNSID( AllowWildcards allowWildcards, AllowDotlessSubdomainMatches allowDotlessSubdomainMatches, IDRole referenceDNSIDRole, + /*optional*/ const NameConstraintsSubtrees* subtreesType, Input referenceDNSID, /*out*/ bool& matches) { @@ -1147,18 +1155,28 @@ MatchPresentedDNSIDWithReferenceDNSID( return NotReached("Skipping '*' failed", Result::FATAL_ERROR_LIBRARY_FAILURE); } - do { - // This will happen if reference is a single, relative label - if (reference.AtEnd()) { - matches = false; - return Success; - } - uint8_t referenceByte; - if (reference.Read(referenceByte) != Success) { - return NotReached("invalid reference ID", - Result::FATAL_ERROR_INVALID_ARGS); - } - } while (!reference.Peek('.')); + // For the permittedSubtrees of a name constraint, wildcard presented + // DNSIDs of the form `*.example.com` only match if the name constraint is + // of the form `.example.com` or `example.com`. To put it another way, a + // permittedSubtrees of `foo.example.com` does not match a wildcard + // presented DNSID of `*.example.com`, because in that case, the + // certificate could be valid for `bar.example.com`, which does not match + // the name constraint. + if (referenceDNSIDRole != IDRole::NameConstraint || + (subtreesType && *subtreesType != NameConstraintsSubtrees::permittedSubtrees)) { + do { + // This will happen if reference is a single, relative label + if (reference.AtEnd()) { + matches = false; + return Success; + } + uint8_t referenceByte; + if (reference.Read(referenceByte) != Success) { + return NotReached("invalid reference ID", + Result::FATAL_ERROR_INVALID_ARGS); + } + } while (!reference.Peek('.')); + } } for (;;) { @@ -1515,9 +1533,12 @@ IsValidRFC822Name(Input input) } } +// `subtreesType` is relevant only when `referenceRFC822NameRole` is +// `IDRole::NameConstraint`. Result MatchPresentedRFC822NameWithReferenceRFC822Name(Input presentedRFC822Name, IDRole referenceRFC822NameRole, + /*optional*/ const NameConstraintsSubtrees* subtreesType, Input referenceRFC822Name, /*out*/ bool& matches) { @@ -1562,6 +1583,7 @@ MatchPresentedRFC822NameWithReferenceRFC822Name(Input presentedRFC822Name, return MatchPresentedDNSIDWithReferenceDNSID( presentedDNSID, AllowWildcards::No, AllowDotlessSubdomainMatches::No, IDRole::NameConstraint, + subtreesType, referenceRFC822Name, matches); } } From 4d731880032decc33cfb0e981ac77d3649e87f31 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 22 Apr 2026 08:20:43 +0200 Subject: [PATCH 7/9] [XPCOM] Update list of executable extensions on Windows. --- xpcom/io/nsLocalFileWin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index 0aa430d9dd..1d5e3da020 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -3020,6 +3020,7 @@ nsLocalFile::IsExecutable(bool* aResult) "air", // Adobe AIR installer "app", // executable application "application", // from bug 348763 + "appref-ms", // ClickOnce link "appx", "appxbundle", "asp", @@ -3080,6 +3081,7 @@ nsLocalFile::IsExecutable(bool* aResult) "scf", // Windows explorer command "scr", "sct", + "search-ms", // Windows Saved Search "settingcontent-ms", "shb", "shs", From 7aaf0ab764663051784d2fa1f8e531ddb8b99ec7 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 22 Apr 2026 09:20:11 +0200 Subject: [PATCH 8/9] [DOM] More consistently use already-calculated image properties. --- dom/base/ImageEncoder.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dom/base/ImageEncoder.cpp b/dom/base/ImageEncoder.cpp index 968c440b7f..cb9fbddf25 100644 --- a/dom/base/ImageEncoder.cpp +++ b/dom/base/ImageEncoder.cpp @@ -400,6 +400,7 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType, layers::PlanarYCbCrImage* ycbcrImage = static_cast (aImage); gfxImageFormat format = SurfaceFormat::A8R8G8B8_UINT32; uint32_t stride = GetAlignedStride<16>(aSize.width, 4); + auto size = stride * aSize.height; size_t length = BufferSizeFromStrideAndHeight(stride, aSize.height); if (length == 0) { return NS_ERROR_INVALID_ARG; @@ -413,10 +414,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType, stride); rv = aEncoder->InitFromData(data.Elements(), - aSize.width * aSize.height * 4, + size, aSize.width, aSize.height, - aSize.width * 4, + stride, imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions); } else { @@ -433,10 +434,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType, return NS_ERROR_INVALID_ARG; } rv = aEncoder->InitFromData(map.mData, - aSize.width * aSize.height * 4, + map.mStride * aSize.height, aSize.width, aSize.height, - aSize.width * 4, + map.mStride, imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions); dataSurface->Unmap(); @@ -467,10 +468,10 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType, return NS_ERROR_INVALID_ARG; } rv = aEncoder->InitFromData(map.mData, - aSize.width * aSize.height * 4, + map.mStride * aSize.height, aSize.width, aSize.height, - aSize.width * 4, + map.mStride, imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions); emptyCanvas->Unmap(); From 8ffe5094c91d88405d1d93884bf027a2d7138134 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 22 Apr 2026 12:00:51 +0200 Subject: [PATCH 9/9] Issue #2946 - Follow-up: Sanity-check WMF video properties. Not sure where else to put this under, but it's a WMF HWA related check, so filing it as a follow-up here to recent work. Also tag #2949 --- dom/media/platforms/wmf/WMFVideoMFTManager.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index 600a260556..114e262c33 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -15,6 +15,7 @@ #include "DXVA2Manager.h" #include "nsThreadUtils.h" #include "Layers.h" +#include "mozilla/CheckedInt.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/layers/LayersTypes.h" #include "MediaInfo.h" @@ -760,6 +761,10 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample, NS_ENSURE_TRUE(SUCCEEDED(hr), hr); stride = mVideoStride; } + if (stride <= 0) { + LOG("CreateBasicVideoFrame: invalid stride %ld", stride); + return E_FAIL; + } // YV12, planar format: [YYYY....][VVVV....][UUUU....] // i.e., Y, then V, then U. @@ -782,9 +787,16 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample, if (videoHeight % 16 != 0) { padding = 16 - (videoHeight % 16); } - uint32_t y_size = stride * (videoHeight + padding); - uint32_t v_size = stride * (videoHeight + padding) / 4; - uint32_t halfStride = (stride + 1) / 2; + mozilla::CheckedInt y_size_checked = + mozilla::CheckedInt(static_cast(stride)) * + (videoHeight + padding); + if (!y_size_checked.isValid()) { + LOG("CreateBasicVideoFrame: plane size too large"); + return E_FAIL; + } + uint32_t y_size = y_size_checked.value(); + uint32_t v_size = y_size / 4; + uint32_t halfStride = static_cast((static_cast(stride) + 1) / 2); uint32_t halfHeight = (videoHeight + 1) / 2; uint32_t halfWidth = (videoWidth + 1) / 2;