Added patch to return correct values in GetThreadTimes function for all threads.

This commit is contained in:
Sebastian Lackner 2014-11-07 03:34:58 +01:00
parent 393eed4e68
commit c213417376
5 changed files with 224 additions and 1 deletions

View File

@ -39,7 +39,7 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [7]:**
**Bugfixes and features included in the next upcoming release [8]:**
* Add stub for NtSetLdtEntries/ZwSetLdtEntries ([Wine Bug #26268](https://bugs.winehq.org/show_bug.cgi?id=26268))
* Allow selection of audio device for PulseAudio backend
@ -48,6 +48,7 @@ Included bug fixes and improvements
* FairplayKD.sys needs KeSetSystemAffinityThread ([Wine Bug #36822](https://bugs.winehq.org/show_bug.cgi?id=36822))
* Fix crash of Trine Demo on start ([Wine Bug #19231](https://bugs.winehq.org/show_bug.cgi?id=19231))
* Fix texture corruption in CSI: Fatal Conspiracy ([Wine Bug #33768](https://bugs.winehq.org/show_bug.cgi?id=33768))
* Return correct values for GetThreadTimes function ([Wine Bug #20230](https://bugs.winehq.org/show_bug.cgi?id=20230))
**Bugs fixed in Wine Staging 1.7.30 [90]:**

1
debian/changelog vendored
View File

@ -7,6 +7,7 @@ wine-compholio (1.7.31) UNRELEASED; urgency=low
* Added patch to prevent processing message events for CoWaitForMultipleHandles when APC calls are queued.
* Added patch with stub for KeSetSystemAffinityThread.
* Added patch to implement DXTn support for d3dx9_36.
* Added patch to return correct values for GetThreadTimes.
* Removed patch for iphlpapi stub functions (accepted upstream).
* Removed patches for FindFirstFileExW (accepted upstream).
* Removed patches for TLB dependencies lookup in resources (accepted upstream).

View File

@ -61,6 +61,7 @@ PATCHLIST := \
ntdll-NtQuerySection.ok \
ntdll-NtSetLdtEntries.ok \
ntdll-Pipe_SpecialCharacters.ok \
ntdll-ThreadTime.ok \
ntdll-WRITECOPY.ok \
ntoskrnl-Irp_Status.ok \
ntoskrnl-KeSetSystemAffinityThread.ok \
@ -978,6 +979,24 @@ ntdll-Pipe_SpecialCharacters.ok:
echo '+ { "ntdll-Pipe_SpecialCharacters", "Michael Müller", "Allow special characters in pipe names." },'; \
) > ntdll-Pipe_SpecialCharacters.ok
# Patchset ntdll-ThreadTime
# |
# | Included patches:
# | * Return correct values in GetThreadTimes() for all threads. [by Sebastian Lackner]
# |
# | This patchset fixes the following Wine bugs:
# | * [#20230] Return correct values for GetThreadTimes function
# |
# | Modified files:
# | * dlls/ntdll/thread.c, server/protocol.def, server/thread.c
# |
.INTERMEDIATE: ntdll-ThreadTime.ok
ntdll-ThreadTime.ok:
$(call APPLY_FILE,ntdll-ThreadTime/0001-ntdll-Return-correct-values-in-GetThreadTimes-for-al.patch)
@( \
echo '+ { "ntdll-ThreadTime", "Sebastian Lackner", "Return correct values in GetThreadTimes() for all threads." },'; \
) > ntdll-ThreadTime.ok
# Patchset ntdll-WRITECOPY
# |
# | Included patches:

View File

@ -0,0 +1,198 @@
From 4d5874dbe7056a4a1a86e13a4f92096e5d77f18f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 7 Nov 2014 03:26:18 +0100
Subject: ntdll: Return correct values in GetThreadTimes() for all threads.
Based on a patch by Ray Hinchliffe <ray@pobox.co.uk>.
---
dlls/ntdll/thread.c | 86 ++++++++++++++++++++++++++++++++++++++++-------------
server/protocol.def | 11 +++++++
server/thread.c | 16 ++++++++++
3 files changed, 93 insertions(+), 20 deletions(-)
mode change 100644 => 100755 dlls/ntdll/thread.c
mode change 100644 => 100755 server/protocol.def
mode change 100644 => 100755 server/thread.c
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
old mode 100644
new mode 100755
index c8461b0..44b1a9c
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -23,6 +23,8 @@
#include <assert.h>
#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
@@ -948,47 +950,91 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
case ThreadTimes:
{
KERNEL_USER_TIMES kusrt;
- /* We need to do a server call to get the creation time or exit time */
+ int unix_pid, unix_tid;
+
+ /* We need to do a server call to get the creation time, exit time, PID and TID */
/* This works on any thread */
- SERVER_START_REQ( get_thread_info )
+ SERVER_START_REQ( get_thread_times )
{
req->handle = wine_server_obj_handle( handle );
- req->tid_in = 0;
status = wine_server_call( req );
if (status == STATUS_SUCCESS)
{
kusrt.CreateTime.QuadPart = reply->creation_time;
kusrt.ExitTime.QuadPart = reply->exit_time;
+ unix_pid = reply->unix_pid;
+ unix_tid = reply->unix_tid;
}
}
SERVER_END_REQ;
if (status == STATUS_SUCCESS)
{
- /* We call times(2) for kernel time or user time */
- /* We can only (portably) do this for the current thread */
- if (handle == GetCurrentThread())
+ unsigned long clk_tck = sysconf(_SC_CLK_TCK);
+ BOOL filled_times = FALSE;
+
+#ifdef __linux__
+ /* only /proc provides exact values for a specific thread */
+ if (unix_pid != -1 && unix_tid != -1)
{
- struct tms time_buf;
- long clocks_per_sec = sysconf(_SC_CLK_TCK);
+ unsigned long usr, sys;
+ char buf[512], *pos;
+ FILE *fp;
+ int i;
+
+ /* based on https://github.com/torvalds/linux/blob/master/fs/proc/array.c */
+ sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid );
+ if ((fp = fopen( buf, "r" )))
+ {
+ pos = fgets( buf, sizeof(buf), fp );
+ fclose( fp );
+
+ /* format of first chunk is "%d (%s) %c" - we have to skip to the last ')'
+ * to avoid misinterpreting the string. */
+ if (pos) pos = strrchr( pos, ')' );
+ if (pos) pos = strchr( pos + 1, ' ' );
+ if (pos) pos++;
+
+ /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp,
+ * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
+ for (i = 0; (i < 11) && pos; i++)
+ {
+ pos = strchr( pos + 1, ' ' );
+ if (pos) pos++;
+ }
+
+ /* the next two values are user and system time */
+ if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2))
+ {
+ kusrt.KernelTime.QuadPart = (ULONGLONG)sys * 10000000 / clk_tck;
+ kusrt.UserTime.QuadPart = (ULONGLONG)usr * 10000000 / clk_tck;
+ filled_times = TRUE;
+ }
+ }
+ }
+#endif
+ /* get values for current process instead */
+ if (!filled_times && handle == GetCurrentThread())
+ {
+ struct tms time_buf;
times(&time_buf);
- kusrt.KernelTime.QuadPart = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
- kusrt.UserTime.QuadPart = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
+
+ kusrt.KernelTime.QuadPart = (ULONGLONG)time_buf.tms_stime * 10000000 / clk_tck;
+ kusrt.UserTime.QuadPart = (ULONGLONG)time_buf.tms_utime * 10000000 / clk_tck;
+ filled_times = TRUE;
}
- else
+
+ /* unable to determine exact values, fill with zero */
+ if (!filled_times)
{
- static BOOL reported = FALSE;
+ static int once;
+ if (!once++)
+ FIXME("Cannot get kerneltime or usertime of other threads\n");
kusrt.KernelTime.QuadPart = 0;
- kusrt.UserTime.QuadPart = 0;
- if (reported)
- TRACE("Cannot get kerneltime or usertime of other threads\n");
- else
- {
- FIXME("Cannot get kerneltime or usertime of other threads\n");
- reported = TRUE;
- }
+ kusrt.UserTime.QuadPart = 0;
}
+
if (data) memcpy( data, &kusrt, min( length, sizeof(kusrt) ));
if (ret_len) *ret_len = min( length, sizeof(kusrt) );
}
diff --git a/server/protocol.def b/server/protocol.def
old mode 100644
new mode 100755
index 4854e3d..6f5575a
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -789,6 +789,17 @@ struct rawinput_device
#define SET_PROCESS_INFO_AFFINITY 0x02
+/* Retrieve information about thread times */
+@REQ(get_thread_times)
+ obj_handle_t handle; /* thread handle */
+@REPLY
+ timeout_t creation_time; /* thread creation time */
+ timeout_t exit_time; /* thread exit time */
+ int unix_pid; /* thread native pid */
+ int unix_tid; /* thread native pid */
+@END
+
+
/* Retrieve information about a thread */
@REQ(get_thread_info)
obj_handle_t handle; /* thread handle */
diff --git a/server/thread.c b/server/thread.c
old mode 100644
new mode 100755
index 50d6940..e670ab5
--- a/server/thread.c
+++ b/server/thread.c
@@ -1346,6 +1346,22 @@ DECL_HANDLER(open_thread)
}
}
+/* fetch information about thread times */
+DECL_HANDLER(get_thread_times)
+{
+ struct thread *thread;
+
+ if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
+ {
+ reply->creation_time = thread->creation_time;
+ reply->exit_time = thread->exit_time;
+ reply->unix_pid = thread->unix_pid;
+ reply->unix_tid = thread->unix_tid;
+
+ release_object( thread );
+ }
+}
+
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
--
2.1.3

View File

@ -0,0 +1,4 @@
Author: Sebastian Lackner
Subject: Return correct values in GetThreadTimes() for all threads.
Revision: 1
Fixes: [20230] Return correct values for GetThreadTimes function