BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI / h / BPatch_eventLock.h
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 #ifndef _BPatch_eventLock_h_
43 #define _BPatch_eventLock_h_
44
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <assert.h>
50 #include <BPatch_dll.h>
51
52 #if !defined(os_windows)
53 #include <pthread.h> // Trying native windows threads for now
54 #else
55 #define WIN32_LEAN_AND_MEAN
56 #include <windows.h>
57 #include <winsock2.h>
58 #endif
59
60 #if defined(os_irix) || defined (os_windows)
61 #define CONST_EXPORT
62 #else
63 #define CONST_EXPORT const
64 #endif
65
66 #if defined (os_windows)
67 #define CONST_ARG
68 #else
69 #define CONST_ARG const
70 #endif
71
72 /*
73  * Class BPatch_eventLock
74  *
75  *
76  * This class contains a (single) mutex lock controlling access to all
77  * underlying BPatch (and lower level) data.
78  * This object is a virtual class that should be a base class for all user
79  * api's to dyninst
80  */
81
82 #if defined(os_windows)
83 #define MUTEX_TYPE CRITICAL_SECTION
84 extern MUTEX_TYPE global_mutex;
85 #else
86 #define MUTEX_TYPE pthread_mutex_t
87 extern MUTEX_TYPE global_mutex;
88 #endif
89
90 extern bool mutex_created;
91 #if defined(os_linux) && defined (arch_x86)
92 #define PTHREAD_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE_NP
93 #define STRERROR_BUFSIZE 512
94 #define ERROR_BUFFER char buf[STRERROR_BUFSIZE]
95 #define STRERROR(x,y) strerror_r(x,y,STRERROR_BUFSIZE)
96 #else
97 #define ERROR_BUFFER
98 #define PTHREAD_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE
99 #define STRERROR_BUFSIZE 0
100 #define STRERROR(x,y) strerror(x)
101 #endif
102
103
104 //  BPatch_eventLock
105 //  
106 //  This class forms a base class for most DyninstAPI classes and is currently
107 //  responsible for managing a global mutex variable which controls access to 
108 //  _all_ internal dyninst/paradyn data structures.
109 //
110 //  It works in conjunction with the locking macros to isolate all mutex operations,
111 //  but can be used seperately as needed (should not be necessary, think twice).
112 //
113 //  Eventually may become more specialized if we move to a finer-grain of data locking.
114
115 #define __LOCK _Lock(__FILE__, __LINE__)
116 #define __UNLOCK _Unlock(__FILE__, __LINE__)
117
118 class BPATCH_DLL_EXPORT BPatch_eventLock {
119
120 protected:
121
122   BPatch_eventLock(); 
123   virtual ~BPatch_eventLock();
124
125   unsigned long threadID() const;
126 public:
127
128   int _Lock(const char *__file__, unsigned int __line__) const; 
129   int _Trylock(const char *__file__, unsigned int __line__) const; 
130   int _Unlock(const char *__file__, unsigned int __line__) const; 
131
132 };
133
134 #define LOCK_FUNCTION(x)   return lock_function_nv (this, &DYNINST_CLASS_NAME::x, \
135                                                     __FILE__, __LINE__)
136 #define LOCK_FUNCTION_V(x)        lock_function_v  (this, &DYNINST_CLASS_NAME::x, \
137                                                     __FILE__, __LINE__)
138
139 //  API_EXPORT is a multithread-lock wrapper.
140 //  Argument summary:
141 //
142 //  z:  The suffix appended onto the wrapped function, usually "Int", no quotes.
143 //      The wrapped function and the wrapping function must have distinct names
144 //      or else they will not be distinguishible (type-wise) overloads.
145 //  w:  The list of arguments passed to the wrapped function.  Really just the 
146 //      argument list without type information.
147 //  t:  Return type of the function
148 //  x:  The name of the function as exported to the API user.  The "internal",
149 //      ie unlocked function prototype is constructed by appending arg <z> to this.
150 //  y:  The parameter list for the function exported to the API user.
151
152 #define API_EXPORT(z, w, t, x, y)      private:  t x##z y; \
153                                        public:   t x y \
154                                        { LOCK_FUNCTION(x##z) w;}
155
156 //  API_EXPORT_V is used for functions that return void.
157 //  This variant would not be necessary were (windows) vc6 not 
158 //  buggy in its template specialization code.  But here we are...
159 //  If we move to vc7, this should be re-evaluated.  The (documented)
160 //  windows compiler bugs only apply to vc6.
161
162 #define API_EXPORT_V(z, w, t, x, y)    private:  t x##z y; \
163                                        public:   t x y \
164                                        { LOCK_FUNCTION_V(x##z) w;}
165
166 //  "CTOR" and "DTOR" flavors do not have return type.
167 //  wrapped function implicitly returns void.
168
169 #define API_EXPORT_CTOR(z, w, x, y)    private:  void x##z y; \
170                                        public:   x y \
171                                        { LOCK_FUNCTION_V(x##z) w;}
172
173 //  here t is for "tilde" (ignored, but there for dtor appearance)
174
175 #define API_EXPORT_DTOR(z, w, t, x, y) private:  void x##z y; \
176                                        public:   virtual ~x y \
177                                        { LOCK_FUNCTION_V(x##z) w;}
178
179 //  operators present a special case for the preprocessor
180 //  suffix <z> is appended to the word "operator", eg, operator_lessthan
181 //  (with <z> = "_lessthan"), forms the wrapped function name
182
183 #define API_EXPORT_OPER(z, w, t, x, y) private:  t operator##z y; \
184                                        public:   t x y \
185                                        { LOCK_FUNCTION(operator##z) w;}
186
187
188
189 //  Typed template argument paramters (used to specify operator types)
190 #define OPER_ARGS_0 ()
191 #define OPER_ARGS_1 (A1 a1)
192 #define OPER_ARGS_2 (A1 a1, A2 a2)
193 #define OPER_ARGS_3 (A1 a1, A2 a2, A3 a3)
194 #define OPER_ARGS_4 (A1 a1, A2 a2, A3 a3, A4 a4)
195 #define OPER_ARGS_5 (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
196 #define OPER_ARGS_6 (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
197 #define OPER_ARGS_7 (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
198 #define OPER_ARGS_8 (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
199 #define OPER_ARGS_9 (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
200
201 //  Untyped template argument parameters (parameters passed to locking operators)
202 #define ARGS_NOTYPE_0 ()
203 #define ARGS_NOTYPE_1 (a1)
204 #define ARGS_NOTYPE_2 (a1,a2)
205 #define ARGS_NOTYPE_3 (a1,a2,a3)
206 #define ARGS_NOTYPE_4 (a1,a2,a3,a4)
207 #define ARGS_NOTYPE_5 (a1,a2,a3,a4,a5)
208 #define ARGS_NOTYPE_6 (a1,a2,a3,a4,a5,a6)
209 #define ARGS_NOTYPE_7 (a1,a2,a3,a4,a5,a6,a7)
210 #define ARGS_NOTYPE_8 (a1,a2,a3,a4,a5,a6,a7,a8)
211 #define ARGS_NOTYPE_9 (a1,a2,a3,a4,a5,a6,a7,a8,a9)
212
213 // Lists of argument types for locking operators (used to specify func ptr types)
214 #define ARG_TYPES_0 
215 #define ARG_TYPES_1 A1
216 #define ARG_TYPES_2 A1,A2
217 #define ARG_TYPES_3 A1,A2,A3
218 #define ARG_TYPES_4 A1,A2,A3,A4
219 #define ARG_TYPES_5 A1,A2,A3,A4,A5
220 #define ARG_TYPES_6 A1,A2,A3,A4,A5,A6
221 #define ARG_TYPES_7 A1,A2,A3,A4,A5,A6,A7
222 #define ARG_TYPES_8 A1,A2,A3,A4,A5,A6,A7,A8
223 #define ARG_TYPES_9 A1,A2,A3,A4,A5,A6,A7,A8,A9
224
225 //  EXPORT_FUNC_OBJ expands to 2 things: (1) a function-object template class (some
226 //  people like to call them "functors", and (2) an overloaded function that 
227 //  implicitly instantiates the function object.  
228 //
229 //  the function that instantiates the function-object is either called
230 //  locked_function_v, or locked_function_nv, depending on whether the 
231 //  function that is encapsulated in the function object returns a value (_nv), or
232 //  void (_v).  Again, this distinction is only necessary due to bugs in the windows
233 //  vc6 compilers.  Otherwise we could use template specialization for the creation
234 //  of function objects, and have uniformly named instantiation functions (and hence
235 //  a more uniform macro, without the special case of _V).
236 //
237 //  By implicitly instantiating the function object and immediately calling its
238 //  operator() with the right arguments, we can effectivly create an inline,
239 //  one-line function wrapper to handle all mutex locking.  This keeps other dyninst
240 //  code free of messy locking considerations, and, hopefully safer from accidentally
241 //  introduced race-conditions as development inevitably progresses.
242 //
243 //  
244
245 #define EXPORT_FUNC_OBJ(num_args, arg_types, t_classes, oper, template_spec, voidflag) \
246   template  t_classes  \
247   class locked_function_##num_args##_args_##voidflag { \
248   private: \
249   RetType (BaseType::*fptr)(arg_types); \
250   BaseType *baseptr; \
251   const char *__file__; \
252   unsigned int __line__; \
253   public: \
254   explicit inline\
255   locked_function_##num_args##_args_##voidflag(BaseType *bptr, \
256                                                RetType (BaseType::*fptr_)(arg_types),\
257                                                const char *_f, unsigned int _l) : \
258                                                fptr(fptr_), baseptr(bptr), \
259                                                __file__(_f), __line__(_l) {} \
260   oper \
261   }; \
262   template t_classes \
263   inline locked_function_##num_args##_args_##voidflag template_spec \
264   lock_function_##voidflag(BaseType *bptr, RetType (BaseType::*fptr_)(arg_types), \
265                            const char *__file__, unsigned int __line__) { \
266     return locked_function_##num_args##_args_##voidflag template_spec \
267                                  (bptr, fptr_, __file__, __line__); \
268   }
269
270
271 //  OPER_NV and OPER_V are where the locking & unlocking actually happen
272 //  These define the "flavor" of EXPORT_FUNC_OBJ, along with <voidflag>
273 //  -- there is a 1-1 mapping:  <voidflag> = "v" <--> OPER_V, and
274 //  <voidflag> = "nv" <--> OPER_NV
275
276 #define OPER_NV(oper_args, oper_args_notype) \
277   inline RetType CONST_EXPORT operator() oper_args \
278   { \
279     baseptr->_Lock(__file__, __line__); \
280     RetType ret = (baseptr->*fptr) oper_args_notype; \
281     baseptr->_Unlock(__file__, __line__); \
282     return ret; \
283   } 
284
285 //  RetType is implicitly void in OPER_V
286 //  (left as template parameter as sanity check 
287 //     -- the compiler will complain if its not void for some reason)
288
289 #define OPER_V(oper_args, oper_args_notype) \
290   inline RetType CONST_EXPORT operator() oper_args \
291   { \
292     baseptr->_Lock(__file__, __line__); \
293     (baseptr->*fptr) oper_args_notype; \
294     baseptr->_Unlock(__file__, __line__); \
295   } 
296
297 #define T_SPEC_0 <BaseType, RetType>
298 #define T_SPEC_1 <BaseType, RetType, A1>
299 #define T_SPEC_2 <BaseType, RetType, A1, A2>
300 #define T_SPEC_3 <BaseType, RetType, A1, A2, A3>
301 #define T_SPEC_4 <BaseType, RetType, A1, A2, A3, A4>
302 #define T_SPEC_5 <BaseType, RetType, A1, A2, A3, A4, A5>
303 #define T_SPEC_6 <BaseType, RetType, A1, A2, A3, A4, A5, A6>
304 #define T_SPEC_7 <BaseType, RetType, A1, A2, A3, A4, A5, A6, A7>
305 #define T_SPEC_8 <BaseType, RetType, A1, A2, A3, A4, A5, A6, A7, A8>
306 #define T_SPEC_9 <BaseType, RetType, A1, A2, A3, A4, A5, A6, A7, A8, A9>
307
308 #define T_CLASSES_0 <class BaseType, class RetType>
309 #define T_CLASSES_1 <class BaseType, class RetType, class A1>
310 #define T_CLASSES_2 <class BaseType, class RetType, class A1, class A2>
311 #define T_CLASSES_3 <class BaseType, class RetType, class A1, class A2, class A3>
312 #define T_CLASSES_4 <class BaseType, class RetType, class A1, class A2, class A3,\
313                      class A4>
314 #define T_CLASSES_5 <class BaseType, class RetType, class A1, class A2, class A3,\
315                      class A4, class A5>
316 #define T_CLASSES_6 <class BaseType, class RetType, class A1, class A2, class A3,\
317                      class A4, class A5, class A6>
318 #define T_CLASSES_7 <class BaseType, class RetType, class A1, class A2, class A3,\
319                      class A4, class A5, class A6, class A7>
320 #define T_CLASSES_8 <class BaseType, class RetType, class A1, class A2, class A3,\
321                      class A4, class A5, class A6, class A7, class A8>
322 #define T_CLASSES_9 <class BaseType, class RetType, class A1, class A2, class A3,\
323                      class A4, class A5, class A6, class A7, class A8, class A9>
324
325 //  Locking function objects for functions that return values
326 //  (At time of writing, the largest number of arguments for a dyninstAPI function was 6
327 //  Providing up to 9)
328
329 EXPORT_FUNC_OBJ(0,ARG_TYPES_0, T_CLASSES_0, OPER_NV(OPER_ARGS_0, ARGS_NOTYPE_0),T_SPEC_0,nv);
330 EXPORT_FUNC_OBJ(1,ARG_TYPES_1, T_CLASSES_1, OPER_NV(OPER_ARGS_1, ARGS_NOTYPE_1),T_SPEC_1,nv);
331 EXPORT_FUNC_OBJ(2,ARG_TYPES_2, T_CLASSES_2, OPER_NV(OPER_ARGS_2, ARGS_NOTYPE_2),T_SPEC_2,nv);
332 EXPORT_FUNC_OBJ(3,ARG_TYPES_3, T_CLASSES_3, OPER_NV(OPER_ARGS_3, ARGS_NOTYPE_3),T_SPEC_3,nv);
333 EXPORT_FUNC_OBJ(4,ARG_TYPES_4, T_CLASSES_4, OPER_NV(OPER_ARGS_4, ARGS_NOTYPE_4),T_SPEC_4,nv);
334 EXPORT_FUNC_OBJ(5,ARG_TYPES_5, T_CLASSES_5, OPER_NV(OPER_ARGS_5, ARGS_NOTYPE_5),T_SPEC_5,nv);
335 EXPORT_FUNC_OBJ(6,ARG_TYPES_6, T_CLASSES_6, OPER_NV(OPER_ARGS_6, ARGS_NOTYPE_6),T_SPEC_6,nv);
336 EXPORT_FUNC_OBJ(7,ARG_TYPES_7, T_CLASSES_7, OPER_NV(OPER_ARGS_7, ARGS_NOTYPE_7),T_SPEC_7,nv);
337 EXPORT_FUNC_OBJ(8,ARG_TYPES_8, T_CLASSES_8, OPER_NV(OPER_ARGS_8, ARGS_NOTYPE_8),T_SPEC_8,nv);
338 EXPORT_FUNC_OBJ(9,ARG_TYPES_9, T_CLASSES_9, OPER_NV(OPER_ARGS_9, ARGS_NOTYPE_9),T_SPEC_9,nv);
339
340 //  Corresponding locking function objects for functions that return void
341
342 EXPORT_FUNC_OBJ(0,ARG_TYPES_0, T_CLASSES_0, OPER_V (OPER_ARGS_0, ARGS_NOTYPE_0),T_SPEC_0, v);
343 EXPORT_FUNC_OBJ(1,ARG_TYPES_1, T_CLASSES_1, OPER_V (OPER_ARGS_1, ARGS_NOTYPE_1),T_SPEC_1, v);
344 EXPORT_FUNC_OBJ(2,ARG_TYPES_2, T_CLASSES_2, OPER_V (OPER_ARGS_2, ARGS_NOTYPE_2),T_SPEC_2, v);
345 EXPORT_FUNC_OBJ(3,ARG_TYPES_3, T_CLASSES_3, OPER_V (OPER_ARGS_3, ARGS_NOTYPE_3),T_SPEC_3, v);
346 EXPORT_FUNC_OBJ(4,ARG_TYPES_4, T_CLASSES_4, OPER_V (OPER_ARGS_4, ARGS_NOTYPE_4),T_SPEC_4, v);
347 EXPORT_FUNC_OBJ(5,ARG_TYPES_5, T_CLASSES_5, OPER_V (OPER_ARGS_5, ARGS_NOTYPE_5),T_SPEC_5, v);
348 EXPORT_FUNC_OBJ(6,ARG_TYPES_6, T_CLASSES_6, OPER_V (OPER_ARGS_6, ARGS_NOTYPE_6),T_SPEC_6, v);
349 EXPORT_FUNC_OBJ(7,ARG_TYPES_7, T_CLASSES_7, OPER_V (OPER_ARGS_7, ARGS_NOTYPE_7),T_SPEC_7, v);
350 EXPORT_FUNC_OBJ(8,ARG_TYPES_8, T_CLASSES_8, OPER_V (OPER_ARGS_8, ARGS_NOTYPE_8),T_SPEC_8, v);
351 EXPORT_FUNC_OBJ(9,ARG_TYPES_9, T_CLASSES_9, OPER_V (OPER_ARGS_9, ARGS_NOTYPE_9),T_SPEC_9, v);
352
353
354   
355 #endif
356