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+
75+WELS_THREAD_ERROR_CODE WelsMutexInit (WELS_MUTEX* mutex) {
76+ InitializeCriticalSection (mutex);
77+
78+ return WELS_THREAD_ERROR_OK;
79+}
80+
81+WELS_THREAD_ERROR_CODE WelsMutexLock (WELS_MUTEX* mutex) {
82+ EnterCriticalSection (mutex);
83+
84+ return WELS_THREAD_ERROR_OK;
85+}
86+
87+WELS_THREAD_ERROR_CODE WelsMutexUnlock (WELS_MUTEX* mutex) {
88+ LeaveCriticalSection (mutex);
89+
90+ return WELS_THREAD_ERROR_OK;
91+}
92+
93+WELS_THREAD_ERROR_CODE WelsMutexDestroy (WELS_MUTEX* mutex) {
94+ DeleteCriticalSection (mutex);
95+
96+ return WELS_THREAD_ERROR_OK;
97+}
98+
99+#else /* _WIN32 */
100+
101+WELS_THREAD_ERROR_CODE WelsMutexInit (WELS_MUTEX* mutex) {
102+ return pthread_mutex_init (mutex, NULL);
103+}
104+
105+WELS_THREAD_ERROR_CODE WelsMutexLock (WELS_MUTEX* mutex) {
106+ return pthread_mutex_lock (mutex);
107+}
108+
109+WELS_THREAD_ERROR_CODE WelsMutexUnlock (WELS_MUTEX* mutex) {
110+ return pthread_mutex_unlock (mutex);
111+}
112+
113+WELS_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+
124+void WelsSleep (uint32_t dwMilliseconds) {
125+ Sleep (dwMilliseconds);
126+}
127+
128+WELS_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+
138+WELS_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+
145+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
146+ return WaitForSingleObject (*event, INFINITE);
147+}
148+
149+WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
150+ return WaitForSingleObject (*event, dwMilliseconds);
151+}
152+
153+WELS_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+
159+WELS_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+
165+WELS_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+
173+WELS_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+
185+WELS_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+
193+WELS_THREAD_HANDLE WelsThreadSelf() {
194+ return GetCurrentThread();
195+}
196+
197+WELS_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+
209+void WelsSleep (uint32_t dwMilliseconds) {
210+ usleep (dwMilliseconds * 1000); // microseconds
211+}
212+
213+WELS_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+
236+WELS_THREAD_ERROR_CODE WelsThreadJoin (WELS_THREAD_HANDLE thread) {
237+ return pthread_join (thread, NULL);
238+}
239+
240+WELS_THREAD_HANDLE WelsThreadSelf() {
241+ return pthread_self();
242+}
243+
244+// unnamed semaphores aren't supported on OS X
245+
246+WELS_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+}
271+WELS_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+
284+WELS_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+
295+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
296+ return sem_wait (*event); // blocking until signaled
297+}
298+
299+WELS_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+
331+WELS_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+
387+WELS_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+
440+WELS_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