• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hwe_osdep.h"
17 
18 #if defined(_WIN32)
19 #include "securec.h"
20 #endif
21 
22 #define ID_AA64PFR0_ADVSIMD_BIT 20
23 #define MVFR1_ADVSIMD_BIT 8
24 
25 namespace OHOS {
26 namespace ImagePlugin {
27 // detect cpu simd capibility
HWE_DetectSimdCapibility(void)28 HWE_KernelType HWE_DetectSimdCapibility(void)
29 {
30     HWE_KernelType ret = KERNEL_TYPE_C;
31 #if HWE_ARM_AARCH64
32     uint64_t regval = 0;
33     uint64_t advSimd;
34 
35     asm volatile("mrs %0, ID_AA64PFR0_EL1" : "=r"(regval));
36     advSimd = (regval >> ID_AA64PFR0_ADVSIMD_BIT) & 0xf; // 0xf: bitmask
37     if (advSimd == 0x0 || advSimd == 0x1) {              // 0x0: support neon without fp16; 0x1: support neno with fp16
38         ret = KERNEL_TYPE_NEON;
39     } else {
40         ret = KERNEL_TYPE_C;
41     }
42 #elif HWE_ARM_AARCH32
43 #if !HWE_IANDROID_ARM
44     uint32_t regval = 0;
45     uint32_t advSimd;
46 
47     asm volatile("mrs %0, MVFR1" : "=r"(regval));
48     advSimd = (regval >> MVFR1_ADVSIMD_BIT) & 0xfff; // 0xff: bitmask
49     if (advSimd == 0x111) {                          // 0x111: support neon
50         ret = KERNEL_TYPE_NEON;
51     } else {
52         ret = KERNEL_TYPE_C;
53     }
54 #else
55     ret = KERNEL_TYPE_NEON;
56 #endif
57 #elif HWE_X86_64
58     ret = KERNEL_TYPE_AVX2;
59 #elif HWE_X86_32
60     ret = KERNEL_TYPE_C;
61 #endif
62     return ret;
63 }
64 
65 #ifdef _WIN32
66 static HWE_Win32ThreadControl g_threadPool;
67 
HWE_PthreadMutexInit(HWE_PthreadMutex * mutex)68 int32_t HWE_PthreadMutexInit(HWE_PthreadMutex *mutex)
69 {
70     return !InitializeCriticalSectionAndSpinCount(mutex, HWE_SPIN_COUNT);
71 }
72 
HWE_PthreadMutexLock(HWE_PthreadMutex * mutex)73 int32_t HWE_PthreadMutexLock(HWE_PthreadMutex *mutex)
74 {
75     static HWE_PthreadMutex init = HWE_PTHREAD_MUTEX_INITIALIZER;
76     if (!memcmp(mutex, &init, sizeof(HWE_PthreadMutex))) {
77         *mutex = g_threadPool.staticMutex;
78     }
79     EnterCriticalSection(mutex);
80     return 0;
81 }
82 
HWE_PthreadMutexUnLock(HWE_PthreadMutex * mutex)83 int32_t HWE_PthreadMutexUnLock(HWE_PthreadMutex *mutex)
84 {
85     LeaveCriticalSection(mutex);
86     return 0;
87 }
88 
HWE_PthreadMutexDestroy(HWE_PthreadMutex * mutex)89 int32_t HWE_PthreadMutexDestroy(HWE_PthreadMutex *mutex)
90 {
91     LeaveCriticalSection(mutex);
92     return 0;
93 }
94 
HWE_PthreadCondInit(HWE_PthreadCond * cond)95 int32_t HWE_PthreadCondInit(HWE_PthreadCond *cond)
96 {
97     HWE_Win32Cond *win32Cond = nullptr;
98     if (g_threadPool.condInit) {
99         g_threadPool.condInit(cond);
100         return 0;
101     }
102     win32Cond = (HWE_Win32Cond *)calloc(1, sizeof(HWE_Win32Cond));
103     if (!win32Cond) {
104         return -1;
105     }
106     cond->ptr = win32Cond;
107     win32Cond->semaphore = CreateSemaphore(nullptr, 0, 0x7fffffff, nullptr);
108     if (!win32Cond->semaphore) {
109         return -1;
110     }
111     if (HWE_PthreadMutexInit(&win32Cond->mtxWaiterCount)) {
112         return -1;
113     }
114     if (HWE_PthreadMutexInit(&win32Cond->mtxBroadcast)) {
115         return -1;
116     }
117     win32Cond->waitersDone = CreateEvent(nullptr, FALSE, FALSE, nullptr);
118     if (!win32Cond->waitersDone) {
119         return -1;
120     }
121     return 0;
122 }
123 
HWE_PthreadCondDestroy(HWE_PthreadCond * cond)124 int32_t HWE_PthreadCondDestroy(HWE_PthreadCond *cond)
125 {
126     HWE_Win32Cond *win32Cond = nullptr;
127     if (g_threadPool.condInit) {
128         return 0;
129     }
130     win32Cond = (HWE_Win32Cond *)cond->ptr;
131     CloseHandle(win32Cond->semaphore);
132     CloseHandle(win32Cond->waitersDone);
133     HWE_PthreadMutexDestroy(&win32Cond->mtxBroadcast);
134     HWE_PthreadMutexDestroy(&win32Cond->mtxWaiterCount);
135     free(win32Cond);
136     return 0;
137 }
138 
HWE_PthreadCondWait(HWE_PthreadCond * cond,HWE_PthreadMutex * mutex)139 int32_t HWE_PthreadCondWait(HWE_PthreadCond *cond, HWE_PthreadMutex *mutex)
140 {
141     HWE_Win32Cond *win32Cond = nullptr;
142     int32_t iLastWaiter;
143     if (g_threadPool.condWait) {
144         return !g_threadPool.condWait(cond, mutex, INFINITE);
145     }
146     win32Cond = (HWE_Win32Cond *)cond->ptr;
147     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxBroadcast);
148     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxWaiterCount);
149     win32Cond->waiterCount++;
150     (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxWaiterCount);
151     (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxBroadcast);
152     (VOID)HWE_PthreadMutexUnLock(mutex);
153     WaitForSingleObject(win32Cond->semaphore, INFINITE);
154     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxWaiterCount);
155     win32Cond->waiterCount--;
156     iLastWaiter = !win32Cond->waiterCount || !win32Cond->isBroadcast;
157     (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxWaiterCount);
158     if (iLastWaiter) {
159         SetEvent(win32Cond->waitersDone);
160     }
161     return HWE_PthreadMutexLock(mutex);
162 }
163 
HWE_PthreadCondSignal(HWE_PthreadCond * cond)164 int32_t HWE_PthreadCondSignal(HWE_PthreadCond *cond)
165 {
166     HWE_Win32Cond *win32Cond = nullptr;
167     int32_t haveWaiter;
168     if (g_threadPool.condSignal) {
169         g_threadPool.condSignal(cond);
170         return 0;
171     }
172     win32Cond = (HWE_Win32Cond *)cond->ptr;
173     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxBroadcast);
174     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxWaiterCount);
175     haveWaiter = win32Cond->waiterCount;
176     (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxWaiterCount);
177     if (haveWaiter) {
178         ReleaseSemaphore(win32Cond->semaphore, 1, nullptr);
179         WaitForSingleObject(win32Cond->waitersDone, INFINITE);
180     }
181     return HWE_PthreadMutexUnLock(&win32Cond->mtxBroadcast);
182 }
183 
HWE_PthreadCondBroadcast(HWE_PthreadCond * cond)184 int32_t HWE_PthreadCondBroadcast(HWE_PthreadCond *cond)
185 {
186     HWE_Win32Cond *win32Cond = nullptr;
187     int32_t haveWaiter = 0;
188     if (g_threadPool.condBroadcast) {
189         g_threadPool.condBroadcast(cond);
190         return 0;
191     }
192     win32Cond = (HWE_Win32Cond *)cond->ptr;
193     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxBroadcast);
194     (VOID)HWE_PthreadMutexLock(&win32Cond->mtxWaiterCount);
195     if (win32Cond->waiterCount) {
196         win32Cond->isBroadcast = 1;
197         haveWaiter = 1;
198     }
199     if (haveWaiter) {
200         ReleaseSemaphore(win32Cond->semaphore, win32Cond->waiterCount, nullptr);
201         (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxWaiterCount);
202         WaitForSingleObject(win32Cond->waitersDone, INFINITE);
203         win32Cond->isBroadcast = 0;
204     } else {
205         (VOID)HWE_PthreadMutexUnLock(&win32Cond->mtxWaiterCount);
206     }
207     return HWE_PthreadMutexUnLock(&win32Cond->mtxBroadcast);
208 }
209 
HWE_Win32ThreadWorker(void * arg)210 static unsigned __stdcall HWE_Win32ThreadWorker(void *arg)
211 {
212     HWE_Pthread *enc = (HWE_Pthread *)arg;
213     enc->ret = enc->func(enc->arg);
214     return 0;
215 }
216 
HWE_PthreadJoin(HWE_Pthread thread)217 int32_t HWE_PthreadJoin(HWE_Pthread thread)
218 {
219     if (thread.isInit == 1) {
220         DWORD pRet = WaitForSingleObject(thread.handle, INFINITE);
221         if (pRet != WAIT_OBJECT_0) {
222             return -1;
223         }
224         CloseHandle(thread.handle);
225     }
226     return 0;
227 }
228 #endif
229 
230 #if !HWE_IANDROID_ARM
HWE_SetThreadAffinityMask(const HWE_Pthread * thread,uint32_t cpuNum,const uint32_t * cpuIdxArray)231 int32_t HWE_SetThreadAffinityMask(const HWE_Pthread *thread, uint32_t cpuNum, const uint32_t *cpuIdxArray)
232 {
233     if (cpuNum == 0) {
234         return 0;
235     }
236     if (thread->isInit) {
237 #if defined(_WIN32)
238         DWORD_PTR threadAffinityMask;
239         if (memset_s((void *)&threadAffinityMask, sizeof(DWORD_PTR), 0, sizeof(DWORD_PTR)) != 0) {
240             return -1;
241         }
242         for (uint32_t idx = 0; idx < cpuNum; idx++) {
243             threadAffinityMask |= (1 << cpuIdxArray[idx]);
244         }
245         int32_t ret = SetThreadAffinityMask(thread->handle, threadAffinityMask);
246         return (ret == 0);
247 #elif defined(__GNUC__)
248         cpu_set_t threadAffinityMask;
249         CPU_ZERO(&threadAffinityMask);
250         for (uint32_t idx = 0; idx < cpuNum; idx++) {
251             CPU_SET(cpuIdxArray[idx], &threadAffinityMask);
252         }
253 #ifdef A_PLATFORM
254         return sched_setaffinity(thread->thread, sizeof(threadAffinityMask), &threadAffinityMask);
255 #else
256         return pthread_setaffinity_np(thread->thread, sizeof(threadAffinityMask), &threadAffinityMask);
257 #endif
258 #else
259         return 0;
260 #endif
261     } else {
262         return -1;
263     }
264 }
265 
HWE_SetThreadPriority(const HWE_Pthread * thread,int32_t schedPriority)266 int32_t HWE_SetThreadPriority(const HWE_Pthread *thread, int32_t schedPriority)
267 {
268     if (thread->isInit) {
269 #if defined(_WIN32)
270         return (SetThreadPriority(thread->handle, schedPriority) == 0);
271 #elif defined(__GNUC__)
272         struct sched_param threadParam;
273         threadParam.sched_priority = schedPriority;
274         if (threadParam.sched_priority <= 0) {
275             return pthread_setschedparam(thread->thread, SCHED_OTHER, &threadParam);
276         } else {
277             return pthread_setschedparam(thread->thread, SCHED_RR, &threadParam);
278         }
279 #else
280         return 0;
281 #endif
282     } else {
283         return -1;
284     }
285 }
286 #endif
287 } // namespace ImagePlugin
288 } // namespace OHOS