1 /*!
2 * \copy
3 * Copyright (c) 2009-2019, 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 wels_decoder_thread.cpp
33 *
34 * \brief Interfaces introduced in thread programming
35 *
36 * \date 08/06/2018 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) && !defined(__CYGWIN__)
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <unistd.h>
51 #ifndef __Fuchsia__
52 #include <sys/sysctl.h>
53 #endif
54 #ifdef __APPLE__
55 #define HW_NCPU_NAME "hw.logicalcpu"
56 #else
57 #define HW_NCPU_NAME "hw.ncpu"
58 #endif
59 #endif
60
61 #include "wels_decoder_thread.h"
62 #include <stdio.h>
63 #include <stdlib.h>
64
GetCPUCount()65 int32_t GetCPUCount() {
66 WelsLogicalProcessInfo pInfo;
67 pInfo.ProcessorCount = 1;
68 WelsQueryLogicalProcessInfo (&pInfo);
69 return pInfo.ProcessorCount;
70 }
71
ThreadCreate(SWelsDecThread * t,LPWELS_THREAD_ROUTINE tf,void * ta)72 int ThreadCreate (SWelsDecThread* t, LPWELS_THREAD_ROUTINE tf, void* ta) {
73 WELS_THREAD_ATTR attr = 0;
74 return WelsThreadCreate (& (t->h), tf, ta, attr);
75 }
76
ThreadWait(SWelsDecThread * t)77 int ThreadWait (SWelsDecThread* t) {
78 return WelsThreadJoin (t->h);
79 }
80
81 #if defined(_WIN32) || defined(__CYGWIN__)
82
EventCreate(SWelsDecEvent * e,int manualReset,int initialState)83 int EventCreate (SWelsDecEvent* e, int manualReset, int initialState) {
84 e->h = CreateEvent (NULL, manualReset, initialState, NULL);
85 e->isSignaled = initialState;
86 return (e->h != NULL) ? 0 : 1;
87 }
88
EventReset(SWelsDecEvent * e)89 void EventReset (SWelsDecEvent* e) {
90 ResetEvent (e->h);
91 e->isSignaled = 0;
92 }
93
EventPost(SWelsDecEvent * e)94 void EventPost (SWelsDecEvent* e) {
95 SetEvent (e->h);
96 e->isSignaled = 1;
97 }
98
EventWait(SWelsDecEvent * e,int32_t timeout)99 int EventWait (SWelsDecEvent* e, int32_t timeout) {
100 DWORD result;
101 if ((uint32_t)timeout == WELS_DEC_THREAD_WAIT_INFINITE || timeout < 0)
102 result = WaitForSingleObject (e->h, INFINITE);
103 else
104 result = WaitForSingleObject (e->h, timeout);
105
106 if (result == WAIT_OBJECT_0)
107 return WELS_DEC_THREAD_WAIT_SIGNALED;
108 else
109 return WAIT_TIMEOUT;
110 }
111
EventDestroy(SWelsDecEvent * e)112 void EventDestroy (SWelsDecEvent* e) {
113 CloseHandle (e->h);
114 e->h = NULL;
115 }
116
SemCreate(SWelsDecSemphore * s,long value,long max)117 int SemCreate (SWelsDecSemphore* s, long value, long max) {
118 s->h = CreateSemaphore (NULL, value, max, NULL);
119 return (s->h != NULL) ? 0 : 1;
120 }
121
SemWait(SWelsDecSemphore * s,int32_t timeout)122 int SemWait (SWelsDecSemphore* s, int32_t timeout) {
123 DWORD result;
124 if ((uint32_t)timeout == WELS_DEC_THREAD_WAIT_INFINITE || timeout < 0)
125 result = WaitForSingleObject (s->h, INFINITE);
126 else
127 result = WaitForSingleObject (s->h, timeout);
128
129 if (result == WAIT_OBJECT_0) {
130 return WELS_DEC_THREAD_WAIT_SIGNALED;
131 } else {
132 return WELS_DEC_THREAD_WAIT_TIMEDOUT;
133 }
134 }
135
SemRelease(SWelsDecSemphore * s,long * prevcount)136 void SemRelease (SWelsDecSemphore* s, long* prevcount) {
137 ReleaseSemaphore (s->h, 1, prevcount);
138 }
139
SemDestroy(SWelsDecSemphore * s)140 void SemDestroy (SWelsDecSemphore* s) {
141 CloseHandle (s->h);
142 s->h = NULL;
143 }
144
145 #else /* _WIN32 */
146
getTimespecFromTimeout(struct timespec * ts,int32_t timeout)147 static void getTimespecFromTimeout (struct timespec* ts, int32_t timeout) {
148 struct timeval tv;
149 gettimeofday (&tv, 0);
150 ts->tv_nsec = tv.tv_usec * 1000 + timeout * 1000000;
151 ts->tv_sec = tv.tv_sec + ts->tv_nsec / 1000000000;
152 ts->tv_nsec %= 1000000000;
153 }
EventCreate(SWelsDecEvent * e,int manualReset,int initialState)154 int EventCreate (SWelsDecEvent* e, int manualReset, int initialState) {
155 if (pthread_mutex_init (& (e->m), NULL))
156 return 1;
157 if (pthread_cond_init (& (e->c), NULL))
158 return 2;
159
160 e->isSignaled = initialState;
161 e->manualReset = manualReset;
162
163 return 0;
164 }
165
EventReset(SWelsDecEvent * e)166 void EventReset (SWelsDecEvent* e) {
167 pthread_mutex_lock (& (e->m));
168 e->isSignaled = 0;
169 pthread_mutex_unlock (& (e->m));
170 }
171
EventPost(SWelsDecEvent * e)172 void EventPost (SWelsDecEvent* e) {
173 pthread_mutex_lock (& (e->m));
174 pthread_cond_broadcast (& (e->c));
175 e->isSignaled = 1;
176 pthread_mutex_unlock (& (e->m));
177 }
178
EventWait(SWelsDecEvent * e,int32_t timeout)179 int EventWait (SWelsDecEvent* e, int32_t timeout) {
180 pthread_mutex_lock (& (e->m));
181 int signaled = e->isSignaled;
182 if (timeout == 0) {
183 pthread_mutex_unlock (& (e->m));
184 if (signaled)
185 return WELS_DEC_THREAD_WAIT_SIGNALED;
186 else
187 return WELS_DEC_THREAD_WAIT_TIMEDOUT;
188 }
189 if (signaled) {
190 if (!e->manualReset) {
191 e->isSignaled = 0;
192 }
193 pthread_mutex_unlock (& (e->m));
194 return WELS_DEC_THREAD_WAIT_SIGNALED;
195 }
196 int rc = 0;
197 if (timeout == WELS_DEC_THREAD_WAIT_INFINITE || timeout < 0) {
198 rc = pthread_cond_wait (& (e->c), & (e->m));
199 } else {
200 struct timespec ts;
201 getTimespecFromTimeout (&ts, timeout);
202 rc = pthread_cond_timedwait (& (e->c), & (e->m), &ts);
203 }
204 if (!e->manualReset) {
205 e->isSignaled = 0;
206 }
207 pthread_mutex_unlock (& (e->m));
208 if (rc == 0)
209 return WELS_DEC_THREAD_WAIT_SIGNALED;
210 else
211 return WELS_DEC_THREAD_WAIT_TIMEDOUT;
212 }
213
EventDestroy(SWelsDecEvent * e)214 void EventDestroy (SWelsDecEvent* e) {
215 pthread_mutex_destroy (& (e->m));
216 pthread_cond_destroy (& (e->c));
217 }
218
SemCreate(SWelsDecSemphore * s,long value,long max)219 int SemCreate (SWelsDecSemphore* s, long value, long max) {
220 s->v = value;
221 s->max = max;
222 if (pthread_mutex_init (& (s->m), NULL))
223 return 1;
224 const char* event_name = "";
225 if (WelsEventOpen (& (s->e), event_name)) {
226 return 2;
227 }
228 return 0;
229 }
230
SemWait(SWelsDecSemphore * s,int32_t timeout)231 int SemWait (SWelsDecSemphore* s, int32_t timeout) {
232 #if defined(__APPLE__)
233 pthread_mutex_lock (& (s->m));
234 #endif
235 int rc = 0;
236 if (timeout != 0) {
237 while ((s->v) == 0) {
238 if (timeout == WELS_DEC_THREAD_WAIT_INFINITE || timeout < 0) {
239 // infinite wait until released
240 #if defined(__APPLE__)
241 rc = pthread_cond_wait (& (s->e), & (s->m));
242 #else
243 rc = sem_wait (s->e);
244 if (rc != 0) rc = errno;
245 #endif
246 } else {
247 struct timespec ts;
248 getTimespecFromTimeout (&ts, timeout);
249 #if defined(__APPLE__)
250 rc = pthread_cond_timedwait (& (s->e), & (s->m), &ts);
251 #else
252 rc = sem_timedwait (s->e, &ts);
253 if (rc != 0) rc = errno;
254 #endif
255 if (rc != EINTR) {
256 // if timed out we return to the caller
257 break;
258 }
259 }
260 }
261 // only decrement counter if semaphore was signaled
262 if (rc == 0)
263 s->v -= 1;
264
265 } else {
266 // Special handling for timeout of 0
267 if (s->v > 0) {
268 s->v -= 1;
269 rc = 0;
270 } else {
271 rc = 1;
272 }
273 }
274 #if defined(__APPLE__)
275 pthread_mutex_unlock (& (s->m));
276 #endif
277 // set return value
278 if (rc == 0)
279 return WELS_DEC_THREAD_WAIT_SIGNALED;
280 else
281 return WELS_DEC_THREAD_WAIT_TIMEDOUT;
282 }
283
SemRelease(SWelsDecSemphore * s,long * o_pPrevCount)284 void SemRelease (SWelsDecSemphore* s, long* o_pPrevCount) {
285 long prevcount;
286 #ifdef __APPLE__
287 pthread_mutex_lock (& (s->m));
288 prevcount = s->v;
289 if (s->v < s->max)
290 s->v += 1;
291 pthread_cond_signal (& (s->e));
292 pthread_mutex_unlock (& (s->m));
293 #else
294 prevcount = s->v;
295 if (s->v < s->max)
296 s->v += 1;
297 sem_post (s->e);
298 #endif
299 if (o_pPrevCount != NULL) {
300 *o_pPrevCount = prevcount;
301 }
302 }
303
SemDestroy(SWelsDecSemphore * s)304 void SemDestroy (SWelsDecSemphore* s) {
305 pthread_mutex_destroy (& (s->m));
306 const char* event_name = "";
307 WelsEventClose (& (s->e), event_name);
308 }
309
310 #endif /* !_WIN32 */
311
312