/[svn]/linuxsampler/trunk/src/common/Mutex.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/Mutex.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3765 - (show annotations) (download)
Mon Apr 6 09:46:52 2020 UTC (4 years ago) by schoenebeck
File size: 5628 byte(s)
Mutex class: Implemented bug detection and deadlock debugging features.

* Bug detection: By enabling macro DEBUG_MUTEX at compile time and
  calling new method setDebugEnabled(true) at runtime, automatic bug
  detection features are activated which e.g. raise an assertion fault
  if a thread attempts to Unlock() a thread it does not own a lock on,
  or when locking more than once while not using mutex type RECURSIVE
  and much more.

* Deadlock debugging: Also if these features were activated like
  described above, the most recent mutex lock is recorded by capturing
  the name of the thread and the precise call stack which caused the
  mutex lock. This information can be used to identify the exact
  situation that lead to a dead lock efficiently with a debugger.

* Bumped version (2.1.1.svn53).

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 # define _XOPEN_SOURCE 500 /* to define PTHREAD_MUTEX_RECURSIVE */
44 # if (!defined(POSIX_C_SOURCE) || POSIX_C_SOURCE < 199801L) && !__DARWIN_UNIX03
45 # warning "Seems you don't have a UNIX98 compatible system."
46 # warning "Please run LinuxSampler's selftest to make sure this won't be a problem!"
47 # warning "(compile tests with 'make tests', run them with 'src/testcases/linuxsamplertest')"
48 # endif
49 # endif
50 #endif
51
52 #include <iostream>
53 #include <errno.h>
54 #include <stdlib.h> /* for exit(int) */
55
56 #include "Mutex.h"
57
58 #if DEBUG_MUTEX
59 # include "Thread.h"
60 # include <assert.h>
61 # include "global_private.h"
62 #endif
63
64 namespace LinuxSampler {
65
66 Mutex::Mutex(type_t type) {
67 #if defined(WIN32)
68 hMutex = CreateMutex( NULL, FALSE, NULL);
69 if (hMutex == NULL) {
70 std::cerr << "Mutex Constructor: Fatal error - CreateMutex error " << GetLastError() << "\n";
71 exit(1);
72 }
73 #else
74 pthread_mutexattr_init(&__posix_mutexattr);
75 // pthread_mutexattr_settype() only works on UNIX98 compatible systems
76 switch (type) {
77 case RECURSIVE:
78 if (pthread_mutexattr_settype(&__posix_mutexattr, PTHREAD_MUTEX_RECURSIVE)) {
79 std::cerr << "Mutex Constructor: Fatal error - unable to pthread_mutexattr_settype(PTHREAD_MUTEX_RECURSIVE)\n" << std::flush;
80 exit(-1);
81 }
82 break;
83 case NON_RECURSIVE:
84 if (pthread_mutexattr_settype(&__posix_mutexattr, PTHREAD_MUTEX_ERRORCHECK)) {
85 std::cerr << "Mutex Constructor: Fatal error - unable to pthread_mutexattr_settype(PTHREAD_MUTEX_ERRORCHECK)\n" << std::flush;
86 exit(-1);
87 }
88 break;
89 default:
90 std::cerr << "Mutex Constructor: Fatal error - Unknown mutex type requested\n" << std::flush;
91 exit(-1);
92 break;
93 }
94 pthread_mutex_init(&__posix_mutex, &__posix_mutexattr);
95 #endif
96 #if DEBUG_MUTEX
97 debugSelf = false;
98 count = 0;
99 #endif
100 }
101
102 Mutex::~Mutex() {
103 #if defined(WIN32)
104 CloseHandle(hMutex);
105 #else
106 pthread_mutex_destroy(&__posix_mutex);
107 pthread_mutexattr_destroy(&__posix_mutexattr);
108 #endif
109 }
110
111 void Mutex::Lock() {
112 #if defined(WIN32)
113 WaitForSingleObject(hMutex, INFINITE);
114 #else
115 pthread_mutex_lock(&__posix_mutex);
116 #endif
117 #if DEBUG_MUTEX
118 if (debugSelf) {
119 std::string caller = Thread::nameOfCaller();
120 ++count;
121 assert(count > 0);
122 if (type != RECURSIVE)
123 assert(count == 1);
124 if (!owner.empty())
125 assert(owner == caller);
126 owner = caller;
127 backtrace = backtraceAsString();
128 }
129 #endif
130 }
131
132 bool Mutex::Trylock() {
133 #if defined(WIN32)
134 if( WaitForSingleObject(hMutex, 0) == WAIT_TIMEOUT) return false;
135 #else
136 if (pthread_mutex_trylock(&__posix_mutex) == EBUSY)
137 return false;
138 #endif
139 #if DEBUG_MUTEX
140 if (debugSelf) {
141 std::string caller = Thread::nameOfCaller();
142 ++count;
143 assert(count > 0);
144 if (type != RECURSIVE)
145 assert(count == 1);
146 if (!owner.empty())
147 assert(owner == caller);
148 owner = caller;
149 backtrace = backtraceAsString();
150 }
151 #endif
152 return true;
153 }
154
155 void Mutex::Unlock() {
156 #if DEBUG_MUTEX
157 if (debugSelf) {
158 std::string caller = Thread::nameOfCaller();
159 assert(count > 0);
160 --count;
161 assert(count >= 0);
162 assert(owner == caller);
163 if (!count)
164 owner.clear();
165 }
166 #endif
167 #if defined(WIN32)
168 ReleaseMutex(hMutex);
169 #else
170 pthread_mutex_unlock(&__posix_mutex);
171 #endif
172 }
173
174 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC