root/trunk/libffado/src/libutil/PosixMutex.cpp

Revision 1336, 6.3 kB (checked in by ppalmers, 16 years ago)

Bring trunk up to date with branches/libffado-2.0:

"""
svn merge -r 1254:1299 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1301:1320 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1322:1323 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1329:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
"""

Add getSupportedSamplingFrequencies() to DICE, RME and Metric Halo AvDevices?

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "PosixMutex.h"
25 #include <errno.h>
26
27 // disable collision tracing for non-debug builds
28 #ifndef DEBUG
29     #undef DEBUG_LOCK_COLLISION_TRACING
30     #define DEBUG_LOCK_COLLISION_TRACING 0
31 #endif
32
33 // check whether backtracing is enabled
34 #if DEBUG_LOCK_COLLISION_TRACING
35     #define DEBUG_LOCK_COLLISION_TRACING_INDEX 2
36     #define DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN 64
37     #if DEBUG_BACKTRACE_SUPPORT
38     // ok
39     #else
40         #error cannot enable lock tracing without backtrace support
41     #endif
42 #endif
43
44 namespace Util
45 {
46
47 IMPL_DEBUG_MODULE( PosixMutex, PosixMutex, DEBUG_LEVEL_NORMAL );
48
49 PosixMutex::PosixMutex()
50 {
51     m_id = "?";
52     pthread_mutexattr_t attr;
53     pthread_mutexattr_init(&attr);
54     #ifdef DEBUG
55         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
56     #else
57         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
58     #endif
59     pthread_mutex_init(&m_mutex, &attr);
60     pthread_mutexattr_destroy(&attr);
61
62     #if DEBUG_LOCK_COLLISION_TRACING
63     m_locked_by = NULL;
64     #endif
65 }
66
67 PosixMutex::PosixMutex(std::string id)
68 {
69     m_id = id;
70     pthread_mutexattr_t attr;
71     pthread_mutexattr_init(&attr);
72     #ifdef DEBUG
73         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
74     #else
75         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
76     #endif
77     pthread_mutex_init(&m_mutex, &attr);
78     pthread_mutexattr_destroy(&attr);
79
80     #if DEBUG_LOCK_COLLISION_TRACING
81     m_locked_by = NULL;
82     #endif
83 }
84
85 PosixMutex::~PosixMutex()
86 {
87     pthread_mutex_destroy(&m_mutex);
88 }
89
90 void
91 PosixMutex::Lock()
92 {
93     int err;
94     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) lock\n", m_id.c_str(), this);
95     #if DEBUG_LOCK_COLLISION_TRACING
96     if(TryLock()) {
97         // locking succeeded
98         m_locked_by = debugBacktraceGet( DEBUG_LOCK_COLLISION_TRACING_INDEX );
99
100         char name[ DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN ];
101         name[0] = 0;
102         debugGetFunctionNameFromAddr(m_locked_by, name, DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN);
103
104         debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
105                     "(%s, %p) %s obtained lock\n",
106                     m_id.c_str(), this, name);
107         return;
108     } else {
109         void *lock_try_by = debugBacktraceGet( DEBUG_LOCK_COLLISION_TRACING_INDEX );
110
111         char name1[ DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN ];
112         name1[0] = 0;
113         debugGetFunctionNameFromAddr(lock_try_by, name1, DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN);
114         char name2[ DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN ];
115         name2[0] = 0;
116         debugGetFunctionNameFromAddr(m_locked_by, name2, DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN);
117
118         debugWarning("(%s, %p) lock collision: %s wants lock, %s has lock\n",
119                     m_id.c_str(), this, name1, name2);
120         if((err = pthread_mutex_lock(&m_mutex))) {
121             if (err == EDEADLK) {
122                 debugError("(%s, %p) Resource deadlock detected\n", m_id.c_str(), this);
123                 debugPrintBacktrace(10);
124             } else {
125                 debugError("(%s, %p) Error locking the mutex: %d\n", m_id.c_str(), this, err);
126             }
127         } else {
128             debugWarning("(%s, %p) lock collision: %s got lock (from %s?)\n",
129                         m_id.c_str(), this, name1, name2);
130         }
131     }
132     #else
133     #ifdef DEBUG
134     if((err = pthread_mutex_lock(&m_mutex))) {
135         if (err == EDEADLK) {
136             debugError("(%s, %p) Resource deadlock detected\n", m_id.c_str(), this);
137             debugPrintBacktrace(10);
138         } else {
139             debugError("(%s, %p) Error locking the mutex: %d\n", m_id.c_str(), this, err);
140         }
141     }
142     #else
143     pthread_mutex_lock(&m_mutex);
144     #endif
145     #endif
146 }
147
148 bool
149 PosixMutex::TryLock()
150 {
151     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) trying to lock\n", m_id.c_str(), this);
152     return pthread_mutex_trylock(&m_mutex) == 0;
153 }
154
155 bool
156 PosixMutex::isLocked()
157 {
158     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) checking lock\n", m_id.c_str(), this);
159     int res = pthread_mutex_trylock(&m_mutex);
160     if(res == 0) {
161         pthread_mutex_unlock(&m_mutex);
162         return false;
163     } else {
164         if (res == EDEADLK) {
165             // this means that the current thread already has the lock,
166             // iow it's locked.
167             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) lock taken by current thread\n", m_id.c_str(), this);
168         } else if(res == EBUSY) {
169             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) lock taken\n", m_id.c_str(), this);
170         } else {
171             debugError("(%s, %p) Bogus error code: %d\n", m_id.c_str(), this, res);
172         }
173         return true;
174     }
175 }
176
177 void
178 PosixMutex::Unlock()
179 {
180     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "(%s, %p) unlock\n", m_id.c_str(), this);
181     #if DEBUG_LOCK_COLLISION_TRACING
182     // unlocking
183     m_locked_by = NULL;
184     void *unlocker = debugBacktraceGet( DEBUG_LOCK_COLLISION_TRACING_INDEX );
185     char name[ DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN ];
186     name[0] = 0;
187     debugGetFunctionNameFromAddr(unlocker, name, DEBUG_LOCK_COLLISION_TRACING_NAME_MAXLEN);
188     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
189                 "(%s, %p)  %s releases lock\n",
190                 m_id.c_str(), this, name);
191     #endif
192
193     #ifdef DEBUG
194     int err;
195     if((err = pthread_mutex_unlock(&m_mutex))) {
196         debugError("(%s, %p) Error unlocking the mutex: %d\n", m_id.c_str(), this, err);
197     }
198     #else
199     pthread_mutex_unlock(&m_mutex);
200     #endif
201 }
202
203 void
204 PosixMutex::show()
205 {
206     debugOutput(DEBUG_LEVEL_NORMAL, "(%s, %p) mutex (%s)\n", m_id.c_str(), this, (isLocked() ? "Locked" : "Unlocked"));
207 }
208
209
210 } // end of namespace
Note: See TracBrowser for help on using the browser.