You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Added patch to return correct values in GetThreadTimes function for all threads.
This commit is contained in:
@@ -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
|
||||
|
4
patches/ntdll-ThreadTime/definition
Normal file
4
patches/ntdll-ThreadTime/definition
Normal 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
|
Reference in New Issue
Block a user