You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
[{"commit":{"message":"Remove unused imports"},"files":[{"filename":"test\/micro\/org\/openjdk\/bench\/vm\/runtime\/CPUTime.java"}],"sha":"c022266d791dbb7b8614df8551f1da11fb6ea1db"},{"commit":{"message":"Add review fixes"},"files":[{"filename":"src\/hotspot\/os\/linux\/os_linux.cpp"}],"sha":"52b1c3ab4ae978effd158d533257c20b8f2bbfda"},{"commit":{"message":"Replace proc with fast Linux specific solution\n\nFixy\n\nRemove imports added by IDE\n\nRemove imports added by IDE\n\nDon't touch bit 3\n\nFix name"},"files":[{"filename":"src\/hotspot\/os\/linux\/os_linux.cpp"},{"filename":"src\/hotspot\/os\/linux\/os_linux.hpp"},{"filename":"test\/micro\/org\/openjdk\/bench\/vm\/runtime\/CPUTime.java"}],"sha":"b3b74d6447a9e61d30e6a1a61a403bef23229ba7"}]
{"files":[{"patch":"@@ -4306,1 +4306,1 @@\n-jlong os::Linux::total_thread_cpu_time(clockid_t clockid) {\n+jlong os::Linux::thread_cpu_time(clockid_t clockid) {\n@@ -4961,0 +4961,23 @@\n+\/\/ Since kernel v2.6.12 the Linux ABI have had support for encoding the clock types\n+\/\/ in the last three bits. Setting bit to 001 (CPUCLOCK_VIRT) will result in the kernel\n+\/\/ returning only user time. POSIX compliant implementations of pthread_getcpuclockid\n+\/\/ for the Linux kernel defaults to construct a clockid with 010 (CPUCLOCK_SCHED)\n+\/\/ set, which return system+user time, which is what the POSIX standard mandates, see\n+\/\/ POSIX.1-2024\/IEEE Std 1003.1-2024 §3.90.\n+static clockid_t get_thread_clockid(Thread* thread, bool total, bool* success) {\n+ constexpr clockid_t CLOCK_TYPE_MASK = 3;\n+ constexpr clockid_t CPUCLOCK_VIRT = 1;\n+\n+ clockid_t clockid;\n+ int rc = pthread_getcpuclockid(thread->osthread()->pthread_id(), &clockid);\n+ if (rc == 0) {\n+ clockid = total ? clockid : (clockid & ~CLOCK_TYPE_MASK) | CPUCLOCK_VIRT;\n+ } else {\n+ \/\/ It's possible to encounter a terminated native thread that failed\n+ \/\/ to detach itself from the VM - which should result in ESRCH.\n+ assert_status(rc == ESRCH, rc, \"pthread_getcpuclockid failed\");\n+ *success = false;\n+ }\n+ return clockid;\n+}\n+\n@@ -4964,11 +4987,4 @@\n- clockid_t clockid;\n- int rc = pthread_getcpuclockid(thread->osthread()->pthread_id(),\n- &clockid);\n- if (rc == 0) {\n- return os::Linux::total_thread_cpu_time(clockid);\n- } else {\n- \/\/ It's possible to encounter a terminated native thread that failed\n- \/\/ to detach itself from the VM - which should result in ESRCH.\n- assert_status(rc == ESRCH, rc, \"pthread_getcpuclockid failed\");\n- return -1;\n- }\n+ bool success = true;\n+ clockid_t clockid = get_thread_clockid(thread, true, &success);\n+\n+ return success ? os::Linux::thread_cpu_time(clockid) : -1;\n@@ -4985,1 +5001,1 @@\n- return os::Linux::total_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);\n+ return os::Linux::thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);\n@@ -4994,1 +5010,1 @@\n- return os::Linux::total_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);\n+ return os::Linux::thread_cpu_time(CLOCK_THREAD_CPUTIME_ID);\n@@ -5008,1 +5024,0 @@\n-\/\/ -1 on error.\n@@ -5010,38 +5025,4 @@\n- pid_t tid = thread->osthread()->thread_id();\n- char *s;\n- char stat[2048];\n- size_t statlen;\n- char proc_name[64];\n- int count;\n- long sys_time, user_time;\n- char cdummy;\n- int idummy;\n- long ldummy;\n- FILE *fp;\n-\n- os::snprintf_checked(proc_name, 64, \"\/proc\/self\/task\/%d\/stat\", tid);\n- fp = os::fopen(proc_name, \"r\");\n- if (fp == nullptr) return -1;\n- statlen = fread(stat, 1, 2047, fp);\n- stat[statlen] = '\\0';\n- fclose(fp);\n-\n- \/\/ Skip pid and the command string. Note that we could be dealing with\n- \/\/ weird command names, e.g. user could decide to rename java launcher\n- \/\/ to \"java 1.4.2 :)\", then the stat file would look like\n- \/\/ 1234 (java 1.4.2 :)) R ... ...\n- \/\/ We don't really need to know the command string, just find the last\n- \/\/ occurrence of \")\" and then start parsing from there. See bug 4726580.\n- s = strrchr(stat, ')');\n- if (s == nullptr) return -1;\n-\n- \/\/ Skip blank chars\n- do { s++; } while (s && isspace((unsigned char) *s));\n-\n- count = sscanf(s,\"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu\",\n- &cdummy, &idummy, &idummy, &idummy, &idummy, &idummy,\n- &ldummy, &ldummy, &ldummy, &ldummy, &ldummy,\n- &user_time, &sys_time);\n- if (count != 13) return -1;\n-\n- return (jlong)user_time * (1000000000 \/ os::Posix::clock_tics_per_second());\n+ bool success = true;\n+ clockid_t clockid = get_thread_clockid(thread, false, &success);\n+\n+ return success ? os::Linux::thread_cpu_time(clockid) : -1;\n","filename":"src\/hotspot\/os\/linux\/os_linux.cpp","additions":34,"deletions":53,"binary":false,"changes":87,"status":"modified"},{"patch":"@@ -145,1 +145,1 @@\n- static jlong total_thread_cpu_time(clockid_t clockid);\n+ static jlong thread_cpu_time(clockid_t clockid);\n","filename":"src\/hotspot\/os\/linux\/os_linux.hpp","additions":1,"deletions":1,"binary":false,"changes":2,"status":"modified"},{"patch":"@@ -0,0 +1,55 @@\n+\/*\n+ * Copyright (c) 2025, Oracle and\/or its affiliates. All rights reserved.\n+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n+ *\n+ * This code is free software; you can redistribute it and\/or modify it\n+ * under the terms of the GNU General Public License version 2 only, as\n+ * published by the Free Software Foundation.\n+ *\n+ * This code is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n+ * version 2 for more details (a copy is included in the LICENSE file that\n+ * accompanied this code).\n+ *\n+ * You should have received a copy of the GNU General Public License version\n+ * 2 along with this work; if not, write to the Free Software Foundation,\n+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n+ *\n+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n+ * or visit www.oracle.com if you need additional information or have any\n+ * questions.\n+ *\/\n+package org.openjdk.bench.vm.runtime;\n+\n+import java.lang.management.ManagementFactory;\n+import java.lang.management.ThreadMXBean;\n+import java.util.concurrent.TimeUnit;\n+\n+import org.openjdk.jmh.annotations.Benchmark;\n+import org.openjdk.jmh.annotations.BenchmarkMode;\n+import org.openjdk.jmh.annotations.Fork;\n+import org.openjdk.jmh.annotations.Measurement;\n+import org.openjdk.jmh.annotations.Mode;\n+import org.openjdk.jmh.annotations.OutputTimeUnit;\n+import org.openjdk.jmh.annotations.Scope;\n+import org.openjdk.jmh.annotations.State;\n+import org.openjdk.jmh.annotations.Threads;\n+import org.openjdk.jmh.annotations.Warmup;\n+\n+@State(Scope.Benchmark)\n+@Warmup(iterations = 5, time = 10)\n+@Measurement(iterations = 5, time = 10)\n+@BenchmarkMode(Mode.SampleTime)\n+@OutputTimeUnit(TimeUnit.MILLISECONDS)\n+@Threads(1)\n+@Fork(value = 5)\n+public class CPUTime {\n+ static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean();\n+ static long user; \/\/ To avoid dead-code elimination\n+\n+ @Benchmark\n+ public void execute() throws Throwable {\n+ user = mxThreadBean.getCurrentThreadUserTime();\n+ }\n+}\n","filename":"test\/micro\/org\/openjdk\/bench\/vm\/runtime\/CPUTime.java","additions":55,"deletions":0,"binary":false,"changes":55,"status":"added"}]}