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