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