NtQueryTimerResolution

This commit is contained in:
DBotThePony 2024-02-04 20:06:12 +07:00
parent 4ff09bea2b
commit d8f4d06d83
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 51 additions and 2 deletions

View File

@ -0,0 +1,23 @@
package ru.dbotthepony.kstarbound
import jnr.ffi.LibraryLoader
import org.apache.logging.log4j.LogManager
import java.nio.LongBuffer
interface WindowsBindings {
fun NtQueryTimerResolution(minimumResolution: LongBuffer, maximumResolution: LongBuffer, currentResolution: LongBuffer)
fun NtSetTimerResolution(desiredResolution: Long, setResolution: Boolean, currentResolution: LongBuffer)
companion object {
private val LOGGER = LogManager.getLogger()
val INSTANCE by lazy {
try {
LibraryLoader.create(WindowsBindings::class.java).load("ntdll")
} catch (err: Throwable) {
LOGGER.error("Failed to link against ntdll.dll, if we are not on Windows then ignore this message", err)
null
}
}
}
}

View File

@ -1,8 +1,10 @@
package ru.dbotthepony.kstarbound.util
import org.apache.logging.log4j.LogManager
import org.lwjgl.system.MemoryStack
import ru.dbotthepony.kommons.util.MailboxExecutorService
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.WindowsBindings
import java.util.concurrent.locks.LockSupport
import java.util.function.BooleanSupplier
@ -54,7 +56,7 @@ class ExecutionSpinner(private val executor: MailboxExecutorService, private val
while (diff > 0L) {
executor.executeQueuedTasks()
diff = timeUntilNextFrame()
if (diff > 400_000L) LockSupport.parkNanos(100_000L)
if (diff > SYSTEM_SCHEDULER_RESOLUTION) LockSupport.parkNanos(500_000L)
}
val mark = System.nanoTime()
@ -73,9 +75,33 @@ class ExecutionSpinner(private val executor: MailboxExecutorService, private val
companion object {
private val LOGGER = LogManager.getLogger()
private var SYSTEM_SCHEDULER_RESOLUTION = 1_000_000L
init {
val thread = object : Thread("Fix God Damn Windows Process Scheduler For Once Please") {
val bindings = WindowsBindings.INSTANCE
if (bindings != null) {
MemoryStack.stackPush().use { stack ->
val minimum = stack.mallocLong(1)
val maximum = stack.mallocLong(1)
val current = stack.mallocLong(1)
minimum.put(0L)
maximum.put(0L)
current.put(0L)
minimum.position(0)
maximum.position(0)
current.position(0)
bindings.NtQueryTimerResolution(minimum, maximum, current)
SYSTEM_SCHEDULER_RESOLUTION = current[0] * 150L // give some room for error
LOGGER.info("NtQueryTimerResolution(): {} ns/{} ns/{} ns min/max/current", minimum[0] * 100L, maximum[0] * 100L, current[0] * 100L)
}
}
val thread = object : Thread("Process scheduler timer hack thread") {
override fun run() {
while (true) {
try {