• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <jni.h>
2 #include <pthread.h>
3 #include <stdlib.h>
4 #include <time.h>
5 #include <string>
6 
7 #define noinline __attribute__((__noinline__))
8 extern "C" JNIEXPORT jstring JNICALL
Java_simpleperf_example_cpp_MainActivity_stringFromJNI(JNIEnv * env,jobject)9 Java_simpleperf_example_cpp_MainActivity_stringFromJNI(
10         JNIEnv* env,
11         jobject /* this */) {
12     std::string hello = "Hello from C++";
13     return env->NewStringUTF(hello.c_str());
14 }
15 
ThrowErrnoException(JNIEnv * env,const char * function_name,int err)16 static void ThrowErrnoException(JNIEnv* env, const char* function_name, int err) {
17     jclass cls = env->FindClass("android/system/ErrnoException");
18     if (cls == nullptr) {
19         return;
20     }
21     jmethodID cid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;I)V");
22     if (cid == nullptr) {
23         return;
24     }
25     jstring msg = env->NewStringUTF(function_name);
26     if (msg == nullptr) {
27         return;
28     }
29     jthrowable obj = (jthrowable)env->NewObject(cls, cid, msg, err);
30     if (obj == nullptr) {
31         return;
32     }
33     env->Throw(obj);
34 }
35 
CallFunction(int a)36 int CallFunction(int a) {
37     return a + atoi("1");
38 }
39 
BusyLoopThread(void *)40 static void* BusyLoopThread(void*) {
41     volatile int i = 0;
42     while (true) {
43         i = CallFunction(i);
44     }
45     return nullptr;
46 }
47 
48 extern "C"
49 JNIEXPORT void JNICALL
Java_simpleperf_example_cpp_MainActivity_createBusyThreadFromJNI(JNIEnv * env,jobject)50 Java_simpleperf_example_cpp_MainActivity_createBusyThreadFromJNI(
51     JNIEnv *env,
52     jobject /* this */) {
53     pthread_t thread;
54     int ret = pthread_create(&thread, nullptr, BusyLoopThread, nullptr);
55     if (ret) {
56         ThrowErrnoException(env, "pthread_create", ret);
57         return;
58     }
59 }
60 
GetSystemClock()61 static inline uint64_t GetSystemClock() {
62     timespec ts;
63     clock_gettime(CLOCK_MONOTONIC, &ts);
64     return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
65 }
66 
67 constexpr int LOOP_COUNT = 100000000;
RunFunction()68 static uint64_t noinline RunFunction() {
69     uint64_t start_time_in_ns = GetSystemClock();
70     for (volatile int i = 0; i < LOOP_COUNT; ++i) {
71     }
72     return GetSystemClock() - start_time_in_ns;
73 }
74 
SleepFunction(unsigned long long sleep_time_in_ns)75 static uint64_t noinline SleepFunction(unsigned long long sleep_time_in_ns) {
76     uint64_t start_time_in_ns = GetSystemClock();
77     struct timespec req;
78     req.tv_sec = sleep_time_in_ns / 1000000000;
79     req.tv_nsec = sleep_time_in_ns % 1000000000;
80     nanosleep(&req, nullptr);
81     return GetSystemClock() - start_time_in_ns;
82 }
83 
SleepThread(void *)84 static void* SleepThread(void*) {
85     pthread_setname_np(pthread_self(), "SleepThread");
86     uint64_t total_sleep_time_in_ns = 0;
87     uint64_t total_run_time_in_ns = 0;
88     while (true) {
89         total_run_time_in_ns += RunFunction();
90         if (total_sleep_time_in_ns < total_run_time_in_ns) {
91             total_sleep_time_in_ns += SleepFunction(total_run_time_in_ns - total_sleep_time_in_ns);
92         }
93     }
94 }
95 
96 extern "C"
97 JNIEXPORT void JNICALL
Java_simpleperf_example_cpp_SleepActivity_createSleepThreadFromJNI(JNIEnv * env,jobject)98 Java_simpleperf_example_cpp_SleepActivity_createSleepThreadFromJNI(
99     JNIEnv *env,
100     jobject /* this */) {
101     pthread_t thread;
102     int ret = pthread_create(&thread, nullptr, SleepThread, nullptr);
103     if (ret) {
104         ThrowErrnoException(env, "pthread_create", ret);
105         return;
106     }
107 }
108 
109 extern "C"
110 JNIEXPORT int JNICALL
Java_simpleperf_example_cpp_MixActivity_callFunction(JNIEnv * env,jobject,int a)111 Java_simpleperf_example_cpp_MixActivity_callFunction(
112     JNIEnv *env,
113     jobject /* this */,
114     int a) {
115     return CallFunction(a);
116 }