xref: /rockchip-linux_mpp/osal/test/mpp_runtime_test.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "mpp_rt_test"
7 
8 #include <stdio.h>
9 #include <pthread.h>
10 #include <time.h>
11 #include <errno.h>
12 
13 #ifdef __GLIBC__
14 #include <gnu/libc-version.h>
15 #endif
16 
17 #ifdef __ANDROID__
18 #include <android/api-level.h>
19 #include <sys/system_properties.h>
20 #endif
21 
22 #if defined(__USE_XOPEN2K) || (defined(__ANDROID__) && __ANDROID_API__ >= 21)
23 #define COND_USE_CLOCK_MONOTONIC
24 #endif
25 
26 #include "mpp_log.h"
27 #include "mpp_runtime.h"
28 
29 clockid_t clock_id = CLOCK_REALTIME;
30 
allocator_check()31 rk_s32 allocator_check()
32 {
33     if (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION))
34         mpp_logi("mpp found ion buffer is valid\n");
35     else
36         mpp_logi("mpp found ion buffer is invalid\n");
37 
38     if (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM))
39         mpp_logi("mpp found drm buffer is valid\n");
40     else
41         mpp_logi("mpp found drm buffer is invalid\n");
42 
43     return MPP_OK;
44 }
45 
46 #if defined(__ANDROID__)
47 // Android OS
os_check()48 int os_check()
49 {
50     char version_str[PROP_VALUE_MAX];
51     char sdk_str[PROP_VALUE_MAX];
52     rk_u32 sdk_api_level = 0;
53 
54     mpp_logi("Compiled for Android System.\n");
55 
56     __system_property_get("ro.build.version.sdk", sdk_str);
57     __system_property_get("ro.build.version.release", version_str);
58     sdk_api_level = atoi(sdk_str);
59 
60     mpp_logi("Running on Android %s, api level %d, program compiled with api level %d.\n",
61              version_str, sdk_api_level, __ANDROID_API__);
62 
63     if (sdk_api_level < __ANDROID_API__)
64         mpp_logi("Warning!!! Target is compiled for a higher api level than current system.\n");
65 
66     // check libc
67 #if defined(__BIONIC__)
68     mpp_logi("Using bionic libc.\n");
69 #else
70     mpp_logi("Unknown libc.\n");
71 #endif // __BIONIC__
72 
73 // POSIX C compatibility test
74     if (__ANDROID_API__ >= 21) {
75         clock_id = CLOCK_MONOTONIC;
76         mpp_logi("pthread_condattr_setclock is defined.\n");
77 
78         if (__ANDROID_API__ >= 30)
79             mpp_logi("pthread_cond_clockwait is defined.\n");
80         else
81             mpp_logi("pthread_cond_clockwait is not defined.\n");
82     } else {
83         mpp_logi("pthread_condattr_setclock is not defined.\n");
84     }
85 
86     return 0;
87 }
88 
89 #else
90 
91 // Linux OS
os_check()92 int os_check()
93 {
94 #if defined(linux) && !defined(__ANDROID__)
95     mpp_logi("Compiled for Linux.\n");
96 #else
97     mpp_logi("Compiled for Unknown OS.\n");
98 #endif // OS check
99 
100     // check libc
101 #if defined(__GLIBC__)
102     mpp_logi("Compiled with glibc %d-%d, running with glibc %s.\n", __GLIBC__, __GLIBC_MINOR__, gnu_get_libc_version());
103 #elif defined(__UCLIBC__)
104     mpp_logi("Using uClibc.\n");
105 #if defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) && defined(__UCLIBC_SUBLEVEL__)
106     mpp_logi("Compiled with uClibc version: %d.%d.%d.\n",
107              __UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__);
108 #else
109     mpp_logi("uClibc version macros not available.\n");
110 #endif
111     mpp_logi("pthread_cond_clockwait is not defined.\n");
112 #elif defined(__MUSL__)
113     mpp_logi("Using musl libc.\n");
114 #else
115     mpp_logi("Unknown libc.\n");
116 #endif // LIBC check
117 
118 // POSIX C compatibility test
119 #if defined(__USE_XOPEN2K)
120     clock_id = CLOCK_MONOTONIC;
121     mpp_logi("XPG6 is supported.\n");
122     mpp_logi("pthread_condattr_setclock is defined.\n");
123 #else
124     mpp_logi("XPG6 is not supported.\n");
125     mpp_logi("pthread_condattr_setclock is not defined.\n");
126 #endif // __USE_XOPEN2K
127 
128     return 0;
129 }
130 #endif // USE_XOPEN2K
131 
132 #ifdef COND_USE_CLOCK_MONOTONIC
133 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
134 pthread_cond_t cond;
135 rk_u32 condition = 0;
136 
wait_thread()137 void *wait_thread()
138 {
139     int ret;
140     struct timespec ts, ts_s, ts_e;
141     char time_str[64];
142     struct tm *tm_info;
143 
144     pthread_mutex_lock(&mutex);
145 
146     clock_gettime(CLOCK_MONOTONIC, &ts);
147     clock_gettime(CLOCK_REALTIME, &ts_s);
148 
149     ts.tv_sec += 1; // timeout after 1 sec
150     tm_info = localtime(&ts_s.tv_sec);
151     strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
152 
153     mpp_logi("Current time is: %s.%08ld.\n", time_str, ts_s.tv_nsec);
154     mpp_logi("Thread is waiting at monotonic time: %ld sec %ld nsec, will be timeout after 1 sec.\n",
155              ts.tv_sec, ts.tv_nsec);
156 
157     while (!condition) {
158         ret = pthread_cond_timedwait(&cond, &mutex, &ts);
159 
160         if (ret == ETIMEDOUT) {
161             clock_gettime(CLOCK_REALTIME, &ts_e);
162             tm_info = localtime(&ts_e.tv_sec);
163             strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
164 
165             mpp_logi("Timeout expired at %s.%09ld.\n", time_str, ts_e.tv_nsec);
166 
167             if ((ts_e.tv_sec - ts_s.tv_sec) != 1)
168                 mpp_loge("Error! Timeout expired too soon or too late.\n");
169             else
170                 mpp_logi("pthrad_cond_timedwait is reliable when using CLOCK_MONOTONIC\n");
171 
172             pthread_mutex_unlock(&mutex);
173             return NULL;
174         }
175     }
176 
177     mpp_logi("Thread is waked up.");
178     pthread_mutex_unlock(&mutex);
179     return NULL;
180 }
181 
check_pthread_clock()182 int check_pthread_clock()
183 {
184     pthread_condattr_t cond_attr;
185     pthread_t thread;
186 
187     pthread_condattr_init(&cond_attr);
188     if (pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC)) {
189         mpp_loge("pthread is not supported with CLOCK_MONOTONIC\n");
190         pthread_condattr_destroy(&cond_attr);
191         pthread_mutex_destroy(&mutex);
192         return -1;
193     }
194     pthread_cond_init(&cond, &cond_attr);
195 
196     pthread_create(&thread, NULL, wait_thread, NULL);
197     pthread_join(thread, NULL);
198 
199     pthread_mutex_destroy(&mutex);
200     pthread_cond_destroy(&cond);
201     pthread_condattr_destroy(&cond_attr);
202 
203     return 0;
204 }
205 #endif // COND_USE_CLOCK_MONOTONIC
206 
main()207 int main()
208 {
209     allocator_check();
210     // system compatibility test
211 #if defined(__LP64__)
212     mpp_logi("This is 64-bit program.\n");
213 #else
214     mpp_logi("This is 32-bit program.\n");
215 #endif // __LP64__
216 
217     os_check();
218 
219 #ifdef COND_USE_CLOCK_MONOTONIC
220     if (check_pthread_clock())
221         mpp_loge("Warning! pthread_cond_timedwait will not be reliable!\n");
222 #else
223     mpp_logi("pthread clock compatibility checking is skipped.\n");
224     mpp_loge("Warning! pthread_cond_timedwait will not be reliable!\n");
225 #endif // COND_USE_CLOCK_MONOTONIC
226 
227     return 0;
228 }
229