1 /*
2 * Copyright (C) 1999-2005 Chris Ross
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * o Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * o Neither the name of the ferite software nor the names of its contributors may
14 * be used to endorse or promote products derived from this software without
15 * specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #ifndef WIN32
36 # include <unistd.h>
37 #endif
38 #include <string.h>
39
40 #ifndef APHEX_AS_COMPONENT
41 #include "../../../config.h"
42 #endif
43
44 #include "aphex.h"
45
46 /***************************************************
47 * THREAD
48 ***************************************************/
aphex_thread_create()49 AphexThread *aphex_thread_create()
50 {
51 AphexThread *thread = malloc(sizeof(AphexThread));
52 return thread;
53 }
54
aphex_thread_destroy(AphexThread * thread)55 void aphex_thread_destroy( AphexThread *thread )
56 {
57 if( thread != NULL )
58 {
59 if( thread->running )
60 aphex_thread_stop( thread );
61 free( thread );
62 }
63 }
64
aphex_thread_start(AphexThread * thread,void * (* start_routine)(void *),void * arg,int detach)65 int aphex_thread_start( AphexThread *thread, void *(*start_routine)(void *), void *arg, int detach )
66 {
67 int retval = 0;
68
69 if( thread != NULL && start_routine != NULL )
70 {
71 #ifdef USE_PTHREAD
72 thread->running = 1;
73 retval = pthread_create( &(thread->thread), NULL, start_routine, arg );
74 if( detach )
75 pthread_detach( thread->thread );
76 #endif
77 if( retval != 0 )
78 {
79 printf( "aphex: ERROR: Not enough system resources to create thread\n" );
80 return -1;
81 }
82 }
83 return 0;
84 }
85
aphex_thread_stop(AphexThread * thread)86 void aphex_thread_stop( AphexThread *thread )
87 {
88 if( thread != NULL )
89 {
90 thread->running = 0;
91 #ifdef USE_PTHREAD
92 pthread_cancel( thread->thread );
93 #endif
94 }
95 }
96
97 #if defined(WIN32)
usleep(int useconds)98 void usleep( int useconds )
99 {
100 if (useconds > 500)
101 sleep ((useconds+500)/1000);
102 else if (useconds > 0)
103 sleep (1);
104 else
105 sleep (0);
106 }
107 #endif
108
aphex_thread_sleep(AphexThread * thread,int msecs)109 void aphex_thread_sleep( AphexThread *thread, int msecs )
110 {
111 usleep( msecs * 1000 );
112 }
113
aphex_thread_join(AphexThread * thread)114 void aphex_thread_join( AphexThread *thread )
115 {
116 if( thread != NULL )
117 {
118 #ifdef USE_PTHREAD
119 pthread_join( thread->thread, NULL );
120 #endif
121 thread->running = 0;
122 }
123 }
124
aphex_thread_exit(AphexThread * thread,void * rval)125 void aphex_thread_exit( AphexThread *thread, void *rval )
126 {
127 if( thread != NULL )
128 {
129 #ifdef USE_PTHREAD
130 pthread_exit( rval );
131 #endif
132 thread->running = 0;
133 }
134 }
135
136 /***************************************************
137 * MUTEX
138 ***************************************************/
aphex_mutex_create()139 AphexMutex *aphex_mutex_create()
140 {
141 AphexMutex *mutex = malloc(sizeof(AphexMutex));
142 #ifdef USE_PTHREAD
143 pthread_mutex_init( &(mutex->mutex), NULL );
144 # if defined(USING_FAKE_RECURSIVE_MUTEX)
145 mutex->count = -1;
146 memset( &(mutex->owner), '\0', sizeof(pthread_t) );
147 # endif
148 #endif
149 mutex->recursive = 0;
150 return mutex;
151 }
152
aphex_mutex_recursive_create()153 AphexMutex *aphex_mutex_recursive_create()
154 {
155 AphexMutex *mutex = malloc(sizeof(AphexMutex));
156
157 #ifdef USE_PTHREAD
158 #if defined(USING_FAKE_RECURSIVE_MUTEX)
159 mutex->count = 0;
160 mutex->is_owned = 0;
161 pthread_cond_init( &mutex->cond, NULL );
162 pthread_mutex_init( &mutex->mutex, NULL );
163 #else
164 pthread_mutexattr_init( &mutex->attr );
165 pthread_mutexattr_settype( &mutex->attr, PTHREAD_MUTEX_RECURSIVE);
166 pthread_mutex_init( &mutex->mutex, &mutex->attr );
167 pthread_mutexattr_destroy( &mutex->attr );
168 #endif
169 mutex->recursive = 1;
170 #endif
171
172 return mutex;
173 }
174
aphex_mutex_destroy(AphexMutex * mutex)175 void aphex_mutex_destroy( AphexMutex *mutex )
176 {
177 if( mutex != NULL )
178 {
179 #ifdef USE_PTHREAD
180 #if defined(USING_FAKE_RECURSIVE_MUTEX)
181 pthread_cond_destroy( &mutex->cond );
182 #else
183 #endif
184 pthread_mutex_destroy( &mutex->mutex );
185 free( mutex );
186 #endif
187 }
188 }
189
aphex_mutex_lock(AphexMutex * mutex)190 int aphex_mutex_lock( AphexMutex *mutex )
191 {
192 #ifdef USE_PTHREAD
193 pthread_t self = pthread_self();
194
195 if( mutex != NULL )
196 {
197 if( pthread_mutex_lock( &mutex->mutex ) == -1 )
198 return -1;
199
200 #if defined(USING_FAKE_RECURSIVE_MUTEX)
201 if( mutex->recursive == 1 )
202 {
203 while (1)
204 {
205 if( pthread_equal(mutex->owner, self) )
206 {
207 mutex->count++;
208 break;
209 }
210 else if( mutex->is_owned == 0 )
211 {
212 mutex->owner = self;
213 mutex->count = 1;
214 mutex->is_owned = 1;
215 break;
216 }
217 else
218 {
219 if( pthread_cond_wait( &mutex->cond, &mutex->mutex ) == -1 )
220 return -1;
221 }
222 }
223 pthread_mutex_unlock( &mutex->mutex );
224 }
225 #endif
226 }
227 #endif
228 return 0;
229 }
230
aphex_mutex_unlock(AphexMutex * mutex)231 int aphex_mutex_unlock( AphexMutex *mutex )
232 {
233 if( mutex != NULL )
234 {
235 #ifdef USE_PTHREAD
236 #if defined(USING_FAKE_RECURSIVE_MUTEX)
237 if( mutex->recursive == 1 )
238 {
239 if( pthread_mutex_lock (&mutex->mutex) == -1 )
240 return -1;
241
242 mutex->count--;
243 if( mutex->count == 0 )
244 {
245 mutex->is_owned = 0;
246 pthread_cond_signal( &mutex->cond );
247 }
248 }
249 #endif
250 pthread_mutex_unlock( &mutex->mutex );
251 #endif
252 }
253 return 0;
254 }
255
256 /***************************************************
257 * EVENT
258 ***************************************************/
aphex_event_create()259 AphexEvent *aphex_event_create()
260 {
261 AphexEvent *event = malloc(sizeof(AphexEvent));
262 #ifdef USE_PTHREAD
263 if(pthread_cond_init( &(event->cond), NULL) != 0){
264 free(event);
265 return NULL;
266 }
267 if(pthread_mutex_init( &(event->mutex), NULL ) != 0){
268 free(event);
269 return NULL;
270 }
271 #endif
272 return event;
273 }
274
aphex_event_destroy(AphexEvent * event)275 void aphex_event_destroy( AphexEvent *event )
276 {
277 if( event != NULL )
278 {
279 #ifdef USE_PTHREAD
280 pthread_cond_destroy( &event->cond );
281 pthread_mutex_destroy( &event->mutex );
282 #endif
283 free(event);
284 }
285 }
286
aphex_event_signal(AphexEvent * event)287 int aphex_event_signal( AphexEvent *event )
288 {
289 #ifdef USE_PTHREAD
290 pthread_cond_signal(&(event->cond));
291 #endif
292 return 0;
293 }
294
aphex_event_wait(AphexEvent * event)295 int aphex_event_wait( AphexEvent *event )
296 {
297 #ifdef USE_PTHREAD
298 pthread_cond_wait(&(event->cond), &(event->mutex));
299 #endif
300 return 0;
301 }
302
303 #if defined(WIN32)
304
305 #include <windows.h>
306 #include <time.h>
307
308 #ifndef __GNUC__
309 #define EPOCHFILETIME (116444736000000000i64)
310 #else
311 #define EPOCHFILETIME (116444736000000000LL)
312 #endif
313
314 struct timezone {
315 int tz_minuteswest; /* minutes W of Greenwich */
316 int tz_dsttime; /* type of dst correction */
317 };
318
gettimeofday(struct timeval * tv,struct timezone * tz)319 __inline int gettimeofday(struct timeval *tv, struct timezone *tz)
320 {
321 FILETIME ft;
322 LARGE_INTEGER li;
323 __int64 t;
324 static int tzflag;
325
326 if (tv)
327 {
328 GetSystemTimeAsFileTime(&ft);
329 li.LowPart = ft.dwLowDateTime;
330 li.HighPart = ft.dwHighDateTime;
331 t = li.QuadPart; /* In 100-nanosecond intervals */
332 t -= EPOCHFILETIME; /* Offset to the Epoch time */
333 t /= 10; /* In microseconds */
334 tv->tv_sec = (long)(t / 1000000);
335 tv->tv_usec = (long)(t % 1000000);
336 }
337
338 if (tz)
339 {
340 if (!tzflag)
341 {
342 _tzset();
343 tzflag++;
344 }
345 tz->tz_minuteswest = _timezone / 60;
346 tz->tz_dsttime = _daylight;
347 }
348
349 return 0;
350 }
351
352 #endif
353
aphex_event_timedwait(AphexEvent * event,int seconds)354 int aphex_event_timedwait( AphexEvent *event , int seconds)
355 {
356 int t_ret = 0;
357
358 #ifdef USE_PTHREAD
359 struct timespec ts;
360 struct timeval tp;
361
362 gettimeofday(&tp, NULL);
363 ts.tv_sec = tp.tv_sec;
364 ts.tv_nsec = tp.tv_usec * 1000;
365 ts.tv_sec += seconds;
366
367 t_ret = pthread_cond_timedwait(&(event->cond), &(event->mutex), &ts);
368 #endif
369
370 if (t_ret != 0)
371 return 1;
372 else
373 return 0;
374 }
375