OpenMPI  0.1.1
vt_iowrap.h
1 /**
2  * VampirTrace
3  * http://www.tu-dresden.de/zih/vampirtrace
4  *
5  * Copyright (c) 2005-2012, ZIH, TU Dresden, Federal Republic of Germany
6  *
7  * Copyright (c) 1998-2005, Forschungszentrum Juelich, Juelich Supercomputing
8  * Centre, Federal Republic of Germany
9  *
10  * See the file COPYING in the package base directory for details
11  **/
12 
13 #ifndef _VT_IOWRAP_H_
14 #define _VT_IOWRAP_H_
15 
16 #include "config.h"
17 
18 #ifdef __cplusplus
19 # define EXTERN extern "C"
20 #else
21 # define EXTERN extern
22 #endif
23 
24 #if (defined(VT_IOWRAP))
25 
26 #include "vt_error.h"
27 #include "vt_thrd.h"
28 #include "vt_inttypes.h"
29 
30 #include <string.h>
31 
32 
33 #define VT_ENABLE_IO_TRACING() \
34  VT_CHECK_THREAD; \
35  VTTHRD_IO_TRACING_ENABLED(VTTHRD_MY_VTTHRD) = 1; \
36  vt_debug_msg( DBG_INIT, "ENABLED I/O tracing (susp=%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(VTTHRD_MY_VTTHRD), __LINE__ )
37 
38 #define VT_DISABLE_IO_TRACING() \
39  VT_CHECK_THREAD; \
40  VTTHRD_IO_TRACING_ENABLED(VTTHRD_MY_VTTHRD) = 0; \
41  vt_debug_msg( DBG_INIT, "DISABLED I/O tracing (susp=%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(VTTHRD_MY_VTTHRD), __LINE__ )
42 
43 #define VT_SUSPEND_IO_TRACING(tid) \
44  { \
45  VTThrd *thrd; \
46  if( tid == VT_CURRENT_THREAD ) { \
47  VT_CHECK_THREAD; \
48  thrd = VTTHRD_MY_VTTHRD; \
49  } else { \
50  thrd = VTThrdv[tid]; \
51  } \
52  if( VTTHRD_IO_TRACING_ENABLED(thrd) ) { \
53  VTTHRD_IO_TRACING_STATE(thrd) = VTTHRD_IO_TRACING_ENABLED(thrd); \
54  VTTHRD_IO_TRACING_SUSPEND_CNT(thrd)++; \
55  VTTHRD_IO_TRACING_ENABLED(thrd) = 0; \
56  vt_debug_msg( DBG_INIT, "SUSPENDED I/O tracing (%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(thrd), __LINE__ ); \
57  } \
58  else { \
59  VTTHRD_IO_TRACING_SUSPEND_CNT(thrd)++; \
60  vt_debug_msg( DBG_INIT, "SUSPENDED I/O tracing (%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(thrd), __LINE__ ); \
61  } \
62  }
63 
64 #define VT_RESUME_IO_TRACING(tid) \
65  { \
66  VTThrd *thrd; \
67  if( tid == VT_CURRENT_THREAD ) { \
68  VT_CHECK_THREAD; \
69  thrd = VTTHRD_MY_VTTHRD; \
70  } else { \
71  thrd = VTThrdv[tid]; \
72  } \
73  vt_debug_msg( DBG_INIT, "TRY RESUME I/O tracing (%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(thrd), __LINE__ ); \
74  if( VTTHRD_IO_TRACING_SUSPEND_CNT(thrd) > 0 ) { \
75  if( (--VTTHRD_IO_TRACING_SUSPEND_CNT(thrd)) == 0 ) { \
76  vt_debug_msg( DBG_INIT, "RESUMED I/O tracing (%hhu) at " __FILE__ ", %i", VTTHRD_IO_TRACING_SUSPEND_CNT(thrd), __LINE__ ); \
77  VTTHRD_IO_TRACING_ENABLED(thrd) = VTTHRD_IO_TRACING_STATE(thrd); \
78  } \
79  } \
80  }
81 
82 enum func_id {
83  open_IDX,
84  open64_IDX,
85  creat_IDX,
86  creat64_IDX,
87  close_IDX,
88  dup_IDX,
89  dup2_IDX,
90  lseek_IDX,
91  lseek64_IDX,
92  read_IDX,
93  write_IDX,
94  readv_IDX,
95  writev_IDX,
96  pread_IDX,
97  pwrite_IDX,
98  pread64_IDX,
99  pwrite64_IDX,
100  fdopen_IDX,
101  fopen_IDX,
102  fopen64_IDX,
103  fclose_IDX,
104  fseek_IDX,
105  fseeko_IDX,
106  fseeko64_IDX,
107  rewind_IDX,
108  fsetpos_IDX,
109  fsetpos64_IDX,
110  fread_IDX,
111  fwrite_IDX,
112  fgetc_IDX,
113  getc_IDX,
114  fgets_IDX,
115  gets_IDX,
116  fputc_IDX,
117  putc_IDX,
118  fputs_IDX,
119  puts_IDX,
120  fscanf_IDX,
121  fprintf_IDX,
122  unlink_IDX,
123  flockfile_IDX,
124  ftrylockfile_IDX,
125  funlockfile_IDX,
126  lockf_IDX,
127  fcntl_IDX,
128  sync_IDX,
129  fflush_IDX,
130  fsync_IDX,
131  fdatasync_IDX,
132  NUMFUNCTIONS
133 };
134 
135 struct iofunctions {
136  int traceme;
137  int vt_func_id;
138 /* The following is necessary to avoid "warning: ISO C forbids conversion of
139  * object pointer to function pointer type". If the function calls break on some
140  * platform, the cause would most possibly lie here.
141  * Then sizeof(void *) != sizeof(<function pointer>)
142  */
143  union {
144  void *p;
145  void (*f)(void);
146  } lib_func;
147 };
148 
149 
150 /* io wrapper initialization/finalization */
151 EXTERN void vt_iowrap_externals_init(void);
152 EXTERN void vt_iowrap_init(void);
153 EXTERN void vt_iowrap_reg(void);
154 EXTERN void vt_iowrap_finalize(void);
155 
156 EXTERN int(*libc_fprintf)(FILE *, const char *, ...);
157 
158 #define open_FUNCDEF (int (*)(const char *, int, mode_t))
159 #define open_FUNCTYPE VT_IOOP_OPEN
160 #define open64_FUNCDEF (int (*)(const char *, int, mode_t))
161 #define open64_FUNCTYPE VT_IOOP_OPEN
162 #define creat_FUNCDEF (int (*)(const char *, mode_t))
163 #define creat_FUNCTYPE VT_IOOP_OPEN
164 #define creat64_FUNCDEF (int (*)(const char *, mode_t))
165 #define creat64_FUNCTYPE VT_IOOP_OPEN
166 #define dup_FUNCDEF (int (*)(int))
167 #define dup_FUNCTYPE VT_IOOP_DUP
168 #define dup2_FUNCDEF (int (*)(int, int))
169 #define dup2_FUNCTYPE VT_IOOP_DUP
170 #define close_FUNCDEF (int (*)(int))
171 #define close_FUNCTYPE VT_IOOP_CLOSE
172 #define lseek_FUNCDEF (off_t (*)(int, off_t, int))
173 #define lseek_FUNCTYPE VT_IOOP_SEEK
174 #define lseek64_FUNCDEF (off64_t (*)(int, off64_t, int))
175 #define lseek64_FUNCTYPE VT_IOOP_SEEK
176 #define read_FUNCDEF (ssize_t (*)(int, void *, size_t))
177 #define read_FUNCTYPE VT_IOOP_READ
178 #define write_FUNCDEF (ssize_t (*)(int, const void *, size_t))
179 #define write_FUNCTYPE VT_IOOP_WRITE
180 #define readv_FUNCDEF (int (*)(int, const struct iovec *, size_t))
181 #define readv_FUNCTYPE VT_IOOP_READ
182 #define writev_FUNCDEF (int (*)(int, const struct iovec *, size_t))
183 #define writev_FUNCTYPE VT_IOOP_WRITE
184 #define pread_FUNCDEF (ssize_t (*)(int, void *, size_t, off_t))
185 #define pread_FUNCTYPE VT_IOOP_READ
186 #define pwrite_FUNCDEF (ssize_t (*)(int, const void *, size_t, off_t))
187 #define pwrite_FUNCTYPE VT_IOOP_WRITE
188 #define pread64_FUNCDEF (ssize_t (*)(int, void *, size_t, off64_t))
189 #define pread64_FUNCTYPE VT_IOOP_READ
190 #define pwrite64_FUNCDEF (ssize_t (*)(int, const void *, size_t, off64_t))
191 #define pwrite64_FUNCTYPE VT_IOOP_WRITE
192 #define fdopen_FUNCDEF (FILE *(*)(int, const char *))
193 #define fdopen_FUNCTYPE VT_IOOP_OPEN
194 #define fopen_FUNCDEF (FILE *(*)(const char *, const char *))
195 #define fopen_FUNCTYPE VT_IOOP_OPEN
196 #define fopen64_FUNCDEF (FILE *(*)(const char *, const char *))
197 #define fopen64_FUNCTYPE VT_IOOP_OPEN
198 #define fclose_FUNCDEF (int (*)(FILE *))
199 #define fclose_FUNCTYPE VT_IOOP_CLOSE
200 #define fseek_FUNCDEF (int (*)(FILE *, long, int))
201 #define fseek_FUNCTYPE VT_IOOP_SEEK
202 #define fseeko_FUNCDEF (int (*)(FILE *, off_t, int))
203 #define fseeko_FUNCTYPE VT_IOOP_SEEK
204 #define fseeko64_FUNCDEF (int (*)(FILE *, off64_t, int))
205 #define fseeko64_FUNCTYPE VT_IOOP_SEEK
206 #define rewind_FUNCDEF (void (*)(FILE *))
207 #define rewind_FUNCTYPE VT_IOOP_SEEK
208 #define fsetpos_FUNCDEF (int (*)(FILE *, const fpos_t *))
209 #define fsetpos_FUNCTYPE VT_IOOP_SEEK
210 #define fsetpos64_FUNCDEF (int (*)(FILE *, const fpos64_t *))
211 #define fsetpos64_FUNCTYPE VT_IOOP_SEEK
212 #define fread_FUNCDEF (size_t (*)(void *, size_t, size_t, FILE *))
213 #define fread_FUNCTYPE VT_IOOP_READ
214 #define fwrite_FUNCDEF (size_t (*)(const void *, size_t, size_t, FILE *))
215 #define fwrite_FUNCTYPE VT_IOOP_WRITE
216 #define fgetc_FUNCDEF (int (*)(FILE *))
217 #define fgetc_FUNCTYPE VT_IOOP_READ
218 #define getc_FUNCDEF (int (*)(FILE *))
219 #define getc_FUNCTYPE VT_IOOP_READ
220 #define fgets_FUNCDEF (char *(*)(char *, int, FILE *))
221 #define fgets_FUNCTYPE VT_IOOP_READ
222 #define gets_FUNCDEF (char *(*)(char *))
223 #define gets_FUNCTYPE VT_IOOP_READ
224 #define fputc_FUNCDEF (int (*)(int, FILE *))
225 #define fputc_FUNCTYPE VT_IOOP_WRITE
226 #define putc_FUNCDEF (int (*)(int, FILE *))
227 #define putc_FUNCTYPE VT_IOOP_WRITE
228 #define fputs_FUNCDEF (int (*)(const char *, FILE *))
229 #define fputs_FUNCTYPE VT_IOOP_WRITE
230 #define puts_FUNCDEF (int (*)(const char *))
231 #define puts_FUNCTYPE VT_IOOP_WRITE
232 /* #define ungetc_FUNCDEF (int (*)(int, FILE *)) */
233 #define fscanf_FUNCDEF (int (*)(FILE *, const char *, ...))
234 #define fscanf_FUNCTYPE VT_IOOP_READ
235 #define fprintf_FUNCDEF (int (*)(FILE *, const char *, ...))
236 #define fprintf_FUNCTYPE VT_IOOP_WRITE
237 /* #define vfscanf_FUNCDEF (int (*)(FILE *, const char *, va_list)) */
238 /* #define vfprintf_FUNCDEF (int (*)(FILE *, const char *, va_list)) */
239 #define unlink_FUNCDEF (int (*)(const char *))
240 #define unlink_FUNCTYPE VT_IOOP_UNLINK
241 #define flockfile_FUNCDEF (void (*)(FILE *))
242 #define flockfile_FUNCTYPE VT_IOOP_LOCK
243 #define ftrylockfile_FUNCDEF (int (*)(FILE *))
244 #define ftrylockfile_FUNCTYPE VT_IOOP_LOCK
245 #define funlockfile_FUNCDEF (void (*)(FILE *))
246 #define funlockfile_FUNCTYPE VT_IOOP_UNLOCK
247 #define lockf_FUNCDEF (int (*)(int, int, off_t))
248 /* No need for lockf_FUNCTYPE, it is set inside the function */
249 #define fcntl_FUNCDEF (int (*)(int, int, void *))
250 /* No need for fcntl_FUNCTYPE, it is set inside the function */
251 #define sync_FUNCDEF (void (*)(void))
252 #define sync_FUNCTYPE VT_IOOP_SYNC
253 #define fflush_FUNCDEF (int (*)(FILE *))
254 #define fflush_FUNCTYPE VT_IOOP_SYNC
255 #define fsync_FUNCDEF (int (*)(int))
256 #define fsync_FUNCTYPE VT_IOOP_SYNC
257 #define fdatasync_FUNCDEF (int (*)(int))
258 #define fdatasync_FUNCTYPE VT_IOOP_SYNC
259 
260 /* #define IOWRAP_REGION_DESCR_LEN 256 */
261 #define DBG_INIT 1
262 #define DBG_IO 2
263 #define DBG_VT_CALL 3
264 #define DBG_TRACECHK 4
265 #define DBG_FULL 255
266 
267 
268 #define FUNC_IDX(f) _FUNC_IDX(f)
269 #define _FUNC_IDX(f) f ## _IDX
270 #define VT_IOWRAP_FUNCDEF(f) f ## _FUNCDEF
271 #define VT_IOWRAP_FUNCTYPE(f) _VT_IOWRAP_FUNCTYPE(f)
272 #define _VT_IOWRAP_FUNCTYPE(f) f ## _FUNCTYPE
273 /* need double macro for stringify to evaluate macro arguments before stringifying */
274 #define stringify(x) _stringify(x)
275 #define _stringify(x) #x
276 
277 /** Setup libc pointers
278  * ... to be used in global initialization before everything else
279  * iolib_handle MUST be initialized already!
280  */
281 #define VT_IOWRAP_INIT_FUNC(FUNC_NAME) \
282 { \
283  if (!iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.p) { \
284  vt_debug_msg(DBG_INIT, "init_func: dlsym(" stringify(FUNC_NAME) ") --> "); \
285  (void)dlerror(); \
286  iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.p = \
287  dlsym( iolib_handle, stringify(FUNC_NAME) ); \
288  vt_debug_msg(DBG_INIT, "%p", iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.p); \
289  if (!iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.p) \
290  symload_fail( stringify(FUNC_NAME), dlerror() ); \
291  } \
292  else { \
293  vt_debug_msg(DBG_INIT, "init_func: " stringify(FUNC_NAME) " was already looked up: %p", \
294  iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.p); \
295  } \
296 }
297 
298 /** Setup VT region and tracing specific settings
299  * ... to be used in global initialization after RFG initialization
300  */
301 #define VT_IOWRAP_REG_FUNC(FUNC_NAME) \
302 { \
303  vt_debug_msg(DBG_INIT, "reg_func: vt_def_region(" stringify(FUNC_NAME) ")"); \
304  iofunctions[FUNC_IDX(FUNC_NAME)].vt_func_id = \
305  vt_def_region( VT_CURRENT_THREAD, stringify(FUNC_NAME), \
306  vt_fid, \
307  VT_NO_LNO, \
308  VT_NO_LNO, \
309  NULL, \
310  VT_LIBC_IO ); \
311  iofunctions[FUNC_IDX(FUNC_NAME)].traceme = 1; \
312 }
313 
314 /** Call the function FUNC_NAME from the I/O library (usually libc)
315  */
316 #if 0
317 #define VT_IOWRAP_CALL_LIBFUNC(FUNC_NAME, RET, ...) \
318 { \
319  vt_libwrap_set_libc_errno(errno); \
320  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
321  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
322  (__VA_ARGS__); \
323  errno = vt_libwrap_get_libc_errno(); \
324 }
325 #endif
326 #define VT_IOWRAP_CALL_LIBFUNC0(FUNC_NAME, RET) \
327 { \
328  vt_libwrap_set_libc_errno(errno); \
329  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
330  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
331  (); \
332  errno = vt_libwrap_get_libc_errno(); \
333 }
334 #define VT_IOWRAP_CALL_LIBFUNC1(FUNC_NAME, RET, ARG1) \
335 { \
336  vt_libwrap_set_libc_errno(errno); \
337  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
338  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
339  (ARG1); \
340  errno = vt_libwrap_get_libc_errno(); \
341 }
342 #define VT_IOWRAP_CALL_LIBFUNC2(FUNC_NAME, RET, ARG1, ARG2) \
343 { \
344  vt_libwrap_set_libc_errno(errno); \
345  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
346  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
347  (ARG1, ARG2); \
348  errno = vt_libwrap_get_libc_errno(); \
349 }
350 #define VT_IOWRAP_CALL_LIBFUNC3(FUNC_NAME, RET, ARG1, ARG2, ARG3) \
351 { \
352  vt_libwrap_set_libc_errno(errno); \
353  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
354  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
355  (ARG1, ARG2, ARG3); \
356  errno = vt_libwrap_get_libc_errno(); \
357 }
358 #define VT_IOWRAP_CALL_LIBFUNC4(FUNC_NAME, RET, ARG1, ARG2, ARG3, ARG4) \
359 { \
360  vt_libwrap_set_libc_errno(errno); \
361  RET = ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
362  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
363  (ARG1, ARG2, ARG3, ARG4); \
364  errno = vt_libwrap_get_libc_errno(); \
365 }
366 
367 #if 0
368 #define VT_IOWRAP_CALL_LIBFUNC_VOID(FUNC_NAME, ...) \
369 { \
370  vt_libwrap_set_libc_errno(errno); \
371  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
372  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
373  (__VA_ARGS__); \
374  errno = vt_libwrap_get_libc_errno(); \
375 }
376 #endif
377 #define VT_IOWRAP_CALL_LIBFUNC_VOID0(FUNC_NAME) \
378 { \
379  vt_libwrap_set_libc_errno(errno); \
380  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
381  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
382  (); \
383  errno = vt_libwrap_get_libc_errno(); \
384 }
385 #define VT_IOWRAP_CALL_LIBFUNC_VOID1(FUNC_NAME, ARG1) \
386 { \
387  vt_libwrap_set_libc_errno(errno); \
388  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
389  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
390  (ARG1); \
391  errno = vt_libwrap_get_libc_errno(); \
392 }
393 #define VT_IOWRAP_CALL_LIBFUNC_VOID2(FUNC_NAME, ARG1, ARG2) \
394 { \
395  vt_libwrap_set_libc_errno(errno); \
396  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
397  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
398  (ARG1, ARG2); \
399  errno = vt_libwrap_get_libc_errno(); \
400 }
401 #define VT_IOWRAP_CALL_LIBFUNC_VOID3(FUNC_NAME, ARG1, ARG2, ARG3) \
402 { \
403  vt_libwrap_set_libc_errno(errno); \
404  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
405  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
406  (ARG1, ARG2, ARG3); \
407  errno = vt_libwrap_get_libc_errno(); \
408 }
409 #define VT_IOWRAP_CALL_LIBFUNC4_VOID(FUNC_NAME, ARG1, ARG2, ARG3, ARG4) \
410 { \
411  vt_libwrap_set_libc_errno(errno); \
412  ( VT_IOWRAP_FUNCDEF(FUNC_NAME) \
413  (iofunctions[FUNC_IDX(FUNC_NAME)].lib_func.f) ) \
414  (ARG1, ARG2, ARG3, ARG4); \
415  errno = vt_libwrap_get_libc_errno(); \
416 }
417 
418 /** Resolve function address from the I/O library (usually libc)
419  */
420 #define VT_IOWRAP_INIT_IOFUNC() \
421  uint64_t matchingid = 0; \
422  ssize_t num_bytes=0; \
423  uint8_t was_recorded; \
424  uint8_t enable_memhooks=0; \
425 { \
426  if( VT_MEMHOOKS_ENABLED() ) \
427  { VT_MEMHOOKS_OFF(); enable_memhooks = 1; } \
428  if (!iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p) { \
429  get_iolib_handle(); \
430  (void)dlerror(); \
431  iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p = \
432  dlsym( iolib_handle, stringify(VT_IOWRAP_THISFUNCNAME) ); \
433  if (!iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p) \
434  symload_fail( stringify(VT_IOWRAP_THISFUNCNAME), dlerror() ); \
435  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_INIT_IOFUNC(): " stringify(VT_IOWRAP_THISFUNCNAME) " --> %p", iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p); \
436  } \
437 }
438 
439 /** Resolve function address from the I/O library (usually libc)
440  */
441 #define VT_IOWRAP_INIT_IOFUNC_OPEN() \
442  uint64_t matchingid = 0; \
443  uint8_t was_recorded; \
444  uint8_t enable_memhooks=0; \
445 { \
446  if( VT_MEMHOOKS_ENABLED() ) \
447  { VT_MEMHOOKS_OFF(); enable_memhooks = 1; } \
448  if (!iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p) { \
449  get_iolib_handle(); \
450  (void)dlerror(); \
451  iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p = \
452  dlsym( iolib_handle, stringify(VT_IOWRAP_THISFUNCNAME) ); \
453  if (!iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p) \
454  symload_fail( stringify(VT_IOWRAP_THISFUNCNAME), dlerror() ); \
455  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_INIT_IOFUNC_OPEN(): " stringify(VT_IOWRAP_THISFUNCNAME) " --> %p", iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].lib_func.p); \
456  } \
457 }
458 
459 /** Check if tracing is enabled and return immediately if not
460  */
461 #if 0
462 #define VT_IOWRAP_CHECK_TRACING(RET, ...) \
463 { \
464  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
465  if( !DO_TRACE() ) { \
466  VT_IOWRAP_CALL_LIBFUNC(VT_IOWRAP_THISFUNCNAME, RET, __VA_ARGS__); \
467  return RET; \
468  } \
469 }
470 #endif
471 #define VT_IOWRAP_CHECK_TRACING1(RET, ARG1) \
472 { \
473  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
474  if( !DO_TRACE() ) { \
475  VT_IOWRAP_CALL_LIBFUNC1(VT_IOWRAP_THISFUNCNAME, RET, ARG1); \
476  return RET; \
477  } \
478 }
479 #define VT_IOWRAP_CHECK_TRACING2(RET, ARG1, ARG2) \
480 { \
481  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
482  if( !DO_TRACE() ) { \
483  VT_IOWRAP_CALL_LIBFUNC2(VT_IOWRAP_THISFUNCNAME, RET, ARG1, ARG2); \
484  return RET; \
485  } \
486 }
487 #define VT_IOWRAP_CHECK_TRACING3(RET, ARG1, ARG2, ARG3) \
488 { \
489  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
490  if( !DO_TRACE() ) { \
491  VT_IOWRAP_CALL_LIBFUNC3(VT_IOWRAP_THISFUNCNAME, RET, ARG1, ARG2, ARG3); \
492  return RET; \
493  } \
494 }
495 #define VT_IOWRAP_CHECK_TRACING4(RET, ARG1, ARG2, ARG3, ARG4) \
496 { \
497  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
498  if( !DO_TRACE() ) { \
499  VT_IOWRAP_CALL_LIBFUNC4(VT_IOWRAP_THISFUNCNAME, RET, ARG1, ARG2, ARG3, ARG4); \
500  return RET; \
501  } \
502 }
503 
504 #if 0
505 #define VT_IOWRAP_CHECK_TRACING_VOID(...) \
506 { \
507  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
508  if( !DO_TRACE() ) { \
509  VT_IOWRAP_CALL_LIBFUNC_VOID(VT_IOWRAP_THISFUNCNAME, __VA_ARGS__); \
510  return; \
511  } \
512 }
513 #endif
514 #define VT_IOWRAP_CHECK_TRACING_VOID0() \
515 { \
516  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
517  if( !DO_TRACE() ) { \
518  VT_IOWRAP_CALL_LIBFUNC_VOID0(VT_IOWRAP_THISFUNCNAME); \
519  return; \
520  } \
521 }
522 #define VT_IOWRAP_CHECK_TRACING_VOID1(ARG1) \
523 { \
524  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
525  if( !DO_TRACE() ) { \
526  VT_IOWRAP_CALL_LIBFUNC_VOID1(VT_IOWRAP_THISFUNCNAME, ARG1); \
527  return; \
528  } \
529 }
530 #define VT_IOWRAP_CHECK_TRACING_VOID2(ARG1, ARG2) \
531 { \
532  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
533  if( !DO_TRACE() ) { \
534  VT_IOWRAP_CALL_LIBFUNC_VOID2(VT_IOWRAP_THISFUNCNAME, ARG1, ARG2); \
535  return; \
536  } \
537 }
538 #define VT_IOWRAP_CHECK_TRACING_VOID3(ARG1, ARG2, ARG3) \
539 { \
540  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
541  if( !DO_TRACE() ) { \
542  VT_IOWRAP_CALL_LIBFUNC_VOID3(VT_IOWRAP_THISFUNCNAME, ARG1, ARG2, ARG3); \
543  return; \
544  } \
545 }
546 #define VT_IOWRAP_CHECK_TRACING_VOID4(ARG1, ARG2, ARG3, ARG4) \
547 { \
548  vt_debug_msg( DBG_TRACECHK, "Macro VT_IOWRAP_CHECK_TRACING_VOID(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
549  if( !DO_TRACE() ) { \
550  VT_IOWRAP_CALL_LIBFUNC_VOID4(VT_IOWRAP_THISFUNCNAME, ARG1, ARG2, ARG3, ARG4); \
551  return; \
552  } \
553 }
554 
555 /** Write enter record and I/O begin record, if necessary
556  */
557 #define VT_IOWRAP_ENTER_IOFUNC() \
558 { \
559  enter_time = vt_pform_wtime(); \
560  vt_debug_msg(DBG_VT_CALL, "vt_enter(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)enter_time); \
561  was_recorded = vt_enter( VT_CURRENT_THREAD, &enter_time, iofunctions[FUNC_IDX(VT_IOWRAP_THISFUNCNAME)].vt_func_id ); \
562  if( was_recorded ) { \
563  matchingid = VTTHRD_IO_NEXT_MATCHINGID(VTTHRD_MY_VTTHRD); \
564  vt_iobegin( VT_CURRENT_THREAD, &enter_time, matchingid ); \
565  } \
566 }
567 
568 /** Write I/O end record
569  * The argument is a failure condition and decides whether VT_IOFLAG_IOFAILED is
570  * added in vt_ioend
571  */
572 #define VT_IOWRAP_LEAVE_IOFUNC(ERROR_CONDITION,FD) \
573 { \
574  int preserve_errno = errno; \
575  uint64_t time = vt_pform_wtime(); \
576  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_LEAVE_IOFUNC(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
577  if( was_recorded ) { \
578  uint32_t ioop = VT_IOWRAP_FUNCTYPE(VT_IOWRAP_THISFUNCNAME); \
579  uint32_t fid; \
580  uint64_t handle; \
581  if( FD == -1 ) { \
582  fid = invalid_fd_fid; \
583  handle = 0; \
584  } \
585  else { \
586  vampir_file_t* file; \
587  file = get_vampir_file( FD ); \
588  fid = file->vampir_file_id; \
589  handle = file->handle; \
590  } \
591  if( ERROR_CONDITION ) { \
592  ioop |= VT_IOFLAG_IOFAILED; \
593  } \
594  vt_debug_msg(DBG_VT_CALL, "vt_ioend(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)time); \
595  vt_ioend( VT_CURRENT_THREAD, &time, fid, matchingid, handle, ioop, (uint64_t)num_bytes ); \
596  } \
597  vt_exit( VT_CURRENT_THREAD, &time ); \
598  if( enable_memhooks ) VT_MEMHOOKS_ON(); \
599  errno = preserve_errno; \
600 }
601 
602 /** Use custom values for fid and handle */
603 #define VT_IOWRAP_LEAVE_IOFUNC_CUSTOM(ERROR_CONDITION, FID, HANDLE) \
604 { \
605  int preserve_errno = errno; \
606  uint64_t time = vt_pform_wtime(); \
607  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_LEAVE_IOFUNC(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
608  if( was_recorded ) { \
609  uint32_t ioop = VT_IOWRAP_FUNCTYPE(VT_IOWRAP_THISFUNCNAME); \
610  if( ERROR_CONDITION ) { \
611  ioop |= VT_IOFLAG_IOFAILED; \
612  } \
613  vt_debug_msg(DBG_VT_CALL, "vt_ioend(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)time); \
614  vt_ioend( VT_CURRENT_THREAD, &time, FID, matchingid, HANDLE, ioop, (uint64_t)num_bytes ); \
615  } \
616  vt_exit( VT_CURRENT_THREAD, &time ); \
617  if( enable_memhooks ) VT_MEMHOOKS_ON(); \
618  errno = preserve_errno; \
619 }
620 
621 /**
622  * If open fails, no fd is returned -> use handle=0 in vt_ioend().
623  * Always remember fd->vampir_file mapping if open succeeds.
624  */
625 #define VT_IOWRAP_LEAVE_IOFUNC_OPEN(ERROR_CONDITION,FD) \
626 { \
627  int preserve_errno = errno; \
628  uint64_t time = vt_pform_wtime(); \
629  uint32_t ioop = VT_IOWRAP_FUNCTYPE(VT_IOWRAP_THISFUNCNAME); \
630  uint32_t fid; \
631  vampir_file_t* file; \
632  uint64_t handle; \
633  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_LEAVE_IOFUNC_OPEN(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
634  if( ERROR_CONDITION ) { \
635  if( was_recorded ) { \
636  if( path && strlen(path) > 0 ) { \
637  fid = vt_iofile_id(path); \
638  } \
639  else { \
640  fid = invalid_fd_fid; \
641  } \
642  handle = 0; \
643  ioop |= VT_IOFLAG_IOFAILED; \
644  } \
645  } \
646  else { \
647  vt_iofile_open( path, FD ); \
648  if( was_recorded ) { \
649  file = get_vampir_file( FD ); \
650  fid = file->vampir_file_id; \
651  handle = file->handle; \
652  } \
653  } \
654  if( was_recorded ) { \
655  vt_debug_msg(DBG_VT_CALL, "vt_ioend(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)time); \
656  vt_ioend( VT_CURRENT_THREAD, &time, fid, matchingid, handle, ioop, 0 ); \
657  } \
658  vt_exit( VT_CURRENT_THREAD, &time ); \
659  if( enable_memhooks ) VT_MEMHOOKS_ON(); \
660  errno = preserve_errno; \
661 }
662 
663 /**
664  * Handle is always from the fd that was dup'd
665  */
666 #define VT_IOWRAP_LEAVE_IOFUNC_DUP(ERROR_CONDITION,OLDFD,NEWFD) \
667 { \
668  int preserve_errno = errno; \
669  uint64_t time = vt_pform_wtime(); \
670  uint32_t ioop = VT_IOWRAP_FUNCTYPE(VT_IOWRAP_THISFUNCNAME); \
671  vampir_file_t* file; \
672  uint32_t fid; \
673  uint64_t handle; \
674  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_LEAVE_IOFUNC_DUP(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
675  file = get_vampir_file( OLDFD ); \
676  fid = file->vampir_file_id; \
677  handle = file->handle; \
678  if( ERROR_CONDITION ) { \
679  ioop |= VT_IOFLAG_IOFAILED; \
680  } \
681  else { \
682  vt_iofile_dupfd( OLDFD, NEWFD ); \
683  } \
684  if( was_recorded ) { \
685  vt_debug_msg(DBG_VT_CALL, "vt_ioend(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)time); \
686  vt_ioend( VT_CURRENT_THREAD, &time, fid, matchingid, handle, ioop, (uint64_t)num_bytes ); \
687  } \
688  vt_exit( VT_CURRENT_THREAD, &time ); \
689  if( enable_memhooks ) VT_MEMHOOKS_ON(); \
690  errno = preserve_errno; \
691 }
692 
693 /* Used for I/O functions that work on paths instead of using fd's, e.g. unlink.
694  */
695 #define VT_IOWRAP_LEAVE_IOFUNC_PATH(ERROR_CONDITION,PATH) \
696 { \
697  int preserve_errno = errno; \
698  uint64_t time = vt_pform_wtime(); \
699  vt_debug_msg( DBG_INIT, "Macro VT_IOWRAP_LEAVE_IOFUNC_PATH(), Function " stringify(VT_IOWRAP_THISFUNCNAME) ); \
700  if( was_recorded ) { \
701  uint32_t ioop = VT_IOWRAP_FUNCTYPE(VT_IOWRAP_THISFUNCNAME); \
702  uint32_t fid; \
703  if( ERROR_CONDITION ) { \
704  if( PATH && strlen(PATH) > 0 ) { \
705  fid = vt_iofile_id(PATH); \
706  } \
707  else { \
708  fid = invalid_fd_fid; \
709  } \
710  ioop |= VT_IOFLAG_IOFAILED; \
711  } \
712  else { \
713  fid = vt_iofile_id(PATH); \
714  } \
715  vt_debug_msg(DBG_VT_CALL, "vt_ioend(" stringify(VT_IOWRAP_THISFUNCNAME) "), stamp %llu", (unsigned long long)time); \
716  vt_ioend( VT_CURRENT_THREAD, &time, fid, matchingid, 0, ioop, 0 ); \
717  } \
718  vt_exit( VT_CURRENT_THREAD, &time ); \
719  if( enable_memhooks ) VT_MEMHOOKS_ON(); \
720  errno = preserve_errno; \
721 }
722 
723 #else /* VT_IOWRAP */
724 
725 #define VT_ENABLE_IO_TRACING()
726 #define VT_DISABLE_IO_TRACING()
727 #define VT_SUSPEND_IO_TRACING(tid)
728 #define VT_RESUME_IO_TRACING(tid)
729 
730 #define libc_fprintf fprintf
731 #define vt_iowrap_externals_init()
732 
733 #endif
734 
735 #endif /* _VT_IOWRAP_H_ */
736