BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI / src / BPatch_eventLock.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  *
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  *
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  *
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  *
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  *
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  *
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42
43
44 #include "BPatch_eventLock.h"
45 #include "BPatch_asyncEventHandler.h"
46 #include "BPatch_thread.h"
47 #include "BPatch_function.h"
48 #include "BPatch_point.h"
49 #include "common/h/Vector.h"
50
51 //#define DEBUG_MUTEX 1
52
53
54 MUTEX_TYPE global_mutex;
55 bool mutex_created = false;
56
57 BPatch_eventMailbox *event_mailbox;
58 unsigned long primary_thread_id = (unsigned long) -1;
59
60 int lock_depth = 0;
61
62 BPatch_eventLock::BPatch_eventLock() 
63 {
64   if (mutex_created) return;
65 #if defined(os_windows)
66   InitializeCriticalSection(&global_mutex);
67   primary_thread_id = _threadid;
68 #else
69   pthread_mutexattr_t mutex_type;
70   pthread_mutexattr_init(&mutex_type);
71   primary_thread_id = (unsigned long) pthread_self();
72 #if defined(arch_ia64)
73   try {
74     pthread_mutexattr_settype(&mutex_type, PTHREAD_MUTEX_RECURSIVE_NP);
75   }catch (...) {
76     fprintf(stderr, "%s[%d]: exception %d\n", __FILE__, __LINE__);
77   }
78   try {
79   pthread_mutex_init(&global_mutex, &mutex_type);
80   }catch (...) {
81     fprintf(stderr, "%s[%d]: exception%d\n", __FILE__, __LINE__);
82   }
83 #else
84   pthread_mutexattr_settype(&mutex_type, PTHREAD_MUTEX_TYPE);
85   pthread_mutex_init(&global_mutex, &mutex_type);
86 #endif
87 #endif // !Windows
88   event_mailbox = new BPatch_eventMailbox();
89   
90   mutex_created = true;
91 }
92
93 #ifdef NOTDEF
94 bool BPatch_eventLock::init() 
95 {
96   if (mutex_created) return;
97 #if defined(os_windows)
98   InitializeCriticalSection(&global_mutex);
99 #else
100   pthread_mutexattr_t mutex_type;
101   pthread_mutexattr_init(&mutex_type);
102 #if defined(arch_ia64)
103   if (0 != pthread_mutexattr_setkind_np(&mutex_type, PTHREAD_MUTEX_TYPE))
104     return false;
105 #else
106   if (0 != pthread_mutexattr_settype(&mutex_type, PTHREAD_MUTEX_TYPE))
107     return false;
108 #endif
109   if (0 != pthread_mutex_init(&global_mutex, &mutex_type))
110     return false;
111 #endif // !Windows
112   mutex_created = true;
113   return true;
114 }
115 #endif
116 BPatch_eventLock::~BPatch_eventLock() {};
117
118 #if defined(os_windows)
119
120 int BPatch_eventLock::_Lock(const char *__file__, unsigned int __line__) const
121 {
122   EnterCriticalSection(&global_mutex);
123   lock_depth++;
124   if ((threadID() == primary_thread_id) && (lock_depth == 1))
125     event_mailbox->executeUserCallbacks();
126   return 0;
127 }
128
129 unsigned long BPatch_eventLock::threadID() const
130 {
131   return (unsigned long) _threadid;
132 }
133
134 int BPatch_eventLock::_Trylock(const char *__file__, unsigned int __line__) const
135 {
136   TryEnterCriticalSection(&global_mutex);
137   return 0;
138 }
139
140 int BPatch_eventLock::_Unlock(const char *__file__, unsigned int __line__) const
141 {
142   lock_depth--;
143   LeaveCriticalSection(&global_mutex);
144   return 0;
145 }
146
147 #else
148 unsigned long BPatch_eventLock::threadID() const
149 {
150   return (unsigned long) pthread_self();
151 }
152
153 int BPatch_eventLock::_Lock(const char *__file__, unsigned int __line__) const
154 {
155   int err = 0;
156   if(0 != (err = pthread_mutex_lock(&global_mutex))){
157     ERROR_BUFFER;
158     fprintf(stderr, "%s[%d]:  failed to lock mutex: %s[%d]\n",
159             __file__, __line__, STRERROR(err, buf), err);
160   }
161   lock_depth++;
162 #ifdef DEBUG_MUTEX
163   fprintf(stderr, "%s[%d]:  lock, depth = %d\n", __file__, __line__, lock_depth);
164 #endif
165
166   unsigned long tid = threadID();
167   if ((tid == primary_thread_id) && (lock_depth == 1))
168     event_mailbox->executeUserCallbacks();
169
170   return err;
171 }
172
173 int BPatch_eventLock::_Trylock(const char *__file__, unsigned int __line__) const
174 {
175   int err = 0;
176   if(0 != (err = pthread_mutex_trylock(&global_mutex))){
177     if (EBUSY != err) {
178       ERROR_BUFFER;
179       //  trylock returns EBUSY immediately when lock cannot be obtained
180       fprintf(stderr, "%s[%d]:  failed to trylock mutex: %s[%d]\n",
181               __file__, __line__, STRERROR(err, buf), err);
182     }
183   }
184   return err;
185 }
186
187 int BPatch_eventLock::_Unlock(const char *__file__, unsigned int __line__) const
188 {
189   int err = 0;
190   lock_depth--;
191 #ifdef DEBUG_MUTEX
192   fprintf(stderr, "%s[%d]:  unlock, lock depth will be %d \n", __file__, __line__, lock_depth);
193 #endif
194   if(0 != (err = pthread_mutex_unlock(&global_mutex))){
195     ERROR_BUFFER;
196     fprintf(stderr, "%s[%d]:  failed to unlock mutex: %s[%d]\n",
197             __file__, __line__, STRERROR(err, buf), err);
198   }
199   return err;
200 }
201
202 #endif
203
204