[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