157 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*  Part of SWI-Prolog
 | |
| 
 | |
|     Author:        Jan Wielemaker
 | |
|     E-mail:        J.Wielemaker@cs.vu.nl
 | |
|     WWW:           http://www.swi-prolog.org
 | |
|     Copyright (C): 1985-2012, University of Amsterdam
 | |
| 			      VU University Amsterdam
 | |
| 
 | |
|     This library is free software; you can redistribute it and/or
 | |
|     modify it under the terms of the GNU Lesser General Public
 | |
|     License as published by the Free Software Foundation; either
 | |
|     version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|     This library is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|     Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public
 | |
|     License along with this library; if not, write to the Free Software
 | |
|     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | |
| */
 | |
| 
 | |
| #ifndef PL_THREAD_H_DEFINED
 | |
| #define PL_THREAD_H_DEFINED
 | |
| 
 | |
| #ifdef THREADS
 | |
| #include <pthread.h>
 | |
| 
 | |
| 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)
 | |
| 
 | |
| 
 | |
| 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
 | |
| #define L_LOCALE       23
 | |
| #ifdef __WINDOWS__
 | |
| #define L_DDE	       24
 | |
| #define L_CSTACK       25
 | |
| #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) g
 | |
| //#define IF_MT(id, g) if ( id == L_THREAD  ) 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
 | |
| 
 | |
| #else
 | |
| #define PL_LOCK(X)
 | |
| #define PL_UNLOCK(X)
 | |
| 
 | |
| typedef void *		IOLOCK;
 | |
| #endif
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 |