aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan José <soyjuanarbol@gmail.com>2025-01-14 08:50:26 -0500
committerGitHub <noreply@github.com>2025-01-14 14:50:26 +0100
commitbe8eec8c5a99bcce5a1b8435237dad588cfd9f28 (patch)
treefc5fe595617637d6998c0ff6298198b7cce3f794
parente59e2a9e49c96feffebdfd44915320e32a91a957 (diff)
downloadlibuv-be8eec8c5a99bcce5a1b8435237dad588cfd9f28.tar.gz
libuv-be8eec8c5a99bcce5a1b8435237dad588cfd9f28.zip
misc: implement uv_getrusage_thread (#4666)
Refs: https://github.com/libuv/libuv/issues/3119 Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com> Co-authored-by: James M Snell <jasnell@gmail.com>
-rw-r--r--docs/src/misc.rst11
-rw-r--r--include/uv.h1
-rw-r--r--src/unix/core.c48
-rw-r--r--src/win/util.c88
-rw-r--r--test/test-platform-output.c16
5 files changed, 140 insertions, 24 deletions
diff --git a/docs/src/misc.rst b/docs/src/misc.rst
index 61883b7e..db95e2dd 100644
--- a/docs/src/misc.rst
+++ b/docs/src/misc.rst
@@ -360,6 +360,17 @@ API
On Windows not all fields are set, the unsupported fields are filled with zeroes.
See :c:type:`uv_rusage_t` for more details.
+.. c:function:: int uv_getrusage_thread(uv_rusage_t* rusage)
+
+ Gets the resource usage measures for the calling thread.
+
+ .. versionadded:: 1.50.0
+
+ .. note::
+ Not supported on all platforms. May return `UV_ENOTSUP`.
+ On macOS and Windows not all fields are set, the unsupported fields are filled with zeroes.
+ See :c:type:`uv_rusage_t` for more details.
+
.. c:function:: uv_pid_t uv_os_getpid(void)
Returns the current process ID.
diff --git a/include/uv.h b/include/uv.h
index b1689e96..f0ec376b 100644
--- a/include/uv.h
+++ b/include/uv.h
@@ -1295,6 +1295,7 @@ typedef struct {
} uv_rusage_t;
UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
+UV_EXTERN int uv_getrusage_thread(uv_rusage_t* rusage);
UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
diff --git a/src/unix/core.c b/src/unix/core.c
index 66053780..61cbc0d0 100644
--- a/src/unix/core.c
+++ b/src/unix/core.c
@@ -52,6 +52,8 @@
#endif
#if defined(__APPLE__)
+# include <mach/mach.h>
+# include <mach/thread_info.h>
# include <sys/filio.h>
# include <sys/sysctl.h>
#endif /* defined(__APPLE__) */
@@ -999,10 +1001,10 @@ int uv__fd_exists(uv_loop_t* loop, int fd) {
}
-int uv_getrusage(uv_rusage_t* rusage) {
+static int uv__getrusage(int who, uv_rusage_t* rusage) {
struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage))
+ if (getrusage(who, &usage))
return UV__ERR(errno);
rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
@@ -1041,6 +1043,48 @@ int uv_getrusage(uv_rusage_t* rusage) {
}
+int uv_getrusage(uv_rusage_t* rusage) {
+ return uv__getrusage(RUSAGE_SELF, rusage);
+}
+
+
+int uv_getrusage_thread(uv_rusage_t* rusage) {
+#if defined(__APPLE__)
+ mach_msg_type_number_t count;
+ thread_basic_info_data_t info;
+ kern_return_t kr;
+ thread_t thread;
+
+ thread = mach_thread_self();
+ count = THREAD_BASIC_INFO_COUNT;
+ kr = thread_info(thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t)&info,
+ &count);
+
+ if (kr != KERN_SUCCESS) {
+ mach_port_deallocate(mach_task_self(), thread);
+ return UV_EINVAL;
+ }
+
+ memset(rusage, 0, sizeof(*rusage));
+
+ rusage->ru_utime.tv_sec = info.user_time.seconds;
+ rusage->ru_utime.tv_usec = info.user_time.microseconds;
+ rusage->ru_stime.tv_sec = info.system_time.seconds;
+ rusage->ru_stime.tv_usec = info.system_time.microseconds;
+
+ mach_port_deallocate(mach_task_self(), thread);
+
+ return 0;
+
+#elif defined(RUSAGE_THREAD)
+ return uv__getrusage(RUSAGE_THREAD, rusage);
+#endif /* defined(__APPLE__) */
+ return UV_ENOTSUP;
+}
+
+
int uv__open_cloexec(const char* path, int flags) {
#if defined(O_CLOEXEC)
int fd;
diff --git a/src/win/util.c b/src/win/util.c
index d7b5f661..1d1b2837 100644
--- a/src/win/util.c
+++ b/src/win/util.c
@@ -874,56 +874,100 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
int uv_getrusage(uv_rusage_t *uv_rusage) {
- FILETIME createTime, exitTime, kernelTime, userTime;
- SYSTEMTIME kernelSystemTime, userSystemTime;
- PROCESS_MEMORY_COUNTERS memCounters;
- IO_COUNTERS ioCounters;
+ FILETIME create_time, exit_time, kernel_time, user_time;
+ SYSTEMTIME kernel_system_time, user_system_time;
+ PROCESS_MEMORY_COUNTERS mem_counters;
+ IO_COUNTERS io_counters;
int ret;
- ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
+ ret = GetProcessTimes(GetCurrentProcess(),
+ &create_time,
+ &exit_time,
+ &kernel_time,
+ &user_time);
if (ret == 0) {
return uv_translate_sys_error(GetLastError());
}
- ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
+ ret = FileTimeToSystemTime(&kernel_time, &kernel_system_time);
if (ret == 0) {
return uv_translate_sys_error(GetLastError());
}
- ret = FileTimeToSystemTime(&userTime, &userSystemTime);
+ ret = FileTimeToSystemTime(&user_time, &user_system_time);
if (ret == 0) {
return uv_translate_sys_error(GetLastError());
}
ret = GetProcessMemoryInfo(GetCurrentProcess(),
- &memCounters,
- sizeof(memCounters));
+ &mem_counters,
+ sizeof(mem_counters));
if (ret == 0) {
return uv_translate_sys_error(GetLastError());
}
- ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
+ ret = GetProcessIoCounters(GetCurrentProcess(), &io_counters);
if (ret == 0) {
return uv_translate_sys_error(GetLastError());
}
memset(uv_rusage, 0, sizeof(*uv_rusage));
- uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
- userSystemTime.wMinute * 60 +
- userSystemTime.wSecond;
- uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
+ uv_rusage->ru_utime.tv_sec = user_system_time.wHour * 3600 +
+ user_system_time.wMinute * 60 +
+ user_system_time.wSecond;
+ uv_rusage->ru_utime.tv_usec = user_system_time.wMilliseconds * 1000;
- uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
- kernelSystemTime.wMinute * 60 +
- kernelSystemTime.wSecond;
- uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
+ uv_rusage->ru_stime.tv_sec = kernel_system_time.wHour * 3600 +
+ kernel_system_time.wMinute * 60 +
+ kernel_system_time.wSecond;
+ uv_rusage->ru_stime.tv_usec = kernel_system_time.wMilliseconds * 1000;
- uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
- uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
+ uv_rusage->ru_majflt = (uint64_t) mem_counters.PageFaultCount;
+ uv_rusage->ru_maxrss = (uint64_t) mem_counters.PeakWorkingSetSize / 1024;
- uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
- uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
+ uv_rusage->ru_oublock = (uint64_t) io_counters.WriteOperationCount;
+ uv_rusage->ru_inblock = (uint64_t) io_counters.ReadOperationCount;
+
+ return 0;
+}
+
+
+int uv_getrusage_thread(uv_rusage_t* uv_rusage) {
+ FILETIME create_time, exit_time, kernel_time, user_time;
+ SYSTEMTIME kernel_system_time, user_system_time;
+ int ret;
+
+ ret = GetThreadTimes(GetCurrentThread(),
+ &create_time,
+ &exit_time,
+ &kernel_time,
+ &user_time);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ ret = FileTimeToSystemTime(&kernel_time, &kernel_system_time);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ ret = FileTimeToSystemTime(&user_time, &user_system_time);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ memset(uv_rusage, 0, sizeof(*uv_rusage));
+
+ uv_rusage->ru_utime.tv_sec = user_system_time.wHour * 3600 +
+ user_system_time.wMinute * 60 +
+ user_system_time.wSecond;
+ uv_rusage->ru_utime.tv_usec = user_system_time.wMilliseconds * 1000;
+
+ uv_rusage->ru_stime.tv_sec = kernel_system_time.wHour * 3600 +
+ kernel_system_time.wMinute * 60 +
+ kernel_system_time.wSecond;
+ uv_rusage->ru_stime.tv_usec = kernel_system_time.wMilliseconds * 1000;
return 0;
}
diff --git a/test/test-platform-output.c b/test/test-platform-output.c
index 4e5300da..d9b39c74 100644
--- a/test/test-platform-output.c
+++ b/test/test-platform-output.c
@@ -236,5 +236,21 @@ TEST_IMPL(platform_output) {
printf(" version: %s\n", uname.version);
printf(" machine: %s\n", uname.machine);
+ ASSERT_OK(uv_getrusage_thread(&rusage));
+ ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0);
+ ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0);
+ ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0);
+ ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0);
+ printf("uv_getrusage_thread:\n");
+ printf(" user: %llu sec %llu microsec\n",
+ (unsigned long long) rusage.ru_utime.tv_sec,
+ (unsigned long long) rusage.ru_utime.tv_usec);
+ printf(" system: %llu sec %llu microsec\n",
+ (unsigned long long) rusage.ru_stime.tv_sec,
+ (unsigned long long) rusage.ru_stime.tv_usec);
+ printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt);
+ printf(" maximum resident set size: %llu\n",
+ (unsigned long long) rusage.ru_maxrss);
+
return 0;
}