1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2020 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #if defined(__APPLE__)
29 # include <sys/cdefs.h> // defines the system macros checked below
30 #endif
31
32 #ifndef _GNU_SOURCE
33 # define _GNU_SOURCE 1 /* so _XOPEN_SOURCE will be defined by features.h */
34 #endif
35
36 #ifdef HAVE_FEATURES_H
37 # include <features.h>
38 #endif
39
40 #if !defined(WIN32)
41 # if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 500
42 # undef _XOPEN_SOURCE
43 # if (!defined(POSIX_C_SOURCE) || POSIX_C_SOURCE < 199801L) && !__DARWIN_UNIX03
44 # warning "Seems you don't have a UNIX98 compatible system."
45 # warning "Please run LinuxSampler's selftest to make sure this won't be a problem!"
46 # warning "(compile tests with 'make tests', run them with 'src/testcases/linuxsamplertest')"
47 # endif
48 # endif
49 #endif
50
51 #include <iostream>
52 #include <errno.h>
53 #include <stdlib.h> /* for exit(int) */
54
55 #include "Mutex.h"
56
57 #if DEBUG_MUTEX
58 # include "Thread.h"
59 # include <assert.h>
60 # include "global_private.h"
61 #endif
62
63 namespace LinuxSampler {
64
Mutex(type_t type)65 Mutex::Mutex(type_t type) {
66 #if defined(WIN32)
67 hMutex = CreateMutex( NULL, FALSE, NULL);
68 if (hMutex == NULL) {
69 std::cerr << "Mutex Constructor: Fatal error - CreateMutex error " << GetLastError() << "\n";
70 exit(1);
71 }
72 #else
73 pthread_mutexattr_init(&__posix_mutexattr);
74 // pthread_mutexattr_settype() only works on UNIX98 compatible systems
75 switch (type) {
76 case RECURSIVE:
77 if (pthread_mutexattr_settype(&__posix_mutexattr, PTHREAD_MUTEX_RECURSIVE)) {
78 std::cerr << "Mutex Constructor: Fatal error - unable to pthread_mutexattr_settype(PTHREAD_MUTEX_RECURSIVE)\n" << std::flush;
79 exit(-1);
80 }
81 break;
82 case NON_RECURSIVE:
83 if (pthread_mutexattr_settype(&__posix_mutexattr, PTHREAD_MUTEX_ERRORCHECK)) {
84 std::cerr << "Mutex Constructor: Fatal error - unable to pthread_mutexattr_settype(PTHREAD_MUTEX_ERRORCHECK)\n" << std::flush;
85 exit(-1);
86 }
87 break;
88 default:
89 std::cerr << "Mutex Constructor: Fatal error - Unknown mutex type requested\n" << std::flush;
90 exit(-1);
91 break;
92 }
93 pthread_mutex_init(&__posix_mutex, &__posix_mutexattr);
94 #endif
95 #if DEBUG_MUTEX
96 debugSelf = false;
97 count = 0;
98 #endif
99 }
100
~Mutex()101 Mutex::~Mutex() {
102 #if defined(WIN32)
103 CloseHandle(hMutex);
104 #else
105 pthread_mutex_destroy(&__posix_mutex);
106 pthread_mutexattr_destroy(&__posix_mutexattr);
107 #endif
108 }
109
Lock()110 void Mutex::Lock() {
111 #if defined(WIN32)
112 WaitForSingleObject(hMutex, INFINITE);
113 #else
114 pthread_mutex_lock(&__posix_mutex);
115 #endif
116 #if DEBUG_MUTEX
117 if (debugSelf) {
118 std::string caller = Thread::nameOfCaller();
119 ++count;
120 assert(count > 0);
121 if (type != RECURSIVE)
122 assert(count == 1);
123 if (!owner.empty())
124 assert(owner == caller);
125 owner = caller;
126 backtrace = backtraceAsString();
127 }
128 #endif
129 }
130
Trylock()131 bool Mutex::Trylock() {
132 #if defined(WIN32)
133 if( WaitForSingleObject(hMutex, 0) == WAIT_TIMEOUT) return false;
134 #else
135 if (pthread_mutex_trylock(&__posix_mutex) == EBUSY)
136 return false;
137 #endif
138 #if DEBUG_MUTEX
139 if (debugSelf) {
140 std::string caller = Thread::nameOfCaller();
141 ++count;
142 assert(count > 0);
143 if (type != RECURSIVE)
144 assert(count == 1);
145 if (!owner.empty())
146 assert(owner == caller);
147 owner = caller;
148 backtrace = backtraceAsString();
149 }
150 #endif
151 return true;
152 }
153
Unlock()154 void Mutex::Unlock() {
155 #if DEBUG_MUTEX
156 if (debugSelf) {
157 std::string caller = Thread::nameOfCaller();
158 assert(count > 0);
159 --count;
160 assert(count >= 0);
161 assert(owner == caller);
162 if (!count)
163 owner.clear();
164 }
165 #endif
166 #if defined(WIN32)
167 ReleaseMutex(hMutex);
168 #else
169 pthread_mutex_unlock(&__posix_mutex);
170 #endif
171 }
172
173 } // namespace LinuxSampler
174