| 
1 | 1 | /*  | 
2 |  | - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.  | 
3 |  | - * Copyright (c) 2015, 2020 SAP SE. All rights reserved.  | 
 | 2 | + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.  | 
 | 3 | + * Copyright (c) 2015, 2025 SAP SE. All rights reserved.  | 
4 | 4 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.  | 
5 | 5 |  *  | 
6 | 6 |  * This code is free software; you can redistribute it and/or modify it  | 
 | 
28 | 28 | /* Implement and update https://bugs.openjdk.org/browse/JDK-8030957 */  | 
29 | 29 | 
 
  | 
30 | 30 | #include <jni.h>  | 
 | 31 | +#include <libperfstat.h>  | 
 | 32 | +#include <pthread.h>  | 
 | 33 | +#include <stdlib.h>  | 
 | 34 | +#include <time.h>  | 
31 | 35 | #include "com_sun_management_internal_OperatingSystemImpl.h"  | 
32 | 36 | 
 
  | 
 | 37 | +static struct perfMetrics{  | 
 | 38 | +    unsigned long long timebase;  | 
 | 39 | +    perfstat_process_t stats;  | 
 | 40 | +    perfstat_cpu_total_t cpu_total;  | 
 | 41 | +} counters;  | 
 | 42 | + | 
 | 43 | +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;  | 
 | 44 | + | 
 | 45 | +int perfInit() {  | 
 | 46 | +    static int initialized = 0;  | 
 | 47 | +    if (!initialized) {  | 
 | 48 | + | 
 | 49 | +        perfstat_id_t id;  | 
 | 50 | +        counters.stats = (perfstat_process_t){0};  | 
 | 51 | +        counters.timebase = 0;  | 
 | 52 | +        int rc = perfstat_cpu_total(NULL, &counters.cpu_total, sizeof(perfstat_cpu_total_t), 1);  | 
 | 53 | +        if (rc < 0) {  | 
 | 54 | +            return -1;  | 
 | 55 | +        }  | 
 | 56 | +        rc = perfstat_process(&id, &counters.stats, sizeof(perfstat_process_t), 1);  | 
 | 57 | +        if (rc < 0) {  | 
 | 58 | +            return -1;  | 
 | 59 | +        }  | 
 | 60 | +        counters.timebase = counters.stats.last_timebase;  | 
 | 61 | +        initialized = 1;  | 
 | 62 | +    }  | 
 | 63 | +    return initialized ? 0 : -1;  | 
 | 64 | +}  | 
 | 65 | + | 
33 | 66 | JNIEXPORT jdouble JNICALL  | 
34 | 67 | Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0  | 
35 | 68 | (JNIEnv *env, jobject dummy)  | 
36 | 69 | {  | 
37 |  | -    return -1.0;  | 
 | 70 | +    double load = -1.0;  | 
 | 71 | +    pthread_mutex_lock(&lock);  | 
 | 72 | +    if (perfInit() == 0) {  | 
 | 73 | +        int ret;  | 
 | 74 | +        perfstat_cpu_total_t cpu_total;  | 
 | 75 | +        ret = perfstat_cpu_total(NULL, &cpu_total, sizeof(perfstat_cpu_total_t), 1);  | 
 | 76 | +        if (ret < 0) {  | 
 | 77 | +            return -1.0;  | 
 | 78 | +        }  | 
 | 79 | +        long long user_diff = cpu_total.user - counters.cpu_total.user;  | 
 | 80 | +        long long sys_diff = cpu_total.sys - counters.cpu_total.sys;  | 
 | 81 | +        long long idle_diff = cpu_total.idle - counters.cpu_total.idle;  | 
 | 82 | +        long long wait_diff = cpu_total.wait - counters.cpu_total.wait;  | 
 | 83 | +        long long total = user_diff + sys_diff + idle_diff + wait_diff;  | 
 | 84 | +        if (total < (user_diff + sys_diff)) {  | 
 | 85 | +            total = user_diff + sys_diff;  | 
 | 86 | +        }  | 
 | 87 | +        if (total == 0) {  | 
 | 88 | +            load = 0.0;  | 
 | 89 | +        } else {  | 
 | 90 | +            load = (double)(user_diff + sys_diff) / total;  | 
 | 91 | +            load = MAX(load, 0.0);  | 
 | 92 | +            load = MIN(load, 1.0);  | 
 | 93 | +        }  | 
 | 94 | +        counters.cpu_total = cpu_total;  | 
 | 95 | +    }  | 
 | 96 | +    pthread_mutex_unlock(&lock);  | 
 | 97 | +    return load;  | 
38 | 98 | }  | 
39 | 99 | 
 
  | 
40 | 100 | JNIEXPORT jdouble JNICALL  | 
41 | 101 | Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0  | 
42 | 102 | (JNIEnv *env, jobject dummy)  | 
43 | 103 | {  | 
44 |  | -    return -1.0;  | 
 | 104 | +    perfstat_process_t curr_stats;  | 
 | 105 | +    perfstat_id_t id;  | 
 | 106 | +    unsigned long long curr_timebase, timebase_diff;  | 
 | 107 | +    double user_diff, sys_diff, delta_time;  | 
 | 108 | +    double cpu_load = -1.0;  | 
 | 109 | +    pthread_mutex_lock(&lock);  | 
 | 110 | +    if (perfInit() == 0) {  | 
 | 111 | +        int ret;  | 
 | 112 | +        ret = perfstat_process(&id, &curr_stats, sizeof(perfstat_process_t), 1);  | 
 | 113 | +        if (ret < 0) {  | 
 | 114 | +            return -1.0;  | 
 | 115 | +        }  | 
 | 116 | +        curr_timebase = curr_stats.last_timebase;  | 
 | 117 | +        timebase_diff = curr_timebase - counters.timebase;  | 
 | 118 | +        if ((long long)timebase_diff < 0 || XINTFRAC == 0) {  | 
 | 119 | +            return -1.0;  | 
 | 120 | +        }  | 
 | 121 | +        delta_time = HTIC2NANOSEC(timebase_diff) / 1000000000.0;  | 
 | 122 | +        user_diff = (double)(curr_stats.ucpu_time - counters.stats.ucpu_time);  | 
 | 123 | +        sys_diff  = (double)(curr_stats.scpu_time - counters.stats.scpu_time);  | 
 | 124 | +        counters.stats = curr_stats;  | 
 | 125 | +        counters.timebase = curr_timebase;  | 
 | 126 | +        if (delta_time == 0) {  | 
 | 127 | +            cpu_load = 0.0;  | 
 | 128 | +        } else {  | 
 | 129 | +            cpu_load = (user_diff + sys_diff) / delta_time;  | 
 | 130 | +            cpu_load = MAX(cpu_load, 0.0);  | 
 | 131 | +            cpu_load = MIN(cpu_load, 1.0);  | 
 | 132 | +        }  | 
 | 133 | +    }  | 
 | 134 | +    pthread_mutex_unlock(&lock);  | 
 | 135 | +    return (jdouble)cpu_load;  | 
45 | 136 | }  | 
46 | 137 | 
 
  | 
47 | 138 | JNIEXPORT jdouble JNICALL  | 
 | 
0 commit comments