#ifndef PL_THREAD_H #define PL_THREAD_H 1 #if defined(THREADS) && !defined(O_PLMT) #define O_PLMT 1 #endif #if defined(O_PLMT) // && defined(PL_KERNEL) /* Support PL_LOCK in the interface */ #if THREADS #include typedef pthread_mutex_t simpleMutex; #define simpleMutexInit(p) pthread_mutex_init(p, NULL) #define simpleMutexDelete(p) pthread_mutex_destroy(p) #define simpleMutexLock(p) pthread_mutex_lock(p) #define simpleMutexUnlock(p) pthread_mutex_unlock(p) typedef pthread_mutex_t recursiveMutex; #define NEED_RECURSIVE_MUTEX_INIT 1 extern int recursiveMutexInit(recursiveMutex *m); #define recursiveMutexDelete(p) pthread_mutex_destroy(p) #define recursiveMutexLock(p) pthread_mutex_lock(p) #define recursiveMutexTryLock(p) pthread_mutex_trylock(p) #define recursiveMutexUnlock(p) pthread_mutex_unlock(p) #define IF_MT(id, g) if ( id == L_THREAD || GD->thread.enabled ) g typedef struct counting_mutex { simpleMutex mutex; /* mutex itself */ const char *name; /* name of the mutex */ long count; /* # times locked */ long unlocked; /* # times unlocked */ #ifdef O_CONTENTION_STATISTICS long collisions; /* # contentions */ #endif struct counting_mutex *next; /* next of allocated chain */ } counting_mutex; extern counting_mutex *allocSimpleMutex(const char *name); extern void freeSimpleMutex(counting_mutex *m); extern counting_mutex _PL_mutexes[]; /* Prolog mutexes */ #define L_MISC 0 #define L_ALLOC 1 #define L_ATOM 2 #define L_FLAG 3 #define L_FUNCTOR 4 #define L_RECORD 5 #define L_THREAD 6 #define L_PREDICATE 7 #define L_MODULE 8 #define L_TABLE 9 #define L_BREAK 10 #define L_FILE 11 #define L_SEETELL 12 #define L_PLFLAG 13 #define L_OP 14 #define L_INIT 15 #define L_TERM 16 #define L_GC 17 #define L_AGC 18 #define L_STOPTHEWORLD 19 #define L_FOREIGN 20 #define L_OS 21 #ifdef __WINDOWS__ #define L_DDE 22 #define L_CSTACK 23 #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The IF_MT(id, g) macro is used to bypass mutexes if threading is disabled. We cannot do this for the L_THREAD mutex however as we need to control when threads can be created. We assume id == L_THREAD is optimized away if id is known at compile-time - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define IF_MT(id, g) if ( id == L_THREAD || GD->thread.enabled ) g #ifdef O_CONTENTION_STATISTICS #define countingMutexLock(cm) \ do \ { if ( pthread_mutex_trylock(&(cm)->mutex) == EBUSY ) \ { (cm)->collisions++; \ pthread_mutex_lock(&(cm)->mutex); \ } \ (cm)->count++; \ } while(0) #else #define countingMutexLock(cm) \ do \ { simpleMutexLock(&(cm)->mutex); \ (cm)->count++; \ } while(0) #endif #define countingMutexUnlock(cm) \ do \ { (cm)->unlocked++; \ assert((cm)->unlocked <= (cm)->count); \ simpleMutexUnlock(&(cm)->mutex); \ } while(0) //#define O_DEBUG_MT #ifdef O_DEBUG_MT #define PL_LOCK(id) \ do { Sdprintf("[%d] %s:%d: LOCK(%s)\n", \ pthread_self(), \ __BASE_FILE__, __LINE__, #id); \ countingMutexLock(&_PL_mutexes[id]); \ } while(0) #define PL_UNLOCK(id) \ do { Sdprintf("[%d] %s:%d: UNLOCK(%s)\n", \ pthread_self(), \ __BASE_FILE__, __LINE__, #id); \ countingMutexUnlock(&_PL_mutexes[id]); \ } while(0) #else #define PL_LOCK(id) IF_MT(id, countingMutexLock(&_PL_mutexes[id])) #define PL_UNLOCK(id) IF_MT(id, countingMutexUnlock(&_PL_mutexes[id])) #endif #undef O_DEBUG_MT #define IOLOCK recursiveMutex #endif #else #define PL_LOCK(X) #define PL_UNLOCK(X) typedef void * IOLOCK; #endif #endif