1 /*  Part of SWI-Prolog
2 
3     Author:        Jan Wielemaker
4     E-mail:        J.Wielemaker@vu.nl
5     WWW:           http://www.swi-prolog.org
6     Copyright (c)  2000-2020, University of Amsterdam
7 			      CWI, Amsterdam
8     All rights reserved.
9 
10     Redistribution and use in source and binary forms, with or without
11     modification, are permitted provided that the following conditions
12     are met:
13 
14     1. Redistributions of source code must retain the above copyright
15        notice, this list of conditions and the following disclaimer.
16 
17     2. Redistributions in binary form must reproduce the above copyright
18        notice, this list of conditions and the following disclaimer in
19        the documentation and/or other materials provided with the
20        distribution.
21 
22     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33     POSSIBILITY OF SUCH DAMAGE.
34 */
35 
36 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37 This  file  defines  just  the   mutexes    needed   by  the  SWI-Prolog
38 multi-threading support. It is in a separate file because it needs to be
39 included before SWI-Stream.h, which in turn  needs to be included early.
40 The remainder of the thread support must be at the end to exploit access
41 to the other Prolog data-types.
42 
43 To allow for multiple thread-implementations, we  do not use plain POSIX
44 mutex-primitives in the remainder of  the   code.  Instead,  mutexes are
45 controlled using the following macros:
46 
47 	type simpleMutex	Non-recursive mutex
48 	type recursiveMutex	Recursive mutex
49 
50 	simpleMutexInit(p)	Initialise a simple mutex
51 	simpleMutexDelete(p)	Delete a simple mutex
52 	simpleMutexLock(p)	Lock a simple mutex
53 	simpleMutexTryLock(p)	Try Lock a simple mutex
54 	simpleMutexUnlock(p)	unlock a simple mutex
55 
56 	recursiveMutexInit(p)	Initialise a recursive mutex
57 	recursiveMutexDelete(p)	Delete a recursive mutex
58 	recursiveMutexLock(p)	Lock a recursive mutex
59 	recursiveMutexTryLock(p) Try Lock a recursive mutex
60 	recursiveMutexUnlock(p)	unlock a recursive mutex
61 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
62 
63 #ifndef PL_MUTEX_H_DEFINED
64 #define PL_MUTEX_H_DEFINED
65 
66 #ifdef O_PLMT
67 
68 #if defined(__WINDOWS__)
69 #define USE_CRITICAL_SECTIONS 1
70 #endif
71 
72 #include <pthread.h>
73 
74 #ifdef USE_CRITICAL_SECTIONS
75 #ifndef WINDOWS_LEAN_AND_MEAN
76 #define WINDOWS_LEAN_AND_MEAN
77 #endif
78 #include <winsock2.h>
79 
80 #include <windows.h>
81 #define RECURSIVE_MUTEXES 1
82 
83 #define simpleMutex CRITICAL_SECTION
84 
85 #define simpleMutexInit(p)	InitializeCriticalSection(p)
86 #define simpleMutexDelete(p)	DeleteCriticalSection(p)
87 #define simpleMutexLock(p)	EnterCriticalSection(p)
88 #if _WIN32_WINNT >= 0x0400
89 #define simpleMutexTryLock(p)	TryEnterCriticalSection(p)
90 #endif
91 #define simpleMutexUnlock(p)	LeaveCriticalSection(p)
92 
93 #else /* USE_CRITICAL_SECTIONS */
94 
95 typedef pthread_mutex_t simpleMutex;
96 
97 #define simpleMutexInit(p)	pthread_mutex_init(p, NULL)
98 #define simpleMutexDelete(p)	pthread_mutex_destroy(p)
99 #define simpleMutexLock(p)	pthread_mutex_lock(p)
100 #define simpleMutexTryLock(p)	(pthread_mutex_trylock(p) == 0)
101 #define simpleMutexUnlock(p)	pthread_mutex_unlock(p)
102 
103 #endif /*USE_CRITICAL_SECTIONS*/
104 
105 #ifdef RECURSIVE_MUTEXES
106 typedef pthread_mutex_t recursiveMutex;
107 
108 #define NEED_RECURSIVE_MUTEX_INIT 1
109 extern int recursiveMutexInit(recursiveMutex *m);
110 #define recursiveMutexDelete(p)	 pthread_mutex_destroy(p)
111 #define recursiveMutexLock(p)	 pthread_mutex_lock(p)
112 #define recursiveMutexTryLock(p) pthread_mutex_trylock(p)
113 #define recursiveMutexUnlock(p)	 pthread_mutex_unlock(p)
114 
115 #else /*RECURSIVE_MUTEXES*/
116 
117 typedef struct {
118   pthread_mutex_t lock;
119 	pthread_t owner;
120      unsigned int count;
121 } recursiveMutex;
122 
123 #define NEED_RECURSIVE_MUTEX_INIT 1
124 #define NEED_RECURSIVE_MUTEX_DELETE 1
125 extern int recursiveMutexInit(recursiveMutex *m);
126 extern int recursiveMutexDelete(recursiveMutex *m);
127 extern int recursiveMutexLock(recursiveMutex *m);
128 extern int recursiveMutexTryLock(recursiveMutex *m);
129 extern int recursiveMutexUnlock(recursiveMutex *m);
130 
131 #endif /*RECURSIVE_MUTEXES*/
132 
133 #ifdef simpleMutexTryLock
134 #define O_CONTENTION_STATISTICS 1
135 #ifndef USE_CRITICAL_SECTIONS
136 #include <errno.h>
137 #endif
138 #endif
139 
140 typedef struct counting_mutex
141 { simpleMutex mutex;			/* mutex itself */
142   const char  *name;			/* name of the mutex */
143   uint64_t     count;			/* # times locked */
144   unsigned int lock_count;		/* # times unlocked */
145 #ifdef O_CONTENTION_STATISTICS
146   unsigned int collisions;		/* # contentions */
147 #endif
148   struct counting_mutex *next;		/* next of allocated chain */
149   struct counting_mutex *prev;		/* prvious in allocated chain */
150 } counting_mutex;
151 
152 extern counting_mutex  *allocSimpleMutex(const char *name);
153 extern void		initSimpleMutex(counting_mutex *m, const char *name);
154 extern void		freeSimpleMutex(counting_mutex *m);
155 
156 #else /*O_PLMT*/
157 
158 #define simpleMutexLock(p)	(void)0
159 #define simpleMutexUnlock(p)	(void)0
160 
161 #endif /*O_PLMT*/
162 
163 #endif /*PL_MUTEX_H_DEFINED*/
164