[PATCH 2/3] server: Add get_process_time

brock at polynubstudios.com brock at polynubstudios.com
Wed Feb 19 04:02:03 CST 2020


From: Brock York <twunknown at gmail.com>

get_process_time returns the amount of time a given
process has spent in kernel and user mode.
Reads from /proc/[pid]/stat the utime and stime fields

Signed-off-by: Brock York <brock at polynubstudios.com>
---
 include/wine/server_protocol.h | 18 ++++++++++++++++-
 server/process.c               | 35 ++++++++++++++++++++++++++++++++++
 server/protocol.def            |  8 ++++++++
 server/request.h               |  8 ++++++++
 server/trace.c                 | 15 +++++++++++++++
 5 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 3b457df8b0..58a6af779b 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -5797,6 +5797,19 @@ struct resume_process_reply
 };
 
 
+struct get_process_time_request
+{
+    struct request_header __header;
+    obj_handle_t handle;
+};
+struct get_process_time_reply
+{
+    struct reply_header __header;
+    unsigned __int64 utime;
+    unsigned __int64 stime;
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -6096,6 +6109,7 @@ enum request
     REQ_terminate_job,
     REQ_suspend_process,
     REQ_resume_process,
+    REQ_get_process_time,
     REQ_NB_REQUESTS
 };
 
@@ -6400,6 +6414,7 @@ union generic_request
     struct terminate_job_request terminate_job_request;
     struct suspend_process_request suspend_process_request;
     struct resume_process_request resume_process_request;
+    struct get_process_time_request get_process_time_request;
 };
 union generic_reply
 {
@@ -6702,8 +6717,9 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
     struct suspend_process_reply suspend_process_reply;
     struct resume_process_reply resume_process_reply;
+    struct get_process_time_reply get_process_time_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 595
+#define SERVER_PROTOCOL_VERSION 596
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/process.c b/server/process.c
index 73984f363f..112006b02e 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1792,3 +1792,38 @@ DECL_HANDLER(resume_process)
         release_object( process );
     }
 }
+
+/* Get kernel and user time for a process */
+DECL_HANDLER(get_process_time)
+{
+    char procPath[32];
+    char line[1024];
+    FILE *procPidStat = NULL;
+    //See man (5) proc for format of /proc/[pid]/stat file
+    const char *procPidStatFmt = "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu";
+    unsigned __int64 utime = 0;
+    unsigned __int64 stime = 0;
+    struct process *process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION );
+
+    if (!process) return;
+#ifdef linux
+    if (process->unix_pid != -1)
+    {
+        sprintf( procPath, "/proc/%u/stat", process->unix_pid );
+        if ((procPidStat = fopen( procPath, "r" )))
+        {
+            fgets( line, sizeof(line), procPidStat );
+            if (sscanf( line, procPidStatFmt, &utime, &stime ) == 2)
+            {
+                reply->utime = utime;
+                reply->stime = stime;
+            }
+            else set_error(STATUS_SEVERITY_ERROR);
+            fclose(procPidStat);
+        }
+        else set_error( STATUS_ACCESS_DENIED );
+    }
+    else set_error( STATUS_ACCESS_DENIED );
+#endif
+    release_object( process );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 6c44b2b43f..5cc568a5bb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3956,3 +3956,11 @@ struct handle_info
 @REQ(resume_process)
     obj_handle_t handle;       /* process handle */
 @END
+
+/* Get kernel and user time for a process */
+ at REQ(get_process_time)
+    obj_handle_t handle;       /* process handle */
+ at REPLY
+    unsigned __int64 utime;   /* time process has spent in user mode */
+    unsigned __int64 stime;   /* time process has spent in kernel mode */
+ at END
diff --git a/server/request.h b/server/request.h
index 15fcb671bb..b38a9f0b5a 100644
--- a/server/request.h
+++ b/server/request.h
@@ -410,6 +410,7 @@ DECL_HANDLER(set_job_completion_port);
 DECL_HANDLER(terminate_job);
 DECL_HANDLER(suspend_process);
 DECL_HANDLER(resume_process);
+DECL_HANDLER(get_process_time);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -713,6 +714,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_terminate_job,
     (req_handler)req_suspend_process,
     (req_handler)req_resume_process,
+    (req_handler)req_get_process_time,
 };
 
 C_ASSERT( sizeof(affinity_t) == 8 );
@@ -741,6 +743,7 @@ C_ASSERT( sizeof(rectangle_t) == 16 );
 C_ASSERT( sizeof(short int) == 2 );
 C_ASSERT( sizeof(thread_id_t) == 4 );
 C_ASSERT( sizeof(timeout_t) == 8 );
+C_ASSERT( sizeof(unsigned __int64) == 8 );
 C_ASSERT( sizeof(unsigned char) == 1 );
 C_ASSERT( sizeof(unsigned int) == 4 );
 C_ASSERT( sizeof(unsigned short) == 2 );
@@ -2445,6 +2448,11 @@ C_ASSERT( FIELD_OFFSET(struct suspend_process_request, handle) == 12 );
 C_ASSERT( sizeof(struct suspend_process_request) == 16 );
 C_ASSERT( FIELD_OFFSET(struct resume_process_request, handle) == 12 );
 C_ASSERT( sizeof(struct resume_process_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_process_time_request, handle) == 12 );
+C_ASSERT( sizeof(struct get_process_time_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_process_time_reply, utime) == 8 );
+C_ASSERT( FIELD_OFFSET(struct get_process_time_reply, stime) == 16 );
+C_ASSERT( sizeof(struct get_process_time_reply) == 24 );
 
 #endif  /* WANT_REQUEST_HANDLERS */
 
diff --git a/server/trace.c b/server/trace.c
index 79e3f22ee5..c69531c9de 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -4608,6 +4608,17 @@ static void dump_resume_process_request( const struct resume_process_request *re
     fprintf( stderr, " handle=%04x", req->handle );
 }
 
+static void dump_get_process_time_request( const struct get_process_time_request *req )
+{
+    fprintf( stderr, " handle=%04x", req->handle );
+}
+
+static void dump_get_process_time_reply( const struct get_process_time_reply *req )
+{
+    dump_uint64( " utime=", &req->utime );
+    dump_uint64( ", stime=", &req->stime );
+}
+
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_exec_process_request,
@@ -4906,6 +4917,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_terminate_job_request,
     (dump_func)dump_suspend_process_request,
     (dump_func)dump_resume_process_request,
+    (dump_func)dump_get_process_time_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -5206,6 +5218,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     NULL,
     NULL,
     NULL,
+    (dump_func)dump_get_process_time_reply,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -5506,6 +5519,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "terminate_job",
     "suspend_process",
     "resume_process",
+    "get_process_time",
 };
 
 static const struct
@@ -5625,6 +5639,7 @@ static const struct
     { "REPARSE_POINT_NOT_RESOLVED",  STATUS_REPARSE_POINT_NOT_RESOLVED },
     { "SECTION_TOO_BIG",             STATUS_SECTION_TOO_BIG },
     { "SEMAPHORE_LIMIT_EXCEEDED",    STATUS_SEMAPHORE_LIMIT_EXCEEDED },
+    { "SEVERITY_ERROR",              STATUS_SEVERITY_ERROR },
     { "SHARING_VIOLATION",           STATUS_SHARING_VIOLATION },
     { "SHUTDOWN_IN_PROGRESS",        STATUS_SHUTDOWN_IN_PROGRESS },
     { "SUSPEND_COUNT_EXCEEDED",      STATUS_SUSPEND_COUNT_EXCEEDED },
-- 
2.25.0




More information about the wine-devel mailing list