[PATCH] Fix GetThreadTimes to work for all threads
Ray Hinchliffe
ray at rh-software.com
Sat Apr 16 09:24:13 CDT 2011
---
dlls/ntdll/thread.c | 95 =
++++++++++++++++++++++++++++++---------
include/wine/server_protocol.h | 19 ++++++++
include/winternl.h | 5 +-
server/request.h | 9 ++++
server/thread.c | 18 ++++++++
server/trace.c | 15 ++++++
6 files changed, 137 insertions(+), 24 deletions(-)
mode change 100644 =3D> 100755 dlls/ntdll/Makefile.in
mode change 100644 =3D> 100755 dlls/ntdll/thread.c
mode change 100644 =3D> 100755 include/wine/server_protocol.h
mode change 100644 =3D> 100755 include/winternl.h
mode change 100644 =3D> 100755 server/request.h
mode change 100644 =3D> 100755 server/thread.c
mode change 100644 =3D> 100755 server/trace.c
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
old mode 100644
new mode 100755
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
old mode 100644
new mode 100755
index 56eca23..81af4d1
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -23,6 +23,8 @@
=20
#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>
@@ -916,45 +918,94 @@ 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 */
+ char buf[ 256 ];
+
+ /* 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 =3D wine_server_obj_handle( handle );
- req->tid_in =3D 0;
status =3D wine_server_call( req );
if (status =3D=3D STATUS_SUCCESS)
{
kusrt.CreateTime.QuadPart =3D reply->creation_time;
- kusrt.ExitTime.QuadPart =3D reply->exit_time;
+ kusrt.ExitTime.QuadPart =3D reply->exit_time;
+
+ sprintf( buf, "/proc/%u/task/%u/stat", =
reply->unix_pid, reply->unix_tid );
}
}
SERVER_END_REQ;
- if (status =3D=3D STATUS_SUCCESS)
+
+ if( status =3D=3D STATUS_SUCCESS )
{
- /* We call times(2) for kernel time or user time */
- /* We can only (portably) do this for the current =
thread */
- if (handle =3D=3D GetCurrentThread())
+ /* do this portably for the current thread */
+ if( handle =3D=3D GetCurrentThread() )
{
- struct tms time_buf;
- long clocks_per_sec =3D sysconf(_SC_CLK_TCK);
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec spec_buf;
+
+ /* are thread times available ? */
+
+ if( ( sysconf( _POSIX_THREAD_CPUTIME =
) ) &&
+ ( !clock_gettime( CLOCK_THREAD_CPUTIME_ID, =
&spec_buf ) ) )
+ {
+ /* yes, but no kernel time, so just return user =
time */
+
+ kusrt.KernelTime.QuadPart =3D 0;
+ kusrt.UserTime.QuadPart =3D =
(ULONGLONG)spec_buf.tv_sec * 10000000 +
+ =
spec_buf.tv_nsec / 100;
+ }
+ else
+#endif
+ {
+ struct tms time_buf;
+ long tick_time =3D 10000000 / sysconf( =
_SC_CLK_TCK );
+
+ /* call times(2) for kernel time or user time =
*/
=20
- times(&time_buf);
- kusrt.KernelTime.QuadPart =3D =
(ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
- kusrt.UserTime.QuadPart =3D =
(ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
+ times(&time_buf);
+
+ kusrt.KernelTime.QuadPart =3D =
(ULONGLONG)time_buf.tms_stime * tick_time;
+ kusrt.UserTime.QuadPart =3D =
(ULONGLONG)time_buf.tms_utime * tick_time;
+ }
}
else
{
- static BOOL reported =3D FALSE;
-
- kusrt.KernelTime.QuadPart =3D 0;
- kusrt.UserTime.QuadPart =3D 0;
- if (reported)
- TRACE("Cannot get kerneltime or usertime of =
other threads\n");
- else
+ unsigned long usr;
+ unsigned long sys;
+ unsigned long ctt;
+ unsigned long got;
+ const char *pos;
+ FILE *fid;
+
+ if( got =3D ( ( fid =3D fopen( buf, "r" ) ) !=3D =
NULL ) )
+ {
+ fgets( buf, sizeof( buf ) - 1, fid );
+ fclose( fid );
+
+ for( got =3D 0, pos =3D buf; ( got < 13 ) && =
pos; got++, pos =3D strchr( pos + 1, ' ' ) ) {}
+
+ if( got =3D pos && ( sscanf( pos, " %u %u", =
&usr, &sys ) =3D=3D 2 ) )
+ {
+ ctt =3D 10000000 / sysconf( _SC_CLK_TCK );
+ kusrt.KernelTime.QuadPart =3D =
(ULONGLONG)sys * ctt;
+ kusrt.UserTime.QuadPart =3D =
(ULONGLONG)usr * ctt;
+ }
+ }
+
+ if( !got ) /* failed to read and decode =
/proc ? */
{
- FIXME("Cannot get kerneltime or usertime of =
other threads\n");
- reported =3D TRUE;
+ static BOOL reported =3D FALSE;
+
+ kusrt.KernelTime.QuadPart =3D 0;
+ kusrt.UserTime.QuadPart =3D 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 =3D TRUE;
+ }
}
}
if (data) memcpy( data, &kusrt, min( length, =
sizeof(kusrt) ));
diff --git a/include/wine/server_protocol.h =
b/include/wine/server_protocol.h
old mode 100644
new mode 100755
index d321a80..e7fe6d6
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -792,6 +792,22 @@ struct set_process_info_reply
=20
=20
=20
+struct get_thread_times_request
+{
+ struct request_header __header;
+ obj_handle_t handle;
+};
+struct get_thread_times_reply
+{
+ struct reply_header __header;
+ timeout_t creation_time;
+ timeout_t exit_time;
+ int unix_pid;
+ int unix_tid;
+};
+
+
+
struct get_thread_info_request
{
struct request_header __header;
@@ -4830,6 +4846,7 @@ enum request
REQ_terminate_thread,
REQ_get_process_info,
REQ_set_process_info,
+ REQ_get_thread_times,
REQ_get_thread_info,
REQ_set_thread_info,
REQ_get_dll_info,
@@ -5080,6 +5097,7 @@ union generic_request
struct terminate_thread_request terminate_thread_request;
struct get_process_info_request get_process_info_request;
struct set_process_info_request set_process_info_request;
+ struct get_thread_times_request get_thread_times_request;
struct get_thread_info_request get_thread_info_request;
struct set_thread_info_request set_thread_info_request;
struct get_dll_info_request get_dll_info_request;
@@ -5328,6 +5346,7 @@ union generic_reply
struct terminate_thread_reply terminate_thread_reply;
struct get_process_info_reply get_process_info_reply;
struct set_process_info_reply set_process_info_reply;
+ struct get_thread_times_reply get_thread_times_reply;
struct get_thread_info_reply get_thread_info_reply;
struct set_thread_info_reply set_thread_info_reply;
struct get_dll_info_reply get_dll_info_reply;
diff --git a/include/winternl.h b/include/winternl.h
old mode 100644
new mode 100755
index a1c9f0c..0801a55
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1241,8 +1241,9 @@ typedef struct =
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
- LARGE_INTEGER Reserved1[2];
- ULONG Reserved2;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER IntTime;
+ ULONG IntCount;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, =
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
=20
/* System Information Class 0x0b */
diff --git a/server/request.h b/server/request.h
old mode 100644
new mode 100755
index 0133af7..0712d67
--- a/server/request.h
+++ b/server/request.h
@@ -121,6 +121,7 @@ DECL_HANDLER(terminate_process);
DECL_HANDLER(terminate_thread);
DECL_HANDLER(get_process_info);
DECL_HANDLER(set_process_info);
+DECL_HANDLER(get_thread_times);
DECL_HANDLER(get_thread_info);
DECL_HANDLER(set_thread_info);
DECL_HANDLER(get_dll_info);
@@ -370,6 +371,7 @@ static const req_handler =
req_handlers[REQ_NB_REQUESTS] =3D
(req_handler)req_terminate_thread,
(req_handler)req_get_process_info,
(req_handler)req_set_process_info,
+ (req_handler)req_get_thread_times,
(req_handler)req_get_thread_info,
(req_handler)req_set_thread_info,
(req_handler)req_get_dll_info,
@@ -717,6 +719,13 @@ C_ASSERT( FIELD_OFFSET(struct =
set_process_info_request, mask) =3D=3D 16 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, priority) =
=3D=3D 20 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, affinity) =
=3D=3D 24 );
C_ASSERT( sizeof(struct set_process_info_request) =3D=3D 32 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_times_request, handle) =3D=3D =
12 );
+C_ASSERT( sizeof(struct get_thread_times_request) =3D=3D 16 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_times_reply, creation_time) =
=3D=3D 8 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_times_reply, exit_time) =3D=3D =
16 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_times_reply, unix_pid) =3D=3D =
24 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_times_reply, unix_tid) =3D=3D =
28 );
+C_ASSERT( sizeof(struct get_thread_times_reply) =3D=3D 32 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, handle) =3D=3D =
12 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, tid_in) =3D=3D =
16 );
C_ASSERT( sizeof(struct get_thread_info_request) =3D=3D 24 );
diff --git a/server/thread.c b/server/thread.c
old mode 100644
new mode 100755
index 983ba2d..0cf694c
--- a/server/thread.c
+++ b/server/thread.c
@@ -1239,6 +1239,24 @@ DECL_HANDLER(open_thread)
}
}
=20
+/* fetch information about thread times */
+DECL_HANDLER(get_thread_times)
+{
+ struct thread *thread;
+
+ thread =3D get_thread_from_handle( req->handle, =
THREAD_QUERY_INFORMATION );
+
+ if (thread)
+ {
+ reply->creation_time =3D thread->creation_time;
+ reply->exit_time =3D thread->exit_time;
+ reply->unix_pid =3D thread->unix_pid;
+ reply->unix_tid =3D thread->unix_tid;;
+
+ release_object( thread );
+ }
+}
+
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
diff --git a/server/trace.c b/server/trace.c
old mode 100644
new mode 100755
index 06fe545..caecee2
--- a/server/trace.c
+++ b/server/trace.c
@@ -1199,6 +1199,19 @@ static void dump_set_process_info_request( const =
struct set_process_info_request
dump_uint64( ", affinity=3D", &req->affinity );
}
=20
+static void dump_get_thread_times_request( const struct =
get_thread_times_request *req )
+{
+ fprintf( stderr, " handle=3D%04x", req->handle );
+}
+
+static void dump_get_thread_times_reply( const struct =
get_thread_times_reply *req )
+{
+ dump_timeout( ", creation_time=3D", &req->creation_time );
+ dump_timeout( ", exit_time=3D", &req->exit_time );
+ fprintf( stderr, ", unix_pid=3D%d", req->unix_pid );
+ fprintf( stderr, ", unix_tid=3D%d", req->unix_tid );
+}
+
static void dump_get_thread_info_request( const struct =
get_thread_info_request *req )
{
fprintf( stderr, " handle=3D%04x", req->handle );
@@ -3920,6 +3933,7 @@ static const dump_func =
req_dumpers[REQ_NB_REQUESTS] =3D {
(dump_func)dump_terminate_thread_request,
(dump_func)dump_get_process_info_request,
(dump_func)dump_set_process_info_request,
+ (dump_func)dump_get_thread_times_request,
(dump_func)dump_get_thread_info_request,
(dump_func)dump_set_thread_info_request,
(dump_func)dump_get_dll_info_request,
@@ -4412,6 +4426,7 @@ static const char * const =
req_names[REQ_NB_REQUESTS] =3D {
"terminate_thread",
"get_process_info",
"set_process_info",
+ "get_thread_times",
"get_thread_info",
"set_thread_info",
"get_dll_info",
--=20
1.7.0.4
------=_NextPart_000_0004_01CBFD9C.A1C4DCF0--
More information about the wine-patches
mailing list