Attached is an (almost) full implementation of GetThreadTimes. The wineserver keeps track of a thread's creation and exit time to a 1 second resolution. This information is passed back to the client through the get_thread_info request. Although MSDN describes the exit time as undefined for running threads, I initialise it to zero to match Windows XP. The thread's user and kernel times are calculated on the client using times(2), to a 100ns resolution. Unfortunately, there seems to be no portable way to get the times(2) of another thread, so my implementation prints a FIXME in that case and returns FALSE. -Ryan ChangeLog: * Mostly implement GetThreadTimes
Index: scheduler/thread.c =================================================================== RCS file: /home/wine/wine/scheduler/thread.c,v retrieving revision 1.125 diff -u -r1.125 thread.c --- scheduler/thread.c 21 Nov 2002 03:45:01 -0000 1.125 +++ scheduler/thread.c 22 Nov 2002 04:55:49 -0000 @@ -24,6 +24,7 @@ #include <assert.h> #include <fcntl.h> #include <sys/types.h> +#include <sys/times.h> #ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> #endif @@ -33,6 +34,7 @@ #include "wine/winbase16.h" #include "thread.h" #include "task.h" +#include "file.h" #include "module.h" #include "winerror.h" #include "selectors.h" @@ -691,9 +693,71 @@ LPFILETIME kerneltime, /* [out] Time thread spent in kernel mode */ LPFILETIME usertime) /* [out] Time thread spent in user mode */ { - FIXME("(0x%p): stub\n",thread); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + if (creationtime || exittime) + { + /* We need to do a server call to get the creation time or exit time */ + /* This works on any thread */ + + SERVER_START_REQ( get_thread_info ) + { + req->handle = thread; + req->tid_in = 0; + if (!wine_server_call_err( req )) + { + if (creationtime) + { + DOSFS_UnixTimeToFileTime(reply->creation_time, creationtime, 0); + } + + if (exittime) + { + DOSFS_UnixTimeToFileTime(reply->exit_time, exittime, 0); + } + } + else + { + return FALSE; + } + + } + SERVER_END_REQ; + } + + if (kerneltime || usertime) + { + /* We call times(2) for kernel time or user time */ + /* We can only (portably) do this for the current thread */ + if (thread == GetCurrentThread()) + { + struct tms time_buf; + long clocks_per_sec; + + times(&time_buf); + clocks_per_sec = sysconf(_SC_CLK_TCK); + + if (kerneltime) + { + DOSFS_UnixTimeToFileTime(time_buf.tms_stime / clocks_per_sec, + kerneltime, + ((time_buf.tms_stime % clocks_per_sec) * 10000000) / clocks_per_sec); + } + + if (usertime) + { + DOSFS_UnixTimeToFileTime(time_buf.tms_utime / clocks_per_sec, + usertime, + ((time_buf.tms_utime % clocks_per_sec) * 10000000) / clocks_per_sec); + } + } + else + { + FIXME("Cannot get kerneltime or usertime of other threads"); + + return FALSE; + } + } + + return TRUE; } Index: include/wine/server_protocol.h =================================================================== RCS file: /home/wine/wine/include/wine/server_protocol.h,v retrieving revision 1.49 diff -u -r1.49 server_protocol.h --- include/wine/server_protocol.h 20 Nov 2002 19:54:32 -0000 1.49 +++ include/wine/server_protocol.h 22 Nov 2002 04:55:50 -0000 @@ -400,6 +400,8 @@ void* teb; int exit_code; int priority; + time_t creation_time; + time_t exit_time; }; @@ -3466,6 +3468,6 @@ struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 90 +#define SERVER_PROTOCOL_VERSION 91 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */