• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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