1 /* *****************************************************************************
2 * Copyright (c) 2007-2014 Alexis Naveros.
4 * Ecere Corporation has unlimited/unrestricted rights.
5 * *****************************************************************************/
9 * Threading interface, POSIX implementation.
14 #if defined(COMPILE_FOR_VSL)
22 #include "mmthreadqt.h"
24 #elif defined(MT_DISABLED)
30 typedef struct mtNull mtMutex;
31 typedef struct mtNull mtSpin;
32 typedef struct mtNull mtSignal;
34 #define mtMutexInit(a)
35 #define mtMutexDestroy(a)
36 #define mtMutexLock(a)
37 #define mtMutexUnlock(a)
38 #define mtMutexTryLock(a)
41 #define mtSpinDestroy(a)
43 #define mtSpinUnlock(a)
44 #define mtSpinTryLock(a)
46 #define mtSignalInit(a)
47 #define mtSignalDestroy(a)
48 #define mtSignalDispatch(a)
49 #define mtSignalBroadcast(a)
50 #define mtSignalMutexWait(a,b)
59 #if _POSIX_SPIN_LOCKS > 0
60 #define MT_SPIN_LOCK_SUPPORT
63 #define MT_BARRIER_SUPPORT
64 #define MT_RWLOCK_SUPPORT
68 static inline void mtYield()
75 typedef struct mtThread mtThread;
83 #define MT_THREAD_FLAGS_JOINABLE (0x1)
84 #define MT_THREAD_FLAGS_SETSTACK (0x2)
87 static inline void mtThreadCreate( mtThread *thread, void *(*threadmain)( void *value ), void *value, int flags, void *stack, size_t stacksize )
91 pthread_attr_init( &attr );
92 #if !MM_WIN32 && !MM_WIN64
93 if( flags & MT_THREAD_FLAGS_SETSTACK )
94 pthread_attr_setstack( &attr, stack, stacksize );
96 if( flags & MT_THREAD_FLAGS_JOINABLE )
97 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
99 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
100 pthread_create( &thread->pthread, &attr, threadmain, value );
101 pthread_attr_destroy( &attr );
106 static inline void mtThreadExit()
112 static inline void mtThreadJoin( mtThread *thread )
115 pthread_join( thread->pthread, &ret );
120 static inline mtThread mtThreadSelf()
123 thread.pthread = pthread_self();
127 static inline int mtThreadCmpEqual( mtThread *thread0, mtThread *thread1 )
129 return ( pthread_equal( thread0->pthread, thread1->pthread ) != 0 ? 1 : 0 );
133 static inline size_t mtGetMinimumStackSize()
135 #ifdef PTHREAD_STACK_MIN
136 return PTHREAD_STACK_MIN;
138 return ( mmcontext.pagesize ? 4*mmcontext.pagesize : 16384 );
145 #ifndef DEBUG_WARNING()
146 #define DEBUG_WARNING() ({printf( "\nRF WARNING : %s %s %d\n", __FILE__, __FUNCTION__, __LINE__ ); fflush( stdout );})
152 typedef struct mtMutex mtMutex;
157 unsigned char *function;
161 pthread_mutex_t pmutex;
164 static inline void mtMutexInit( mtMutex *mutex )
166 pthread_mutex_init( &mutex->pmutex, 0 );
170 static inline void mtMutexDestroy( mtMutex *mutex )
172 pthread_mutex_destroy( &mutex->pmutex );
178 #define mtMutexLock(a) mtMutexLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
179 #define mtMutexUnlock(a) mtMutexUnlockDebug(a,__FUNCTION__,__FILE__,__LINE__)
180 #define mtMutexTryLock(a) mtMutexTryLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
182 static inline void mtMutexLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
184 printf( "Mutex lock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
186 if( pthread_mutex_trylock( &mutex->pmutex ) )
188 printf( " Mutex %p locked by %s() in %s:%d\n", mutex, mutex->function, mutex->file, mutex->line );
190 if( pthread_mutex_lock( &mutex->pmutex ) )
193 mutex->function = (unsigned char *)function;
194 mutex->file = (unsigned char *)file;
199 static inline void mtMutexUnlockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
201 mutex->function = (unsigned char *)function;
202 mutex->file = (unsigned char *)file;
204 printf( "Mutex Unlock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
206 if( pthread_mutex_unlock( &mutex->pmutex ) )
211 static inline int mtMutexTryLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
213 printf( "Mutex Trylock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
215 if( !( pthread_mutex_trylock( &mutex->pmutex ) ) )
217 mutex->function = (unsigned char *)function;
218 mutex->file = (unsigned char *)file;
228 static inline void mtMutexLock( mtMutex *mutex )
230 pthread_mutex_lock( &mutex->pmutex );
234 static inline void mtMutexUnlock( mtMutex *mutex )
236 pthread_mutex_unlock( &mutex->pmutex );
240 static inline int mtMutexTryLock( mtMutex *mutex )
242 return !( pthread_mutex_trylock( &mutex->pmutex ) );
253 typedef struct mtSignal mtSignal;
257 pthread_cond_t pcond;
260 static inline void mtSignalInit( mtSignal *signal )
262 pthread_cond_init( &signal->pcond, 0 );
266 static inline void mtSignalDestroy( mtSignal *signal )
268 pthread_cond_destroy( &signal->pcond );
272 static inline void mtSignalWake( mtSignal *signal )
275 if( pthread_cond_signal( &signal->pcond ) )
278 pthread_cond_signal( &signal->pcond );
283 static inline void mtSignalBroadcast( mtSignal *signal )
286 if( pthread_cond_broadcast( &signal->pcond ) )
289 pthread_cond_broadcast( &signal->pcond );
294 static inline void mtSignalWait( mtSignal *signal, mtMutex *mutex )
297 if( pthread_cond_wait( &signal->pcond, &mutex->pmutex ) )
300 pthread_cond_wait( &signal->pcond, &mutex->pmutex );
305 static inline void mtSignalWaitTimeout( mtSignal *signal, mtMutex *mutex, long milliseconds )
310 gettimeofday( &tp, NULL );
311 ts.tv_sec = tp.tv_sec + ( milliseconds / 1000 );
312 microsecs = tp.tv_usec + ( ( milliseconds % 1000 ) * 1000 );
313 if( microsecs >= 1000000 )
316 microsecs -= 1000000;
318 ts.tv_nsec = (int)(microsecs * 1000);
319 pthread_cond_timedwait( &signal->pcond, &mutex->pmutex, &ts );
324 #define MT_MUTEX_INITIALIZER { 0, 0, 0, PTHREAD_MUTEX_INITIALIZER }
326 #define MT_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
335 #ifdef MM_ATOMIC_SUPPORT
337 typedef struct mtSpin mtSpin;
341 mmAtomic32 atomicspin;
344 static inline void mtSpinInit( mtSpin *spin )
346 mmAtomicWrite32( &spin->atomicspin, 0x0 );
350 static inline void mtSpinDestroy( mtSpin *spin )
355 static inline void mtSpinLock( mtSpin *spin )
357 mmAtomicSpin32( &spin->atomicspin, 0x0, 0x1 );
361 static inline void mtSpinUnlock( mtSpin *spin )
363 mmAtomicWrite32( &spin->atomicspin, 0x0 );
367 static inline int mtSpinTryLock( mtSpin *spin )
369 return mmAtomicCmpReplace32( &spin->atomicspin, 0x0, 0x1 );
372 #elif _POSIX_SPIN_LOCKS > 0
374 typedef struct mtSpin mtSpin;
379 unsigned char *function;
383 pthread_spinlock_t pspinlock;
386 static inline void mtSpinInit( mtSpin *spin )
388 pthread_spin_init( &spin->pspinlock, PTHREAD_PROCESS_PRIVATE );
392 static inline void mtSpinDestroy( mtSpin *spin )
394 pthread_spin_destroy( &spin->pspinlock );
398 static inline void mtSpinLock( mtSpin *spin )
401 if( pthread_spin_lock( &spin->pspinlock ) )
404 pthread_spin_lock( &spin->pspinlock );
409 static inline void mtSpinUnlock( mtSpin *spin )
412 if( pthread_spin_unlock( &spin->pspinlock ) )
415 pthread_spin_unlock( &spin->pspinlock );
420 static inline int mtSpinTryLock( mtSpin *spin )
422 return !( pthread_spin_trylock( &spin->pspinlock ) );
427 typedef struct mtMutex mtSpin;
429 #define mtSpinInit(a) mtMutexInit(a)
430 #define mtSpinDestroy(a) mtMutexDestroy(a)
431 #define mtSpinLock(a) mtMutexLock(a)
432 #define mtSpinUnlock(a) mtMutexUnlock(a)
433 #define mtSpinTryLock(a) mtMutexTryLock(a)
443 #ifdef MT_BARRIER_SUPPORT
447 pthread_barrier_t pbarrier;
450 static inline void mtBarrierInit( mtBarrier *barrier, int count )
452 pthread_barrier_init( &barrier->pbarrier, 0, count );
456 static inline void mtBarrierDestroy( mtBarrier *barrier )
458 pthread_barrier_destroy( &barrier->pbarrier );
462 static inline int mtBarrierWait( mtBarrier *barrier )
464 return pthread_barrier_wait( &barrier->pbarrier );
475 #ifdef MT_RWLOCK_SUPPORT
477 typedef struct mtRWlock mtRWlock;
481 pthread_rwlock_t prwlock;
485 static inline void mtRWlockInit( mtRWlock *rwlock )
487 pthread_rwlock_init( &rwlock->prwlock, 0 );
491 static inline void mtRWlockDestroy( mtRWlock *rwlock )
493 pthread_rwlock_destroy( &rwlock->prwlock );
497 static inline void mtRWlockRead( mtRWlock *rwlock )
499 pthread_rwlock_rdlock( &rwlock->prwlock );
503 static inline void mtRWlockWrite( mtRWlock *rwlock )
505 pthread_rwlock_wrlock( &rwlock->prwlock );
509 static inline void mtRWlockUnlock( mtRWlock *rwlock )
511 pthread_rwlock_unlock( &rwlock->prwlock );
515 static inline int mtRWlockTryRead( mtRWlock *rwlock )
517 return pthread_rwlock_rdlock( &rwlock->prwlock );
520 static inline int mtRWlockTryWrite( mtRWlock *rwlock )
522 return pthread_rwlock_wrlock( &rwlock->prwlock );