[PATCH 2/3] server: Add get_process_time
brock at polynubstudios.com
brock at polynubstudios.com
Wed Feb 19 03:50:28 CST 2020
From: Brock York <twunknown at gmail.com>
get_process_time returns the amount of time a given
process has spent in the kernel and user mode.
Reads from /proc/[pid]/stat the utime and stime fields
---
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