1 // -*- Mode: C++; -*-
2 // Package : omniORB
3 // tracedthread.cc Created on: 15/6/99
4 // Author : David Riddoch (djr)
5 //
6 // Copyright (C) 2002-2010 Apasphere Ltd
7 // Copyright (C) 1996,1999 AT&T Research Cambridge
8 //
9 // This file is part of the omniORB library.
10 //
11 // The omniORB library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library. If not, see http://www.gnu.org/licenses/
23 //
24 //
25 // Description:
26 // omni_thread style mutex and condition variables with checks.
27 //
28
29 #include <omniORB4/CORBA.h>
30 #include <stdio.h>
31
32 #ifdef HAS_pch
33 #pragma hdrstop
34 #endif
35
36 #include <omniORB4/tracedthread.h>
37
38 OMNI_USING_NAMESPACE(omni)
39
40 //////////////////////////////////////////////////////////////////////
41 ////////////////////////// omni_tracedmutex //////////////////////////
42 //////////////////////////////////////////////////////////////////////
43
44 #define BOMB_OUT() throw *(int*)0
45
46 #ifdef OMNIORB_ENABLE_LOCK_TRACES
47
48 static const char* bug_msg =
49 " This is probably a bug in omniORB. Please submit a report\n"
50 " (with stack trace if possible) to <bugs@omniorb-support.com>.\n";
51
52
omni_tracedmutex(const char * name)53 omni_tracedmutex::omni_tracedmutex(const char* name)
54 : pd_cond(&pd_lock),
55 pd_holder(0),
56 pd_n_conds(0),
57 pd_deleted(0)
58 {
59 if (name) {
60 pd_logname = new char[strlen(name) + 30];
61 sprintf(pd_logname, "%s (%p)", name, (void*)this);
62 }
63 else {
64 pd_logname = new char[30];
65 sprintf(pd_logname, "(%p)", (void*)this);
66 }
67 if (omniORB::traceLocking) {
68 omniORB::logger log;
69 log << "- " << pd_logname << ": mutex constructed.\n";
70 }
71 }
72
73
~omni_tracedmutex()74 omni_tracedmutex::~omni_tracedmutex()
75 {
76 if (pd_deleted) {
77 if (omniORB::trace(1)) {
78 omniORB::logger log;
79 log << "Assertion failed -- mutex (" << (void*)this
80 << ") deleted more than once.\n"
81 << bug_msg;
82 }
83 BOMB_OUT();
84 }
85 if (omniORB::traceLocking) {
86 omniORB::logger log;
87 log << "- " << pd_logname << ": mutex deleted.\n";
88 }
89 if (pd_holder) {
90 if (omniORB::trace(1)) {
91 omniORB::logger log;
92 log << "Assertion failed -- mutex " << pd_logname
93 << " destroyed whilst held.\n"
94 << bug_msg;
95 }
96 BOMB_OUT();
97 }
98 if (pd_n_conds != 0) {
99 if (omniORB::trace(1)) {
100 omniORB::logger log;
101 log << "Assertion failed -- mutex " << pd_logname
102 << " destroyed whilst still being used "
103 << " by " << pd_n_conds << " condition variable(s).\n"
104 << bug_msg;
105 }
106 BOMB_OUT();
107 }
108 pd_deleted = 1;
109 delete [] pd_logname;
110 }
111
112
113 void
lock()114 omni_tracedmutex::lock()
115 {
116 if (pd_deleted) {
117 if (omniORB::trace(1)) {
118 omniORB::logger log;
119 log << "Assertion failed -- attempt to lock deleted mutex ("
120 << (void*)this << ").\n"
121 << bug_msg;
122 }
123 BOMB_OUT();
124 }
125
126 omni_thread* me = omni_thread::self();
127
128 omni_mutex_lock sync(pd_lock);
129
130 if (me && pd_holder == me) {
131 if (omniORB::trace(1)) {
132 omniORB::logger log;
133 log << "Assertion failed -- attempt to lock mutex " << pd_logname
134 << " when already held.\n"
135 << bug_msg;
136 }
137 BOMB_OUT();
138 }
139
140 if (pd_holder && omniORB::traceLocking) {
141 omniORB::logger log;
142 log << "- " << pd_logname << ": block in lock.\n";
143 }
144
145 while (pd_holder) pd_cond.wait();
146
147 if (omniORB::traceLocking) {
148 omniORB::logger log;
149 log << "- " << pd_logname << ": locked.\n";
150 }
151
152 pd_holder = me ? me : (omni_thread*) 1;
153 }
154
155
156 void
unlock()157 omni_tracedmutex::unlock()
158 {
159 if (pd_deleted) {
160 if (omniORB::trace(1)) {
161 omniORB::logger log;
162 log << "Assertion failed -- attempt to unlock deleted mutex ("
163 << (void*)this << ").\n"
164 << bug_msg;
165 }
166 BOMB_OUT();
167 }
168
169 omni_thread* me = omni_thread::self();
170
171 {
172 omni_mutex_lock sync(pd_lock);
173
174 if (!pd_holder ||
175 (me && pd_holder != me)) {
176
177 if (omniORB::trace(1)) {
178 omniORB::logger log;
179 log << "Assertion failed -- attempt to unlock mutex " << pd_logname
180 << " not held.\n"
181 << bug_msg;
182 }
183 BOMB_OUT();
184 }
185
186 pd_holder = 0;
187 }
188 if (omniORB::traceLocking) {
189 omniORB::logger log;
190 log << "- " << pd_logname << ": unlocked.\n";
191 }
192 pd_cond.signal();
193 }
194
195
196 void
assert_held(const char * file,int line,int yes)197 omni_tracedmutex::assert_held(const char* file, int line, int yes)
198 {
199 {
200 omni_mutex_lock sync(pd_lock);
201
202 omni_thread* me = omni_thread::self();
203
204 if (( yes && pd_holder == me) ||
205 (!yes && pd_holder != me) ||
206 (!me))
207
208 return;
209 }
210
211 if (omniORB::trace(1)) {
212 omniORB::logger log;
213 log << "Assertion failed -- mutex " << pd_logname
214 << (yes ? " is not held.\n" : " should not be held.\n")
215 << bug_msg
216 << " file: " << file << "\n"
217 << " line: " << line << "\n";
218 }
219 BOMB_OUT();
220 }
221
222
223 //////////////////////////////////////////////////////////////////////
224 //////////////////////// omni_tracedcondition ////////////////////////
225 //////////////////////////////////////////////////////////////////////
226
omni_tracedcondition(omni_tracedmutex * m,const char * name)227 omni_tracedcondition::omni_tracedcondition(omni_tracedmutex* m,
228 const char* name)
229 : pd_mutex(*m), pd_cond(&m->pd_lock), pd_n_waiters(0),
230 pd_deleted(0)
231 {
232 if (!m) {
233 if (omniORB::trace(1)) {
234 omniORB::logger log;
235 log << "Assertion failed -- omni_tracedcondition "
236 << (name ? name : "<unknown>")
237 << " initialised with a nil mutex argument.\n" << bug_msg;
238 }
239 BOMB_OUT();
240 }
241
242 if (name) {
243 pd_logname = new char[strlen(name) + 30];
244 sprintf(pd_logname, "%s (%p)", name, (void*)this);
245 }
246 else {
247 pd_logname = new char[30];
248 sprintf(pd_logname, "(%p)", (void*)this);
249 }
250
251 pd_mutex.pd_lock.lock();
252 pd_mutex.pd_n_conds++;
253 pd_mutex.pd_lock.unlock();
254
255 if (omniORB::traceLocking) {
256 omniORB::logger log;
257 log << "- " << pd_logname << ": condition constructed.\n";
258 }
259 }
260
261
~omni_tracedcondition()262 omni_tracedcondition::~omni_tracedcondition()
263 {
264 if (pd_deleted) {
265 if (omniORB::trace(1)) {
266 omniORB::logger log;
267 log << "Assertion failed -- condition (" << (void*)this
268 << ") deleted more than once.\n"
269 << bug_msg;
270 }
271 BOMB_OUT();
272 }
273 if (omniORB::traceLocking) {
274 omniORB::logger log;
275 log << "- " << pd_logname << ": condition deleted.\n";
276 }
277 if (pd_n_waiters) {
278 if (omniORB::trace(1)) {
279 omniORB::logger log;
280 log << "Warning: omni_tracedcondition " << pd_logname
281 << " was deleted, but there are still threads waiting on it.\n";
282 }
283 }
284 pd_mutex.pd_lock.lock();
285 pd_mutex.pd_n_conds--;
286 pd_mutex.pd_lock.unlock();
287 pd_deleted = 1;
288 delete [] pd_logname;
289 }
290
291
292 void
wait()293 omni_tracedcondition::wait()
294 {
295 if (pd_deleted) {
296 if (omniORB::trace(1)) {
297 omniORB::logger log;
298 log << "Assertion failed -- attempt to wait on deleted condition ("
299 << pd_logname << ").\n"
300 << bug_msg;
301 }
302 BOMB_OUT();
303 }
304
305 omni_thread* me = omni_thread::self();
306
307 if (omniORB::traceLocking) {
308 omniORB::logger log;
309 log << "- " << pd_logname << ": wait...\n";
310 }
311
312 omni_mutex_lock sync(pd_mutex.pd_lock);
313
314 if (me && pd_mutex.pd_holder != me) {
315 if (omniORB::trace(1)) {
316 omniORB::logger log;
317 log << "Assertion failed -- attempt to wait on condition variable "
318 << pd_logname
319 << " but the calling thread does not hold the associated mutex "
320 << pd_mutex.pd_logname << "\n"
321 << bug_msg;
322 }
323 BOMB_OUT();
324 }
325
326 pd_mutex.pd_holder = 0;
327 pd_mutex.pd_cond.signal();
328 pd_n_waiters++;
329 pd_cond.wait();
330 pd_n_waiters--;
331 while( pd_mutex.pd_holder ) pd_mutex.pd_cond.wait();
332 pd_mutex.pd_holder = me ? me : (omni_thread*) 1;
333
334 if (omniORB::traceLocking) {
335 omniORB::logger log;
336 log << "- " << pd_logname << ": wait completed.\n";
337 }
338 }
339
340
341 int
timedwait(unsigned long secs,unsigned long nanosecs)342 omni_tracedcondition::timedwait(unsigned long secs, unsigned long nanosecs)
343 {
344 if (pd_deleted) {
345 if (omniORB::trace(1)) {
346 omniORB::logger log;
347 log << "Assertion failed -- attempt to wait on deleted condition ("
348 << pd_logname << ").\n"
349 << bug_msg;
350 }
351 BOMB_OUT();
352 }
353
354 omni_thread* me = omni_thread::self();
355
356 if (omniORB::traceLocking) {
357 omniORB::logger log;
358 log << "- " << pd_logname << ": timedwait...\n";
359 }
360
361 omni_mutex_lock sync(pd_mutex.pd_lock);
362
363 if (me && pd_mutex.pd_holder != me) {
364 if (omniORB::trace(1)) {
365 omniORB::logger log;
366 log << "Assertion failed -- attempt to timedwait on condition variable "
367 << pd_logname
368 << " but the calling thread does not hold the associated mutex "
369 << pd_mutex.pd_logname << "\n"
370 << bug_msg;
371 }
372 BOMB_OUT();
373 }
374
375 pd_mutex.pd_holder = 0;
376 pd_mutex.pd_cond.signal();
377 pd_n_waiters++;
378 int ret = pd_cond.timedwait(secs, nanosecs);
379 pd_n_waiters--;
380 while( pd_mutex.pd_holder ) pd_mutex.pd_cond.wait();
381 pd_mutex.pd_holder = me ? me : (omni_thread*) 1;
382
383 if (omniORB::traceLocking) {
384 omniORB::logger log;
385 log << "- " << pd_logname << ": timedwait completed (" << ret << ")\n";
386 }
387 return ret;
388 }
389
390
391 void
signal()392 omni_tracedcondition::signal()
393 {
394 if (pd_deleted) {
395 if (omniORB::trace(1)) {
396 omniORB::logger log;
397 log << "Assertion failed -- attempt to signal on deleted condition ("
398 << (void*)this << ")\n"
399 << bug_msg;
400 }
401 BOMB_OUT();
402 }
403 if (omniORB::traceLocking) {
404 omniORB::logger log;
405 log << "- " << pd_logname << ": signal.\n";
406 }
407 pd_cond.signal();
408 }
409
410
411 void
broadcast()412 omni_tracedcondition::broadcast()
413 {
414 if (pd_deleted) {
415 if (omniORB::trace(1)) {
416 omniORB::logger log;
417 log << "Assertion failed -- attempt to broadcast on deleted condition ("
418 << (void*)this << ")\n"
419 << bug_msg;
420 }
421 BOMB_OUT();
422 }
423 if (omniORB::traceLocking) {
424 omniORB::logger log;
425 log << "- " << pd_logname << ": broadcast.\n";
426 }
427 pd_cond.broadcast();
428 }
429
430
431 #endif // ifdef OMNIORB_ENABLE_LOCK_TRACES
432
433 #if defined __vxWorks__
434 # ifndef OMNIORB_ENABLE_LOCK_TRACES
_dummy_TRACEDTHREAD_workaround_for_bug_in_munch_2_cdtor_c_()435 void _dummy_TRACEDTHREAD_workaround_for_bug_in_munch_2_cdtor_c_ () {}
436 # endif // ifndef OMNIORB_ENABLE_LOCK_TRACES
437 #endif // __vxWorks__
438