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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3765 - (hide 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 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 3765 * Copyright (C) 2005 - 2020 Christian Schoenebeck *
7 schoenebeck 53 * *
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 persson 830 #ifdef HAVE_CONFIG_H
25     # include <config.h>
26     #endif
27    
28 persson 3455 #if defined(__APPLE__)
29 schoenebeck 3054 # include <sys/cdefs.h> // defines the system macros checked below
30     #endif
31    
32 schoenebeck 289 #ifndef _GNU_SOURCE
33     # define _GNU_SOURCE 1 /* so _XOPEN_SOURCE will be defined by features.h */
34     #endif
35    
36 persson 830 #ifdef HAVE_FEATURES_H
37 wylder 819 # include <features.h>
38     #endif
39 schoenebeck 289
40 senoner 1481 #if !defined(WIN32)
41 schoenebeck 3054 # if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 500
42     # undef _XOPEN_SOURCE
43 schoenebeck 3290 # define _XOPEN_SOURCE 500 /* to define PTHREAD_MUTEX_RECURSIVE */
44     # if (!defined(POSIX_C_SOURCE) || POSIX_C_SOURCE < 199801L) && !__DARWIN_UNIX03
45 schoenebeck 3054 # 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 schoenebeck 289 #endif
51    
52 schoenebeck 53 #include <iostream>
53 capela 268 #include <errno.h>
54 schoenebeck 281 #include <stdlib.h> /* for exit(int) */
55 capela 268
56 schoenebeck 53 #include "Mutex.h"
57    
58 schoenebeck 3765 #if DEBUG_MUTEX
59     # include "Thread.h"
60     # include <assert.h>
61     # include "global_private.h"
62     #endif
63    
64 schoenebeck 880 namespace LinuxSampler {
65    
66 schoenebeck 3290 Mutex::Mutex(type_t type) {
67 senoner 1481 #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 persson 932 pthread_mutexattr_init(&__posix_mutexattr);
75 schoenebeck 3290 // 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 schoenebeck 53 exit(-1);
92 schoenebeck 3290 break;
93 schoenebeck 53 }
94     pthread_mutex_init(&__posix_mutex, &__posix_mutexattr);
95 senoner 1481 #endif
96 schoenebeck 3765 #if DEBUG_MUTEX
97     debugSelf = false;
98     count = 0;
99     #endif
100 schoenebeck 53 }
101    
102     Mutex::~Mutex() {
103 senoner 1481 #if defined(WIN32)
104     CloseHandle(hMutex);
105     #else
106 schoenebeck 53 pthread_mutex_destroy(&__posix_mutex);
107 persson 932 pthread_mutexattr_destroy(&__posix_mutexattr);
108 senoner 1481 #endif
109 schoenebeck 53 }
110    
111     void Mutex::Lock() {
112 senoner 1481 #if defined(WIN32)
113     WaitForSingleObject(hMutex, INFINITE);
114     #else
115 schoenebeck 53 pthread_mutex_lock(&__posix_mutex);
116 senoner 1481 #endif
117 schoenebeck 3765 #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 schoenebeck 53 }
131    
132 senkov 165 bool Mutex::Trylock() {
133 senoner 1481 #if defined(WIN32)
134     if( WaitForSingleObject(hMutex, 0) == WAIT_TIMEOUT) return false;
135     #else
136 senkov 165 if (pthread_mutex_trylock(&__posix_mutex) == EBUSY)
137 senoner 1481 return false;
138 schoenebeck 3765 #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 senkov 165 return true;
153     }
154    
155 schoenebeck 53 void Mutex::Unlock() {
156 schoenebeck 3765 #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 senoner 1481 #if defined(WIN32)
168     ReleaseMutex(hMutex);
169     #else
170 schoenebeck 53 pthread_mutex_unlock(&__posix_mutex);
171 senoner 1481 #endif
172 schoenebeck 53 }
173 schoenebeck 880
174     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC