Skip to content

Commit

Permalink
fix(Threading): add thread priorities for better input performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadowApex committed Sep 10, 2023
1 parent 4c944e0 commit d1b9545
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 4 deletions.
Binary file not shown.
Binary file not shown.
9 changes: 9 additions & 0 deletions addons/linuxthread/linuxthread.gdextension
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[configuration]

entry_symbol = "linux_thread_library_init"
compatibility_minimum = 4.1

[libraries]

linux.debug.x86_64 = "res://addons/linuxthread/bin/liblinuxthread.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://addons/linuxthread/bin/liblinuxthread.linux.template_release.x86_64.so"
1 change: 1 addition & 0 deletions core/systems/threading/input_thread.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
script = ExtResource("1_rbhla")
name = "InputThread"
target_tick_rate = 600
niceness = -20
1 change: 1 addition & 0 deletions core/systems/threading/io_thread.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
script = ExtResource("1_qvlys")
name = "IOThread"
target_tick_rate = 30
niceness = 0
39 changes: 37 additions & 2 deletions core/systems/threading/shared_thread.gd
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const watchdog := preload("res://core/systems/threading/watchdog_thread.tres")

var thread: Thread
var mutex := Mutex.new()
var tid := -1
var running := false
var nodes: Array[NodeThread] = []
var process_funcs: Array[Callable] = []
Expand All @@ -24,6 +25,8 @@ var logger := Log.get_logger("SharedThread", Log.LEVEL.INFO)
@export var name := "SharedThread"
## Target rate to run at in ticks per second
@export var target_tick_rate := 60
## Priority (niceness) of the thread
@export var niceness := 0


func _init() -> void:
Expand All @@ -42,7 +45,7 @@ func start() -> void:
running = true
thread = Thread.new()
thread.start(_run)
logger.info("Thread group started: " + name)
logger.info("Shared thread started: " + name)


## Stops the thread for the thread group
Expand All @@ -53,7 +56,28 @@ func stop() -> void:
running = false
mutex.unlock()
thread.wait_to_finish()
logger.info("Thread group stopped: " + name)
logger.info("Shared thread stopped: " + name)


## Set the given thread niceness to the given value.
## Note: in order to set negative nice value, this must be run:
## setcap 'cap_sys_nice=eip' <opengamepadui binary>
func set_priority(value: int) -> int:
# If this was called from another thread, schedule it to run on the thread
mutex.lock()
var thread_id := tid
mutex.unlock()
if LinuxThread.get_tid() != thread_id:
logger.debug("Set thread priority was called from another thread")
return await exec(set_priority.bind(value))

# Set the thread priority if this function was called from the SharedThread
var err := LinuxThread.set_thread_priority(value)
if err == OK:
niceness = value
logger.info("Set thread niceness on {0} ({1}) to: {2}".format([name, thread_id, value]))

return err


## Add the given [NodeThread] to the list of nodes to process. This should
Expand Down Expand Up @@ -145,6 +169,17 @@ func remove_process(method: Callable) -> void:


func _run() -> void:
# Update the thread ID
mutex.lock()
tid = LinuxThread.get_tid()
mutex.unlock()
logger.info("Started thread with thread ID: " + str(LinuxThread.get_tid()))

# If the nice value isn't default, reassign the thread priority
if niceness != 0:
if await set_priority(niceness) != OK:
logger.warn("Unable to set niceness on thread: " + name)

# TODO: Fix unsafe thread operations
Thread.set_thread_safety_checks_enabled(false)
var exited := false
Expand Down
1 change: 1 addition & 0 deletions core/systems/threading/system_thread.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
script = ExtResource("1_hqprx")
name = "SystemThread"
target_tick_rate = 600
niceness = 0
1 change: 1 addition & 0 deletions core/systems/threading/utility_thread.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
script = ExtResource("1_svd22")
name = "UtilityThread"
target_tick_rate = 10
niceness = 0
1 change: 1 addition & 0 deletions core/systems/threading/watchdog_thread.tres
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
script = ExtResource("1_fg543")
name = "WatchdogThread"
target_tick_rate = 1
warn_after_num_missed_frames = 20
4 changes: 4 additions & 0 deletions entrypoint.gd
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ func _apply_update_packs() -> void:
if OS.execute("chmod", ["+x", file_path]) != OK:
logger.warn("Failed to set execute permissions. Not loading update pack")
return

# Try to run setcap to allow setting thread priorities
if OS.execute("/usr/share/opengamepadui/scripts/make_nice", []) != OK:
logger.warn("Unable to run setcap to enable thread priorities")

# Launch the update pack executable and exit
var update_bin := ProjectSettings.globalize_path(update_pack_entrypoint)
Expand Down
17 changes: 15 additions & 2 deletions rootfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,34 @@ install: ## Install OpenGamepadUI (default: ~/.local)
install -Dm644 usr/share/icons/hicolor/scalable/apps/opengamepadui.svg \
$(PREFIX)/share/icons/hicolor/scalable/apps/opengamepadui.svg
mkdir -p $(PREFIX)/share/opengamepadui
install -Dm644 usr/share/opengamepadui/libdbus.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libdbus.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/libevdev.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libevdev.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/libxlib.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libxlib.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/liblinuxthread.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/liblinuxthread.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/libopensd.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libopensd.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/libpty.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libpty.linux.template_debug.x86_64.so
install -Dm644 usr/share/opengamepadui/libxlib.linux.template_debug.x86_64.so \
$(PREFIX)/share/opengamepadui/libxlib.linux.template_debug.x86_64.so
install -Dm755 usr/share/opengamepadui/opengamepad-ui.x86_64 \
$(PREFIX)/share/opengamepadui/opengamepad-ui.x86_64
setcap 'cap_sys_nice=eip' $(PREFIX)/share/opengamepadui/opengamepad-ui.x86_64 || true
mkdir -p $(PREFIX)/share/opengamepadui/scripts
install -Dm755 usr/share/opengamepadui/scripts/powertools \
$(PREFIX)/share/opengamepadui/scripts/powertools
install -Dm755 usr/share/opengamepadui/scripts/manage_input \
$(PREFIX)/share/opengamepadui/scripts/manage_input
install -Dm755 usr/share/opengamepadui/scripts/make_nice \
$(PREFIX)/share/opengamepadui/scripts/make_nice
install -Dm644 usr/share/polkit-1/actions/org.shadowblip.powertools.policy \
$(PREFIX)/share/polkit-1/actions/org.shadowblip.powertools.policy
install -Dm644 usr/share/polkit-1/actions/org.shadowblip.manage_input.policy \
$(PREFIX)/share/polkit-1/actions/org.shadowblip.manage_input.policy
install -Dm644 usr/share/polkit-1/actions/org.shadowblip.setcap.policy \
$(PREFIX)/share/polkit-1/actions/org.shadowblip.setcap.policy
install -Dm644 usr/lib/udev/hwdb.d/59-opengamepadui-handheld.hwdb \
$(PREFIX)/lib/udev/hwdb.d/59-opengamepadui-handheld.hwdb
install -Dm644 usr/lib/udev/rules.d/61-opengamepadui-handheld.rules \
Expand Down
10 changes: 10 additions & 0 deletions rootfs/usr/share/opengamepadui/scripts/make_nice
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
set -eu

if [[ $EUID -ne 0 ]]; then
exec pkexec --disable-internal-agent "$0" "$HOME" "$@"
fi

USER_HOME="$1"
UPDATE_PATH="${USER_HOME}/.local/share/opengamepadui/updates/opengamepad-ui.x86_64"
setcap 'cap_sys_nice=eip' "${UPDATE_PATH}"
16 changes: 16 additions & 0 deletions rootfs/usr/share/polkit-1/actions/org.shadowblip.setcap.policy
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<vendor>ShadowBlip</vendor>
<vendor_url>http://www.github.com/shadowblip</vendor_url>
<action id="org.shadowblip.pkexec.setcap">
<description>Allow negative nice values</description>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/share/opengamepadui/scripts/make_nice</annotate>
</action>
</policyconfig>

0 comments on commit d1b9545

Please sign in to comment.