History

reoranize common to inc/src/x86/arm

Licai Guo committed 12 years ago

Commit e39de8d1 parent 7313ecd40 files · +207 −207Browse files

Showing the changes to codec/common/src/WelsThreadLib.cpp (1 of 40 files). Show all

Unified · Split

codec/common/src/WelsThreadLib.cpp+473−0
@@ -0,0 +1,473 @@
1/*!
2 * \copy
3 * Copyright (c) 2009-2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *
32 * \file WelsThreadLib.c
33 *
34 * \brief Interfaces introduced in thread programming
35 *
36 * \date 11/17/2009 Created
37 *
38 *************************************************************************************
39 */
40
41
42#ifdef LINUX
43#ifndef _GNU_SOURCE
44#define _GNU_SOURCE
45#endif
46#include <sched.h>
47#elif !defined(_WIN32)
48#include <sys/types.h>
49#include <sys/sysctl.h>
50#include <sys/param.h>
51#include <unistd.h>
52#ifdef __APPLE__
53#define HW_NCPU_NAME "hw.logicalcpu"
54#else
55#define HW_NCPU_NAME "hw.ncpu"
56#endif
57#endif
58#ifdef ANDROID_NDK
59#include <cpu-features.h>
60#endif
61
62#include "WelsThreadLib.h"
63#include <stdio.h>
64#include <stdlib.h>
65
66
67#ifdef _WIN32
68
69#ifdef WINAPI_FAMILY
70#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
71#define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0)
72#endif
73#endif
74
75WELS_THREAD_ERROR_CODE WelsMutexInit (WELS_MUTEX* mutex) {
76 InitializeCriticalSection (mutex);
77
78 return WELS_THREAD_ERROR_OK;
79}
80
81WELS_THREAD_ERROR_CODE WelsMutexLock (WELS_MUTEX* mutex) {
82 EnterCriticalSection (mutex);
83
84 return WELS_THREAD_ERROR_OK;
85}
86
87WELS_THREAD_ERROR_CODE WelsMutexUnlock (WELS_MUTEX* mutex) {
88 LeaveCriticalSection (mutex);
89
90 return WELS_THREAD_ERROR_OK;
91}
92
93WELS_THREAD_ERROR_CODE WelsMutexDestroy (WELS_MUTEX* mutex) {
94 DeleteCriticalSection (mutex);
95
96 return WELS_THREAD_ERROR_OK;
97}
98
99#else /* _WIN32 */
100
101WELS_THREAD_ERROR_CODE WelsMutexInit (WELS_MUTEX* mutex) {
102 return pthread_mutex_init (mutex, NULL);
103}
104
105WELS_THREAD_ERROR_CODE WelsMutexLock (WELS_MUTEX* mutex) {
106 return pthread_mutex_lock (mutex);
107}
108
109WELS_THREAD_ERROR_CODE WelsMutexUnlock (WELS_MUTEX* mutex) {
110 return pthread_mutex_unlock (mutex);
111}
112
113WELS_THREAD_ERROR_CODE WelsMutexDestroy (WELS_MUTEX* mutex) {
114 return pthread_mutex_destroy (mutex);
115}
116
117#endif /* !_WIN32 */
118
119
120#ifdef MT_ENABLED
121
122#ifdef _WIN32
123
124void WelsSleep (uint32_t dwMilliseconds) {
125 Sleep (dwMilliseconds);
126}
127
128WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* event, const char* event_name) {
129 WELS_EVENT h = CreateEvent (NULL, FALSE, FALSE, NULL);
130
131 if (h == NULL) {
132 return WELS_THREAD_ERROR_GENERAL;
133 }
134 *event = h;
135 return WELS_THREAD_ERROR_OK;
136}
137
138WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {
139 if (SetEvent (*event)) {
140 return WELS_THREAD_ERROR_OK;
141 }
142 return WELS_THREAD_ERROR_GENERAL;
143}
144
145WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
146 return WaitForSingleObject (*event, INFINITE);
147}
148
149WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
150 return WaitForSingleObject (*event, dwMilliseconds);
151}
152
153WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
154 WELS_EVENT* event_list, WELS_EVENT* master_event) {
155 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
156 return WaitForMultipleObjects (nCount, event_list, FALSE, INFINITE);
157}
158
159WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
160 WELS_EVENT* event_list, WELS_EVENT* master_event) {
161 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
162 return WaitForMultipleObjects (nCount, event_list, TRUE, INFINITE);
163}
164
165WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
166 CloseHandle (*event);
167
168 *event = NULL;
169 return WELS_THREAD_ERROR_OK;
170}
171
172
173WELS_THREAD_ERROR_CODE WelsThreadCreate (WELS_THREAD_HANDLE* thread, LPWELS_THREAD_ROUTINE routine,
174 void* arg, WELS_THREAD_ATTR attr) {
175 WELS_THREAD_HANDLE h = CreateThread (NULL, 0, routine, arg, 0, NULL);
176
177 if (h == NULL) {
178 return WELS_THREAD_ERROR_GENERAL;
179 }
180 * thread = h;
181
182 return WELS_THREAD_ERROR_OK;
183}
184
185WELS_THREAD_ERROR_CODE WelsThreadJoin (WELS_THREAD_HANDLE thread) {
186 WaitForSingleObject (thread, INFINITE);
187 CloseHandle (thread);
188
189 return WELS_THREAD_ERROR_OK;
190}
191
192
193WELS_THREAD_HANDLE WelsThreadSelf() {
194 return GetCurrentThread();
195}
196
197WELS_THREAD_ERROR_CODE WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* pInfo) {
198 SYSTEM_INFO si;
199
200 GetSystemInfo (&si);
201
202 pInfo->ProcessorCount = si.dwNumberOfProcessors;
203
204 return WELS_THREAD_ERROR_OK;
205}
206
207#else
208
209void WelsSleep (uint32_t dwMilliseconds) {
210 usleep (dwMilliseconds * 1000); // microseconds
211}
212
213WELS_THREAD_ERROR_CODE WelsThreadCreate (WELS_THREAD_HANDLE* thread, LPWELS_THREAD_ROUTINE routine,
214 void* arg, WELS_THREAD_ATTR attr) {
215 WELS_THREAD_ERROR_CODE err = 0;
216
217 pthread_attr_t at;
218 err = pthread_attr_init (&at);
219 if (err)
220 return err;
221#ifndef __ANDROID__
222 err = pthread_attr_setscope (&at, PTHREAD_SCOPE_SYSTEM);
223 if (err)
224 return err;
225 err = pthread_attr_setschedpolicy (&at, SCHED_FIFO);
226 if (err)
227 return err;
228#endif
229 err = pthread_create (thread, &at, routine, arg);
230
231 pthread_attr_destroy (&at);
232
233 return err;
234}
235
236WELS_THREAD_ERROR_CODE WelsThreadJoin (WELS_THREAD_HANDLE thread) {
237 return pthread_join (thread, NULL);
238}
239
240WELS_THREAD_HANDLE WelsThreadSelf() {
241 return pthread_self();
242}
243
244// unnamed semaphores aren't supported on OS X
245
246WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {
247#ifdef __APPLE__
248 if (p_event == NULL || event_name == NULL)
249 return WELS_THREAD_ERROR_GENERAL;
250 *p_event = sem_open (event_name, O_CREAT, (S_IRUSR | S_IWUSR)/*0600*/, 0);
251 if (*p_event == (sem_t*)SEM_FAILED) {
252 sem_unlink (event_name);
253 *p_event = NULL;
254 return WELS_THREAD_ERROR_GENERAL;
255 } else {
256 return WELS_THREAD_ERROR_OK;
257 }
258#else
259 WELS_EVENT event = (WELS_EVENT) malloc(sizeof(*event));
260 if (event == NULL)
261 return WELS_THREAD_ERROR_GENERAL;
262 WELS_THREAD_ERROR_CODE err = sem_init(event, 0, 0);
263 if (!err) {
264 *p_event = event;
265 return err;
266 }
267 free(event);
268 return err;
269#endif
270}
271WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
272#ifdef __APPLE__
273 WELS_THREAD_ERROR_CODE err = sem_close (*event); // match with sem_open
274 if (event_name)
275 sem_unlink (event_name);
276 return err;
277#else
278 WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init
279 free(*event);
280 return err;
281#endif
282}
283
284WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {
285 WELS_THREAD_ERROR_CODE err = 0;
286// int32_t val = 0;
287// sem_getvalue(event, &val);
288// fprintf( stderr, "before signal it, val= %d..\n",val );
289 err = sem_post (*event);
290// sem_getvalue(event, &val);
291// fprintf( stderr, "after signal it, val= %d..\n",val );
292 return err;
293}
294
295WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
296 return sem_wait (*event); // blocking until signaled
297}
298
299WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
300 if (dwMilliseconds != (uint32_t) - 1) {
301 return sem_wait (*event);
302 } else {
303#if defined(__APPLE__)
304 int32_t err = 0;
305 int32_t wait_count = 0;
306 do {
307 err = sem_trywait (*event);
308 if (WELS_THREAD_ERROR_OK == err)
309 break;// WELS_THREAD_ERROR_OK;
310 else if (wait_count > 0)
311 break;
312 usleep (dwMilliseconds * 1000);
313 ++ wait_count;
314 } while (1);
315 return err;
316#else
317 struct timespec ts;
318 struct timeval tv;
319
320 gettimeofday (&tv, 0);
321
322 ts.tv_nsec = tv.tv_usec * 1000 + dwMilliseconds * 1000000;
323 ts.tv_sec = tv.tv_sec + ts.tv_nsec / 1000000000;
324 ts.tv_nsec %= 1000000000;
325
326 return sem_timedwait (*event, &ts);
327#endif//__APPLE__
328 }
329}
330
331WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
332 WELS_EVENT* event_list, WELS_EVENT* master_event) {
333 uint32_t nIdx = 0;
334 uint32_t uiAccessTime = 2; // 2 us once
335
336 if (nCount == 0)
337 return WELS_THREAD_ERROR_WAIT_FAILED;
338
339 if (master_event != NULL) {
340 // This design relies on the events actually being semaphores;
341 // if multiple events in the list have been signalled, the master
342 // event should have a similar count (events in windows can't keep
343 // track of the actual count, but the master event isn't needed there
344 // since it uses WaitForMultipleObjects).
345 int32_t err = sem_wait (*master_event);
346 if (err != WELS_THREAD_ERROR_OK)
347 return err;
348 uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
349 }
350
351 while (1) {
352 nIdx = 0; // access each event by order
353 while (nIdx < nCount) {
354 int32_t err = 0;
355 int32_t wait_count = 0;
356
357 /*
358 * although such interface is not used in __GNUC__ like platform, to use
359 * pthread_cond_timedwait() might be better choice if need
360 */
361 do {
362 err = sem_trywait (event_list[nIdx]);
363 if (WELS_THREAD_ERROR_OK == err)
364 return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
365 else if (wait_count > 0 || uiAccessTime == 0)
366 break;
367 usleep (uiAccessTime);
368 ++ wait_count;
369 } while (1);
370 // we do need access next event next time
371 ++ nIdx;
372 }
373 usleep (1); // switch to working threads
374 if (master_event != NULL) {
375 // A master event was used and was signalled, but none of the events in the
376 // list was found to be signalled, thus wait a little more when rechecking
377 // the list to avoid busylooping here.
378 // If we ever hit this codepath it's mostly a bug in the code that signals
379 // the events.
380 uiAccessTime = 2;
381 }
382 }
383
384 return WELS_THREAD_ERROR_WAIT_FAILED;
385}
386
387WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
388 WELS_EVENT* event_list, WELS_EVENT* master_event) {
389 uint32_t nIdx = 0;
390 uint32_t uiCountSignals = 0;
391 uint32_t uiSignalFlag = 0; // UGLY: suppose maximal event number up to 32
392
393 if (nCount == 0 || nCount > (sizeof (uint32_t) << 3))
394 return WELS_THREAD_ERROR_WAIT_FAILED;
395
396 while (1) {
397 nIdx = 0; // access each event by order
398 while (nIdx < nCount) {
399 const uint32_t kuiBitwiseFlag = (1 << nIdx);
400
401 if ((uiSignalFlag & kuiBitwiseFlag) != kuiBitwiseFlag) { // non-blocking mode
402 int32_t err = 0;
403// fprintf( stderr, "sem_wait(): start to wait event %d..\n", nIdx );
404 if (master_event == NULL) {
405 err = sem_wait (event_list[nIdx]);
406 } else {
407 err = sem_wait (*master_event);
408 if (err == WELS_THREAD_ERROR_OK) {
409 err = sem_wait (event_list[nIdx]);
410 if (err != WELS_THREAD_ERROR_OK) {
411 // We successfully waited for the master event,
412 // but waiting for the individual event failed (e.g. EINTR?).
413 // Increase the master event count so that the next retry will
414 // work as intended.
415 sem_post (*master_event);
416 }
417 }
418 }
419// fprintf( stderr, "sem_wait(): wait event %d result %d errno %d..\n", nIdx, err, errno );
420 if (WELS_THREAD_ERROR_OK == err) {
421// int32_t val = 0;
422// sem_getvalue(&event_list[nIdx], &val);
423// fprintf( stderr, "after sem_timedwait(), event_list[%d] semaphore value= %d..\n", nIdx, val);
424
425 uiSignalFlag |= kuiBitwiseFlag;
426 ++ uiCountSignals;
427 if (uiCountSignals >= nCount) {
428 return WELS_THREAD_ERROR_OK;
429 }
430 }
431 }
432 // we do need access next event next time
433 ++ nIdx;
434 }
435 }
436
437 return WELS_THREAD_ERROR_WAIT_FAILED;
438}
439
440WELS_THREAD_ERROR_CODE WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* pInfo) {
441#ifdef ANDROID_NDK
442 pInfo->ProcessorCount = android_getCpuCount();
443 return WELS_THREAD_ERROR_OK;
444#elif defined(LINUX)
445
446 cpu_set_t cpuset;
447
448 CPU_ZERO (&cpuset);
449
450 if (!sched_getaffinity (0, sizeof (cpuset), &cpuset))
451 pInfo->ProcessorCount = CPU_COUNT (&cpuset);
452 else
453 pInfo->ProcessorCount = 1;
454
455 return WELS_THREAD_ERROR_OK;
456
457#else
458
459 size_t len = sizeof (pInfo->ProcessorCount);
460
461 if (sysctlbyname (HW_NCPU_NAME, &pInfo->ProcessorCount, &len, NULL, 0) == -1)
462 pInfo->ProcessorCount = 1;
463
464 return WELS_THREAD_ERROR_OK;
465
466#endif//LINUX
467}
468
469#endif
470
471
472#endif // MT_ENABLED
473

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t