[Darshan-commits] [Git][darshan/darshan][master] 57 commits: skeleton stubs for stdio module

Shane Snyder xgitlab at cels.anl.gov
Wed Jul 6 17:51:47 CDT 2016


Shane Snyder pushed to branch master at darshan / darshan


Commits:
78ebc882 by Phil Carns at 2016-04-14T15:42:50-04:00
skeleton stubs for stdio module

- - - - -
8efca566 by Phil Carns at 2016-04-14T17:26:05-04:00
taking note of what functions we may need to catch

- - - - -
ebbe6421 by Phil Carns at 2016-04-19T12:01:32-04:00
initial skeleton for stdio wrapper lib

- move fopen/fopen64 wrappers to stdio module
- make infrastructure for tracking stream pointers based on similar fd
  infrastructure in posix
- define placeholder record structs
- wrappers don't actually do anything yet

- - - - -
db5a2150 by Phil Carns at 2016-04-29T15:20:39-04:00
Merge remote-tracking branch 'origin/master' into dev-stdio

- - - - -
4fd93356 by Phil Carns at 2016-04-29T15:39:07-04:00
add missing file from previous commits

- - - - -
28131252 by Phil Carns at 2016-04-29T17:22:27-04:00
start filling in fopen counters

- - - - -
841429de by Phil Carns at 2016-04-29T17:31:41-04:00
get utils working for stdio module

- - - - -
8d3a2c8a by Phil Carns at 2016-05-01T07:58:33-04:00
Merge remote-tracking branch 'origin/master' into dev-stdio

- - - - -
96247ec9 by Phil Carns at 2016-05-01T07:59:39-04:00
remove old TODO comment

- - - - -
76c86577 by Phil Carns at 2016-05-01T08:20:31-04:00
stub regression test for stdio module

- - - - -
585615f9 by Phil Carns at 2016-05-01T08:30:30-04:00
check more stdio counters in regression

- - - - -
7e58577d by Phil Carns at 2016-05-01T08:34:19-04:00
fopen64 wrapper

- - - - -
29b23f7e by Phil Carns at 2016-05-01T09:00:35-04:00
move fclose wrapper to stdio module

- - - - -
107937f1 by Phil Carns at 2016-05-01T09:03:46-04:00
start tracking which symbols have been captured

- - - - -
7e1b6e91 by Phil Carns at 2016-05-01T09:51:05-04:00
move fwrite wrapper to stdio module

- - - - -
f3b3ba9a by Phil Carns at 2016-05-01T09:56:34-04:00
Merge remote-tracking branch 'origin/master' into dev-stdio

- - - - -
25833864 by Phil Carns at 2016-05-01T09:57:11-04:00
remove old reminder comment

- - - - -
da685755 by Phil Carns at 2016-05-01T10:21:19-04:00
move fread wrapper to stdio module

- - - - -
91092ee1 by Phil Carns at 2016-05-01T10:32:14-04:00
move fseek wrapper to stdio module

- - - - -
af624bef by Phil Carns at 2016-05-01T10:39:58-04:00
misc code cleanups and notes

- - - - -
9a13bcc0 by Phil Carns at 2016-05-18T17:15:35-05:00
comments

- - - - -
11c80b44 by Phil Carns at 2016-05-18T17:17:52-05:00
move comments

- - - - -
9930d72a by Phil Carns at 2016-05-23T20:38:32-04:00
fdopen wrapper

- - - - -
e025a97f by Phil Carns at 2016-05-23T20:42:01-04:00
freopen wrapper

- - - - -
9781671b by Phil Carns at 2016-05-23T20:50:05-04:00
fflush wrapper

- - - - -
4cdf8a06 by Phil Carns at 2016-05-23T20:53:18-04:00
fgetc wrapper

- - - - -
da08451f by Phil Carns at 2016-05-23T20:57:07-04:00
fgets wrapper

- - - - -
9e6663d9 by Phil Carns at 2016-05-23T21:13:46-04:00
fscanf and vfscanf wrappers

- needs testing

- - - - -
551c339c by Phil Carns at 2016-05-23T21:18:51-04:00
getc wrapper

- - - - -
05a68fd0 by Phil Carns at 2016-05-23T21:23:11-04:00
skip the unlocked functions

- - - - -
d4fc0944 by Phil Carns at 2016-05-23T21:26:48-04:00
getw wrapper

- - - - -
c2a08740 by Phil Carns at 2016-05-23T22:37:10-04:00
fprintf wrapper

- - - - -
09926b48 by Phil Carns at 2016-05-23T22:51:39-04:00
fputc wrapper

- - - - -
3b4bef1d by Phil Carns at 2016-05-23T22:54:37-04:00
fputs wrapper

- - - - -
d094097c by Phil Carns at 2016-05-23T22:57:57-04:00
putc wrapper

- - - - -
29641b6a by Phil Carns at 2016-05-23T23:00:21-04:00
putw wrapper

- - - - -
9697f099 by Phil Carns at 2016-05-23T23:03:11-04:00
fseeko wrapper

- - - - -
6c43ebe8 by Phil Carns at 2016-05-23T23:05:21-04:00
add missing 64 bit variants

- - - - -
0461e398 by Phil Carns at 2016-05-23T23:18:54-04:00
freopen64 wrapper

- - - - -
93a0e7a1 by Phil Carns at 2016-05-23T23:20:13-04:00
fseeko64 wrapper

- - - - -
0289d4ab by Phil Carns at 2016-05-23T23:24:12-04:00
fsetpos and fsetpos64 wrappers

- - - - -
904b6dbc by Phil Carns at 2016-05-23T23:26:29-04:00
rewind wrapper

- - - - -
4b1dcbb5 by Phil Carns at 2016-05-23T23:27:48-04:00
on second thought, let's not mess with ungetc

- - - - -
5fd3c5c1 by Phil Carns at 2016-05-23T23:28:46-04:00
update comments

- - - - -
3d7cc3c6 by Phil Carns at 2016-05-24T16:54:43-04:00
implement shared reduction for stdio records

- - - - -
106767d3 by Phil Carns at 2016-05-24T17:30:40-04:00
update test case to account for shared reduction

- - - - -
9cd5e5c0 by Phil Carns at 2016-05-27T17:16:33-04:00
get fscanf working

- includes regression test for fprintf and fscanf
- apparently you have to wrap __isoc99_fscanf instead of fscanf
  sometimes

- - - - -
1a67e237 by Phil Carns at 2016-06-22T14:53:53-04:00
Merge remote-tracking branch 'origin/master' into dev-stdio

- note: darshan-stdio module updates are still needed; this merge just
  updates the rest of the code and resolves conflicts

- - - - -
ad6ea64f by Phil Carns at 2016-06-23T17:33:59-04:00
convert stdio module to use new apis

- eliminated 110 SLOC
- untested

- - - - -
af5dfe77 by Phil Carns at 2016-06-24T12:44:27-04:00
update stdio module logutils to match new apis

- - - - -
9d18599a by Phil Carns at 2016-06-24T12:51:40-04:00
typo

- - - - -
112b403f by Phil Carns at 2016-06-24T13:00:15-04:00
bug fix, transposed arguments to mod register

- - - - -
8bb4890f by Phil Carns at 2016-06-24T13:15:28-04:00
cleanup sizeof calls

- - - - -
ebb9ba17 by Phil Carns at 2016-06-24T13:32:37-04:00
fix another sizeof bug

- - - - -
06b84605 by Phil Carns at 2016-06-30T15:05:31-04:00
comment update

- - - - -
5c5f5334 by Shane Snyder at 2016-07-06T13:12:32-05:00
Merge branch 'dev-stdio'

Conflicts:
	darshan-log-format.h
	darshan-runtime/Makefile.in
	darshan-util/Makefile.in
	darshan-util/darshan-logutils.h

- - - - -
5c5e4452 by Shane Snyder at 2016-07-06T13:15:33-05:00
fix prototypes for a few stdio funcs

- - - - -


20 changed files:

- darshan-log-format.h
- darshan-runtime/Makefile.in
- darshan-runtime/configure
- darshan-runtime/darshan-runtime-config.h.in
- darshan-runtime/lib/darshan-posix.c
- + darshan-runtime/lib/darshan-stdio.c
- darshan-runtime/share/ld-opts/darshan-base-ld-opts.in
- darshan-runtime/share/ld-opts/darshan-posix-ld-opts
- + darshan-runtime/share/ld-opts/darshan-stdio-ld-opts
- + darshan-stdio-log-format.h
- + darshan-test/regression/test-cases/fprintf-fscanf-test.sh
- + darshan-test/regression/test-cases/src/fprintf-fscanf-test.c
- + darshan-test/regression/test-cases/src/stdio-test.c
- + darshan-test/regression/test-cases/stdio-test.sh
- darshan-util/Makefile.in
- darshan-util/configure
- darshan-util/darshan-logutils.h
- + darshan-util/darshan-stdio-logutils.c
- + darshan-util/darshan-stdio-logutils.h
- darshan-util/darshan-util-config.h.in


Changes:

=====================================
darshan-log-format.h
=====================================
--- a/darshan-log-format.h
+++ b/darshan-log-format.h
@@ -112,6 +112,7 @@ struct darshan_base_record
 #include "darshan-pnetcdf-log-format.h"
 #include "darshan-bgq-log-format.h"
 #include "darshan-lustre-log-format.h"
+#include "darshan-stdio-log-format.h"
 
 /* X-macro for keeping module ordering consistent */
 /* NOTE: first val used to define module enum values, 
@@ -130,7 +131,8 @@ struct darshan_base_record
     X(DARSHAN_HDF5_MOD,     "HDF5",     DARSHAN_HDF5_VER,       &hdf5_logutils) \
     X(DARSHAN_PNETCDF_MOD,  "PNETCDF",  DARSHAN_PNETCDF_VER,    &pnetcdf_logutils) \
     X(DARSHAN_BGQ_MOD,      "BG/Q",     DARSHAN_BGQ_VER,        &bgq_logutils) \
-    X(DARSHAN_LUSTRE_MOD,   "LUSTRE",   DARSHAN_LUSTRE_VER,     &lustre_logutils)
+    X(DARSHAN_LUSTRE_MOD,   "LUSTRE",   DARSHAN_LUSTRE_VER,     &lustre_logutils) \
+    X(DARSHAN_STDIO_MOD,    "STDIO",    DARSHAN_STDIO_VER,      &stdio_logutils)
 
 /* unique identifiers to distinguish between available darshan modules */
 /* NOTES: - valid ids range from [0...DARSHAN_MAX_MODS-1]


=====================================
darshan-runtime/Makefile.in
=====================================
--- a/darshan-runtime/Makefile.in
+++ b/darshan-runtime/Makefile.in
@@ -35,8 +35,8 @@ CFLAGS_SHARED = -DDARSHAN_CONFIG_H=\"darshan-runtime-config.h\" -I . -I$(srcdir)
 
 LIBS = -lz @LIBBZ2@
 
-DARSHAN_STATIC_MOD_OBJS = lib/darshan-posix.o lib/darshan-mpiio.o lib/darshan-hdf5.o lib/darshan-pnetcdf.o
-DARSHAN_DYNAMIC_MOD_OBJS = lib/darshan-posix.po lib/darshan-mpiio.po lib/darshan-hdf5.po lib/darshan-pnetcdf.po
+DARSHAN_STATIC_MOD_OBJS = lib/darshan-posix.o lib/darshan-mpiio.o lib/darshan-hdf5.o lib/darshan-pnetcdf.o lib/darshan-stdio.o
+DARSHAN_DYNAMIC_MOD_OBJS = lib/darshan-posix.po lib/darshan-mpiio.po lib/darshan-hdf5.po lib/darshan-pnetcdf.po lib/darshan-stdio.po
 
 ifdef DARSHAN_USE_BGQ
 DARSHAN_STATIC_MOD_OBJS += lib/darshan-bgq.o
@@ -121,6 +121,12 @@ lib/darshan-lustre.o: lib/darshan-lustre.c darshan-lustre.h darshan.h darshan-co
 lib/darshan-lustre.po: lib/darshan-lustre.c darshan-lustre.h darshan.h darshan-dynamic.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-lustre-log-format.h | lib
 	$(CC) $(CFLAGS_SHARED) -c $< -o $@
 
+lib/darshan-stdio.o: lib/darshan-stdio.c darshan.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | lib
+	$(CC) $(CFLAGS) -c $< -o $@
+
+lib/darshan-stdio.po: lib/darshan-stdio.c darshan.h darshan-dynamic.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | lib
+	$(CC) $(CFLAGS_SHARED) -c $< -o $@
+
 lib/lookup3.o: lib/lookup3.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
@@ -172,6 +178,7 @@ endif
 	install -m 644 $(srcdir)/share/ld-opts/darshan-posix-ld-opts $(datarootdir)/ld-opts/darshan-posix-ld-opts
 	install -m 644 $(srcdir)/share/ld-opts/darshan-hdf5-ld-opts $(datarootdir)/ld-opts/darshan-hdf5-ld-opts
 	install -m 644 $(srcdir)/share/ld-opts/darshan-pnetcdf-ld-opts $(datarootdir)/ld-opts/darshan-pnetcdf-ld-opts
+	install -m 644 $(srcdir)/share/ld-opts/darshan-stdio-ld-opts $(datarootdir)/ld-opts/darshan-stdio-ld-opts
 ifdef ENABLE_MMAP_LOGS
 	install -m 755 share/darshan-mmap-epilog.sh $(datarootdir)/darshan-mmap-epilog.sh
 endif


=====================================
darshan-runtime/configure
=====================================
The diff for this file was not included because it is too large.

=====================================
darshan-runtime/darshan-runtime-config.h.in
=====================================
--- a/darshan-runtime/darshan-runtime-config.h.in
+++ b/darshan-runtime/darshan-runtime-config.h.in
@@ -60,6 +60,9 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 


=====================================
darshan-runtime/lib/darshan-posix.c
=====================================
--- a/darshan-runtime/lib/darshan-posix.c
+++ b/darshan-runtime/lib/darshan-posix.c
@@ -45,8 +45,6 @@ DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
 DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
 DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
 DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
-DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
-DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
 DARSHAN_FORWARD_DECL(mkstemp, int, (char *template));
 DARSHAN_FORWARD_DECL(mkostemp, int, (char *template, int flags));
 DARSHAN_FORWARD_DECL(mkstemps, int, (char *template, int suffixlen));
@@ -59,11 +57,8 @@ DARSHAN_FORWARD_DECL(pread64, ssize_t, (int fd, void *buf, size_t count, off64_t
 DARSHAN_FORWARD_DECL(pwrite64, ssize_t, (int fd, const void *buf, size_t count, off64_t offset));
 DARSHAN_FORWARD_DECL(readv, ssize_t, (int fd, const struct iovec *iov, int iovcnt));
 DARSHAN_FORWARD_DECL(writev, ssize_t, (int fd, const struct iovec *iov, int iovcnt));
-DARSHAN_FORWARD_DECL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
-DARSHAN_FORWARD_DECL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
 DARSHAN_FORWARD_DECL(lseek, off_t, (int fd, off_t offset, int whence));
 DARSHAN_FORWARD_DECL(lseek64, off64_t, (int fd, off64_t offset, int whence));
-DARSHAN_FORWARD_DECL(fseek, int, (FILE *stream, long offset, int whence));
 DARSHAN_FORWARD_DECL(__xstat, int, (int vers, const char* path, struct stat *buf));
 DARSHAN_FORWARD_DECL(__xstat64, int, (int vers, const char* path, struct stat64 *buf));
 DARSHAN_FORWARD_DECL(__lxstat, int, (int vers, const char* path, struct stat *buf));
@@ -75,7 +70,6 @@ DARSHAN_FORWARD_DECL(mmap64, void*, (void *addr, size_t length, int prot, int fl
 DARSHAN_FORWARD_DECL(fsync, int, (int fd));
 DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
 DARSHAN_FORWARD_DECL(close, int, (int fd));
-DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
 DARSHAN_FORWARD_DECL(aio_read, int, (struct aiocb *aiocbp));
 DARSHAN_FORWARD_DECL(aio_write, int, (struct aiocb *aiocbp));
 DARSHAN_FORWARD_DECL(aio_read64, int, (struct aiocb64 *aiocbp));
@@ -197,7 +191,7 @@ static int darshan_mem_alignment = 1;
     POSIX_UNLOCK(); \
 } while(0)
 
-#define POSIX_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
+#define POSIX_RECORD_OPEN(__ret, __path, __mode, __tm1, __tm2) do { \
     darshan_record_id rec_id; \
     struct posix_file_record_ref *rec_ref; \
     char *newpath; \
@@ -220,10 +214,7 @@ static int darshan_mem_alignment = 1;
     rec_ref->offset = 0; \
     rec_ref->last_byte_written = 0; \
     rec_ref->last_byte_read = 0; \
-    if(__stream_flag)\
-        rec_ref->file_rec->counters[POSIX_FOPENS] += 1; \
-    else \
-        rec_ref->file_rec->counters[POSIX_OPENS] += 1; \
+    rec_ref->file_rec->counters[POSIX_OPENS] += 1; \
     if(rec_ref->file_rec->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0 || \
      rec_ref->file_rec->fcounters[POSIX_F_OPEN_TIMESTAMP] > __tm1) \
         rec_ref->file_rec->fcounters[POSIX_F_OPEN_TIMESTAMP] = __tm1; \
@@ -234,7 +225,7 @@ static int darshan_mem_alignment = 1;
     if(newpath != __path) free(newpath); \
 } while(0)
 
-#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do { \
+#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __tm1, __tm2) do { \
     struct posix_file_record_ref* rec_ref; \
     size_t stride; \
     int64_t this_offset; \
@@ -261,10 +252,7 @@ static int darshan_mem_alignment = 1;
     if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] < (this_offset + __ret - 1)) \
         rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] = (this_offset + __ret - 1); \
     rec_ref->file_rec->counters[POSIX_BYTES_READ] += __ret; \
-    if(__stream_flag) \
-        rec_ref->file_rec->counters[POSIX_FREADS] += 1; \
-    else \
-        rec_ref->file_rec->counters[POSIX_READS] += 1; \
+    rec_ref->file_rec->counters[POSIX_READS] += 1; \
     DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_READ_0_100]), __ret); \
     darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
         &(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
@@ -291,7 +279,7 @@ static int darshan_mem_alignment = 1;
         __tm1, __tm2, rec_ref->last_read_end); \
 } while(0)
 
-#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do { \
+#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __tm1, __tm2) do { \
     struct posix_file_record_ref* rec_ref; \
     size_t stride; \
     int64_t this_offset; \
@@ -318,10 +306,7 @@ static int darshan_mem_alignment = 1;
     if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] < (this_offset + __ret - 1)) \
         rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] = (this_offset + __ret - 1); \
     rec_ref->file_rec->counters[POSIX_BYTES_WRITTEN] += __ret; \
-    if(__stream_flag) \
-        rec_ref->file_rec->counters[POSIX_FWRITES] += 1; \
-    else \
-        rec_ref->file_rec->counters[POSIX_WRITES] += 1; \
+    rec_ref->file_rec->counters[POSIX_WRITES] += 1; \
     DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_WRITE_0_100]), __ret); \
     darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
         &(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
@@ -404,7 +389,7 @@ int DARSHAN_DECL(open)(const char *path, int flags, ...)
     }
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -437,7 +422,7 @@ int DARSHAN_DECL(open64)(const char *path, int flags, ...)
     }
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -455,7 +440,7 @@ int DARSHAN_DECL(creat)(const char* path, mode_t mode)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -473,55 +458,7 @@ int DARSHAN_DECL(creat64)(const char* path, mode_t mode)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
-    POSIX_POST_RECORD();
-
-    return(ret);
-}
-
-FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
-{
-    FILE* ret;
-    int fd;
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fopen);
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fopen(path, mode);
-    tm2 = darshan_core_wtime();
-
-    if(ret == NULL)
-        fd = -1;
-    else
-        fd = fileno(ret);
-
-    POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
-    POSIX_POST_RECORD();
-
-    return(ret);
-}
-
-FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
-{
-    FILE* ret;
-    int fd;
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fopen64);
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fopen64(path, mode);
-    tm2 = darshan_core_wtime();
-
-    if(ret == NULL)
-        fd = -1;
-    else
-        fd = fileno(ret);
-
-    POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -539,7 +476,7 @@ int DARSHAN_DECL(mkstemp)(char* template)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -557,7 +494,7 @@ int DARSHAN_DECL(mkostemp)(char* template, int flags)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -575,7 +512,7 @@ int DARSHAN_DECL(mkstemps)(char* template, int suffixlen)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -593,7 +530,7 @@ int DARSHAN_DECL(mkostemps)(char* template, int suffixlen, int flags)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
+    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -614,7 +551,7 @@ ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -635,7 +572,7 @@ ssize_t DARSHAN_DECL(write)(int fd, const void *buf, size_t count)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -656,7 +593,7 @@ ssize_t DARSHAN_DECL(pread)(int fd, void *buf, size_t count, off_t offset)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -677,7 +614,7 @@ ssize_t DARSHAN_DECL(pwrite)(int fd, const void *buf, size_t count, off_t offset
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -698,7 +635,7 @@ ssize_t DARSHAN_DECL(pread64)(int fd, void *buf, size_t count, off64_t offset)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -719,7 +656,7 @@ ssize_t DARSHAN_DECL(pwrite64)(int fd, const void *buf, size_t count, off64_t of
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -745,7 +682,7 @@ ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
+    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -771,67 +708,7 @@ ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
     tm2 = darshan_core_wtime();
 
     POSIX_PRE_RECORD();
-    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
-    POSIX_POST_RECORD();
-
-    return(ret);
-}
-
-size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-    size_t ret;
-    int aligned_flag = 0;
-    int fd;
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fread);
-
-    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fread(ptr, size, nmemb, stream);
-    tm2 = darshan_core_wtime();
-
-    fd = fileno(stream);
-    POSIX_PRE_RECORD();
-    if(ret > 0)
-    {
-        POSIX_RECORD_READ(size*ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
-    }
-    else
-    {
-        POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
-    }
-    POSIX_POST_RECORD();
-
-    return(ret);
-}
-
-size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-    size_t ret;
-    int aligned_flag = 0;
-    int fd;
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fwrite);
-
-    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fwrite(ptr, size, nmemb, stream);
-    tm2 = darshan_core_wtime();
-
-    fd = fileno(stream);
-    POSIX_PRE_RECORD();
-    if(ret > 0)
-    {
-        POSIX_RECORD_WRITE(size*ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
-    }
-    else
-    {
-        POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
-    }
+    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
     POSIX_POST_RECORD();
 
     return(ret);
@@ -897,38 +774,6 @@ off_t DARSHAN_DECL(lseek64)(int fd, off_t offset, int whence)
     return(ret);
 }
 
-int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
-{
-    int ret;
-    struct posix_file_record_ref *rec_ref;
-    int fd;
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fseek);
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fseek(stream, offset, whence);
-    tm2 = darshan_core_wtime();
-
-    if(ret >= 0)
-    {
-        POSIX_PRE_RECORD();
-        fd = fileno(stream);
-        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
-        if(rec_ref)
-        {
-            rec_ref->offset = ftell(stream);
-            DARSHAN_TIMER_INC_NO_OVERLAP(
-                rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
-                tm1, tm2, rec_ref->last_meta_end);
-            rec_ref->file_rec->counters[POSIX_FSEEKS] += 1;
-        }
-        POSIX_POST_RECORD();
-    }
-
-    return(ret);
-}
-
 int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
 {
     int ret;
@@ -1199,37 +1044,6 @@ int DARSHAN_DECL(close)(int fd)
     return(ret);
 }
 
-int DARSHAN_DECL(fclose)(FILE *fp)
-{
-    int ret;
-    struct posix_file_record_ref *rec_ref;
-    int fd = fileno(fp);
-    double tm1, tm2;
-
-    MAP_OR_FAIL(fclose);
-
-    tm1 = darshan_core_wtime();
-    ret = __real_fclose(fp);
-    tm2 = darshan_core_wtime();
-
-    POSIX_PRE_RECORD();
-    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
-    if(rec_ref)
-    {
-        rec_ref->last_byte_written = 0;
-        rec_ref->last_byte_read = 0;
-        rec_ref->file_rec->fcounters[POSIX_F_CLOSE_TIMESTAMP] =
-            darshan_core_wtime();
-        DARSHAN_TIMER_INC_NO_OVERLAP(
-            rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
-            tm1, tm2, rec_ref->last_meta_end);
-        darshan_delete_record_ref(&(posix_runtime->fd_hash), &fd, sizeof(int));
-    }
-    POSIX_POST_RECORD();
-
-    return(ret);
-}
-
 int DARSHAN_DECL(aio_read)(struct aiocb *aiocbp)
 {
     int ret;
@@ -1319,13 +1133,13 @@ ssize_t DARSHAN_DECL(aio_return)(struct aiocb *aiocbp)
         if(aiocbp->aio_lio_opcode == LIO_WRITE)
         {
             POSIX_RECORD_WRITE(ret, aiocbp->aio_fildes,
-                1, aiocbp->aio_offset, aligned_flag, 0,
+                1, aiocbp->aio_offset, aligned_flag,
                 tmp->tm1, tm2);
         }
         else if(aiocbp->aio_lio_opcode == LIO_READ)
         {
             POSIX_RECORD_READ(ret, aiocbp->aio_fildes,
-                1, aiocbp->aio_offset, aligned_flag, 0,
+                1, aiocbp->aio_offset, aligned_flag,
                 tmp->tm1, tm2);
         }
         free(tmp);
@@ -1356,13 +1170,13 @@ ssize_t DARSHAN_DECL(aio_return64)(struct aiocb64 *aiocbp)
         if(aiocbp->aio_lio_opcode == LIO_WRITE)
         {
             POSIX_RECORD_WRITE(ret, aiocbp->aio_fildes,
-                1, aiocbp->aio_offset, aligned_flag, 0,
+                1, aiocbp->aio_offset, aligned_flag,
                 tmp->tm1, tm2);
         }
         else if(aiocbp->aio_lio_opcode == LIO_READ)
         {
             POSIX_RECORD_READ(ret, aiocbp->aio_fildes,
-                1, aiocbp->aio_offset, aligned_flag, 0,
+                1, aiocbp->aio_offset, aligned_flag,
                 tmp->tm1, tm2);
         }
         free(tmp);
@@ -1927,15 +1741,15 @@ void darshan_posix_shutdown_bench_setup(int test_case)
         case 1: /* single file-per-process */
             snprintf(filepath, 256, "fpp-0_rank-%d", my_rank);
             
-            POSIX_RECORD_OPEN(fd_array[0], filepath, 777, 0, 0, 1);
-            POSIX_RECORD_WRITE(size_array[0], fd_array[0], 0, 0, 1, 0, 1, 2);
+            POSIX_RECORD_OPEN(fd_array[0], filepath, 777, 0, 1);
+            POSIX_RECORD_WRITE(size_array[0], fd_array[0], 0, 0, 1, 1, 2);
 
             break;
         case 2: /* single shared file */
             snprintf(filepath, 256, "shared-0");
 
-            POSIX_RECORD_OPEN(fd_array[0], filepath, 777, 0, 0, 1);
-            POSIX_RECORD_WRITE(size_array[0], fd_array[0], 0, 0, 1, 0, 1, 2);
+            POSIX_RECORD_OPEN(fd_array[0], filepath, 777, 0, 1);
+            POSIX_RECORD_WRITE(size_array[0], fd_array[0], 0, 0, 1, 1, 2);
 
             break;
         case 3: /* 1024 unique files per proc */
@@ -1943,9 +1757,9 @@ void darshan_posix_shutdown_bench_setup(int test_case)
             {
                 snprintf(filepath, 256, "fpp-%d_rank-%d", i , my_rank);
 
-                POSIX_RECORD_OPEN(fd_array[i], filepath, 777, 0, 0, 1);
+                POSIX_RECORD_OPEN(fd_array[i], filepath, 777, 0, 1);
                 POSIX_RECORD_WRITE(size_array[i % DARSHAN_COMMON_VAL_MAX_RUNTIME_COUNT],
-                    fd_array[i], 0, 0, 1, 0, 1, 2);
+                    fd_array[i], 0, 0, 1, 1, 2);
             }
 
             break;
@@ -1954,9 +1768,9 @@ void darshan_posix_shutdown_bench_setup(int test_case)
             {
                 snprintf(filepath, 256, "shared-%d", i);
 
-                POSIX_RECORD_OPEN(fd_array[i], filepath, 777, 0, 0, 1);
+                POSIX_RECORD_OPEN(fd_array[i], filepath, 777, 0, 1);
                 POSIX_RECORD_WRITE(size_array[i % DARSHAN_COMMON_VAL_MAX_RUNTIME_COUNT],
-                    fd_array[i], 0, 0, 1, 0, 1, 2);
+                    fd_array[i], 0, 0, 1, 1, 2);
             }
 
             break;


=====================================
darshan-runtime/lib/darshan-stdio.c
=====================================
--- /dev/null
+++ b/darshan-runtime/lib/darshan-stdio.c
@@ -0,0 +1,1185 @@
+/*
+ * Copyright (C) 2015 University of Chicago.
+ * See COPYRIGHT notice in top-level directory.
+ *
+ */
+
+/* TODO list (general) for this module:
+ * - add stdio page to darshan-job-summary
+ * - update darshan-parser to include stdio information in any relevant 
+ *   performance estimate / summary modes
+ * - figure out what to do about posix module compatibility
+ *   - remove stdio counters in POSIX or keep and set to -1?
+ *   - affected counters in posix module:
+ *     - POSIX_FOPENS
+ *     - POSIX_FREADS
+ *     - POSIX_FWRITES
+ *     - POSIX_FSEEKS
+ */
+
+/* catalog of stdio functions instrumented by this module
+ *
+ * functions for opening streams
+ * --------------
+ * FILE    *fdopen(int, const char *);                      DONE
+ * FILE    *fopen(const char *, const char *);              DONE
+ * FILE    *fopen64(const char *, const char *);            DONE
+ * FILE    *freopen(const char *, const char *, FILE *);    DONE
+ * FILE    *freopen64(const char *, const char *, FILE *);  DONE
+ *
+ * functions for closing streams
+ * --------------
+ * int      fclose(FILE *);                                 DONE
+ *
+ * functions for flushing streams
+ * --------------
+ * int      fflush(FILE *);                                 DONE
+ *
+ * functions for reading data
+ * --------------
+ * int      fgetc(FILE *);                                  DONE
+ * char    *fgets(char *, int, FILE *);                     DONE
+ * size_t   fread(void *, size_t, size_t, FILE *);          DONE
+ * int      fscanf(FILE *, const char *, ...);              DONE
+ * int      vfscanf(FILE *, const char *, va_list);         DONE
+ * int      getc(FILE *);                                   DONE
+ * int      getw(FILE *);                                   DONE
+ *
+ * functions for writing data
+ * --------------
+ * int      fprintf(FILE *, const char *, ...);             DONE
+ * int      vfprintf(FILE *, const char *, va_list);        DONE
+ * int      fputc(int, FILE *);                             DONE
+ * int      fputs(const char *, FILE *);                    DONE
+ * size_t   fwrite(const void *, size_t, size_t, FILE *);   DONE
+ * int      putc(int, FILE *);                              DONE
+ * int      putw(int, FILE *);                              DONE
+ *
+ * functions for changing file position
+ * --------------
+ * int      fseek(FILE *, long int, int);                   DONE
+ * int      fseeko(FILE *, off_t, int);                     DONE
+ * int      fseeko64(FILE *, off_t, int);                   DONE
+ * int      fsetpos(FILE *, const fpos_t *);                DONE
+ * int      fsetpos64(FILE *, const fpos_t *);              DONE
+ * void     rewind(FILE *);                                 DONE
+ *
+ * Omissions: 
+ *   - _unlocked() variants of the various flush, read, and write
+ *     functions.  There are many of these, but they are not available on all
+ *     systems and the man page advises not to use them.
+ *   - ungetc()
+ */
+
+#define _XOPEN_SOURCE 500
+#define _GNU_SOURCE
+
+#include "darshan-runtime-config.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <search.h>
+#include <assert.h>
+#include <libgen.h>
+#include <pthread.h>
+
+#include "darshan.h"
+#include "darshan-dynamic.h"
+
+DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
+DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
+DARSHAN_FORWARD_DECL(fdopen, FILE*, (int fd, const char *mode));
+DARSHAN_FORWARD_DECL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
+DARSHAN_FORWARD_DECL(freopen64, FILE*, (const char *path, const char *mode, FILE *stream));
+DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
+DARSHAN_FORWARD_DECL(fflush, int, (FILE *fp));
+DARSHAN_FORWARD_DECL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
+DARSHAN_FORWARD_DECL(fputc, int, (int c, FILE *stream));
+DARSHAN_FORWARD_DECL(putw, int, (int w, FILE *stream));
+DARSHAN_FORWARD_DECL(fputs, int, (const char *s, FILE *stream));
+DARSHAN_FORWARD_DECL(fprintf, int, (FILE *stream, const char *format, ...));
+DARSHAN_FORWARD_DECL(vfprintf, int, (FILE *stream, const char *format, va_list));
+DARSHAN_FORWARD_DECL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
+DARSHAN_FORWARD_DECL(fgetc, int, (FILE *stream));
+DARSHAN_FORWARD_DECL(getw, int, (FILE *stream));
+DARSHAN_FORWARD_DECL(_IO_getc, int, (FILE *stream));
+DARSHAN_FORWARD_DECL(_IO_putc, int, (int, FILE *stream));
+DARSHAN_FORWARD_DECL(fscanf, int, (FILE *stream, const char *format, ...));
+DARSHAN_FORWARD_DECL(__isoc99_fscanf, int, (FILE *stream, const char *format, ...));
+DARSHAN_FORWARD_DECL(vfscanf, int, (FILE *stream, const char *format, va_list ap));
+DARSHAN_FORWARD_DECL(fgets, char*, (char *s, int size, FILE *stream));
+DARSHAN_FORWARD_DECL(fseek, int, (FILE *stream, long offset, int whence));
+DARSHAN_FORWARD_DECL(fseeko, int, (FILE *stream, off_t offset, int whence));
+DARSHAN_FORWARD_DECL(fseeko64, int, (FILE *stream, off_t offset, int whence));
+DARSHAN_FORWARD_DECL(fsetpos, int, (FILE *stream, const fpos_t *pos));
+DARSHAN_FORWARD_DECL(fsetpos64, int, (FILE *stream, const fpos64_t *pos));
+DARSHAN_FORWARD_DECL(rewind, void, (FILE *stream));
+
+/* structure to track stdio stats at runtime */
+struct stdio_file_record_ref
+{
+    struct darshan_stdio_file* file_rec;
+    int64_t offset;
+    double last_meta_end;
+    double last_read_end;
+    double last_write_end;
+};
+
+/* The stdio_runtime structure maintains necessary state for storing
+ * STDIO file records and for coordinating with darshan-core at 
+ * shutdown time.
+ */
+struct stdio_runtime
+{
+    void *rec_id_hash;
+    void *stream_hash;
+    int file_rec_count;
+};
+
+static struct stdio_runtime *stdio_runtime = NULL;
+static pthread_mutex_t stdio_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static int instrumentation_disabled = 0;
+static int darshan_mem_alignment = 1;
+static int my_rank = -1;
+
+static void stdio_runtime_initialize(void);
+static void stdio_shutdown(
+    MPI_Comm mod_comm,
+    darshan_record_id *shared_recs,
+    int shared_rec_count,
+    void **stdio_buf,
+    int *stdio_buf_sz);
+static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
+    int *len, MPI_Datatype *datatype);
+static struct stdio_file_record_ref *stdio_track_new_file_record(
+    darshan_record_id rec_id, const char *path);
+static void stdio_cleanup_runtime();
+
+#define STDIO_LOCK() pthread_mutex_lock(&stdio_runtime_mutex)
+#define STDIO_UNLOCK() pthread_mutex_unlock(&stdio_runtime_mutex)
+
+#define STDIO_PRE_RECORD() do { \
+    STDIO_LOCK(); \
+    if(!stdio_runtime && !instrumentation_disabled) stdio_runtime_initialize(); \
+    if(!stdio_runtime) { \
+        STDIO_UNLOCK(); \
+        return(ret); \
+    } \
+} while(0)
+
+#define STDIO_POST_RECORD() do { \
+    STDIO_UNLOCK(); \
+} while(0)
+
+#define STDIO_RECORD_OPEN(__ret, __path, __tm1, __tm2) do { \
+    darshan_record_id rec_id; \
+    struct stdio_file_record_ref* rec_ref; \
+    char *newpath; \
+    if(__ret == NULL) break; \
+    newpath = darshan_clean_file_path(__path); \
+    if(!newpath) newpath = (char*)__path; \
+    if(darshan_core_excluded_path(newpath)) { \
+        if(newpath != (char*)__path) free(newpath); \
+        break; \
+    } \
+    rec_id = darshan_core_gen_record_id(newpath); \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash, &rec_id, sizeof(rec_id)); \
+    if(!rec_ref) rec_ref = stdio_track_new_file_record(rec_id, newpath); \
+    if(!rec_ref) { \
+        if(newpath != (char*)__path) free(newpath); \
+        break; \
+    } \
+    rec_ref->offset = 0; \
+    rec_ref->file_rec->counters[STDIO_OPENS] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_OPEN_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_META_TIME], __tm1, __tm2, rec_ref->last_meta_end); \
+    darshan_add_record_ref(&(stdio_runtime->stream_hash), &(__ret), sizeof(__ret), rec_ref); \
+    if(newpath != (char*)__path) free(newpath); \
+} while(0)
+
+
+#define STDIO_RECORD_READ(__fp, __bytes,  __tm1, __tm2) do{ \
+    struct stdio_file_record_ref* rec_ref; \
+    int64_t this_offset; \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
+    if(!rec_ref) break; \
+    this_offset = rec_ref->offset; \
+    rec_ref->offset = this_offset + __bytes; \
+    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] < (this_offset + __bytes - 1)) \
+        rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] = (this_offset + __bytes - 1); \
+    rec_ref->file_rec->counters[STDIO_BYTES_READ] += __bytes; \
+    rec_ref->file_rec->counters[STDIO_READS] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_READ_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_READ_TIME], __tm1, __tm2, rec_ref->last_write_end); \
+} while(0)
+
+#define STDIO_RECORD_WRITE(__fp, __bytes,  __tm1, __tm2, __fflush_flag) do{ \
+    struct stdio_file_record_ref* rec_ref; \
+    int64_t this_offset; \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
+    if(!rec_ref) break; \
+    this_offset = rec_ref->offset; \
+    rec_ref->offset = this_offset + __bytes; \
+    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] < (this_offset + __bytes - 1)) \
+        rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] = (this_offset + __bytes - 1); \
+    rec_ref->file_rec->counters[STDIO_BYTES_WRITTEN] += __bytes; \
+    if(__fflush_flag) \
+        rec_ref->file_rec->counters[STDIO_FLUSHES] += 1; \
+    else \
+        rec_ref->file_rec->counters[STDIO_WRITES] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_WRITE_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_WRITE_TIME], __tm1, __tm2, rec_ref->last_write_end); \
+} while(0)
+
+FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
+{
+    FILE* ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fopen);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fopen(path, mode);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
+{
+    FILE* ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fopen);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fopen64(path, mode);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+FILE* DARSHAN_DECL(fdopen)(int fd, const char *mode)
+{
+    FILE* ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fdopen);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fdopen(fd, mode);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    STDIO_RECORD_OPEN(ret, "UNKNOWN-FDOPEN", tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+FILE* DARSHAN_DECL(freopen)(const char *path, const char *mode, FILE *stream)
+{
+    FILE* ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(freopen);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_freopen(path, mode, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+FILE* DARSHAN_DECL(freopen64)(const char *path, const char *mode, FILE *stream)
+{
+    FILE* ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(freopen64);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_freopen64(path, mode, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+int DARSHAN_DECL(fflush)(FILE *fp)
+{
+    double tm1, tm2;
+    int ret;
+
+    MAP_OR_FAIL(fflush);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fflush(fp);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret >= 0)
+        STDIO_RECORD_WRITE(fp, 0, tm1, tm2, 1);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fclose)(FILE *fp)
+{
+    double tm1, tm2;
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+
+    MAP_OR_FAIL(fclose);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fclose(fp);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &fp, sizeof(fp));
+    if(rec_ref)
+    {
+        if(rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] == 0 ||
+         rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] > tm1)
+           rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] = tm1;
+        rec_ref->file_rec->fcounters[STDIO_F_CLOSE_END_TIMESTAMP] = tm2;
+        DARSHAN_TIMER_INC_NO_OVERLAP(
+            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+            tm1, tm2, rec_ref->last_meta_end);
+        darshan_delete_record_ref(&(stdio_runtime->stream_hash), &fp, sizeof(fp));
+    }
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    size_t ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fwrite);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fwrite(ptr, size, nmemb, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret > 0)
+        STDIO_RECORD_WRITE(stream, size*ret, tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+int DARSHAN_DECL(fputc)(int c, FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fputc);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fputc(c, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF)
+        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(putw)(int w, FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(putw);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_putw(w, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF)
+        STDIO_RECORD_WRITE(stream, sizeof(int), tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+
+int DARSHAN_DECL(fputs)(const char *s, FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fputs);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fputs(s, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF && ret > 0)
+        STDIO_RECORD_WRITE(stream, strlen(s), tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(vfprintf)(FILE *stream, const char *format, va_list ap)
+{
+    int ret;
+    double tm1, tm2;
+    long start_off, end_off;
+
+    MAP_OR_FAIL(vfprintf);
+
+    tm1 = darshan_core_wtime();
+    start_off = ftell(stream);
+    ret = __real_vfprintf(stream, format, ap);
+    end_off = ftell(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret > 0)
+        STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+int DARSHAN_DECL(fprintf)(FILE *stream, const char *format, ...)
+{
+    int ret;
+    double tm1, tm2;
+    va_list ap;
+    long start_off, end_off;
+
+    MAP_OR_FAIL(vfprintf);
+
+    tm1 = darshan_core_wtime();
+    /* NOTE: we intentionally switch to vfprintf here to handle the variable
+     * length arguments.
+     */
+    start_off = ftell(stream);
+    va_start(ap, format);
+    ret = __real_vfprintf(stream, format, ap);
+    va_end(ap);
+    end_off = ftell(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret > 0)
+        STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    size_t ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fread);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fread(ptr, size, nmemb, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret > 0)
+        STDIO_RECORD_READ(stream, size*ret, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fgetc)(FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fgetc);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fgetc(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF)
+        STDIO_RECORD_READ(stream, 1, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+/* NOTE: stdio.h typically implements getc() as a macro pointing to _IO_getc */
+int DARSHAN_DECL(_IO_getc)(FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(_IO_getc);
+
+    tm1 = darshan_core_wtime();
+    ret = __real__IO_getc(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF)
+        STDIO_RECORD_READ(stream, 1, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+/* NOTE: stdio.h typically implements putc() as a macro pointing to _IO_putc */
+int DARSHAN_DECL(_IO_putc)(int c, FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(_IO_putc);
+
+    tm1 = darshan_core_wtime();
+    ret = __real__IO_putc(c, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF)
+        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(getw)(FILE *stream)
+{
+    int ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(getw);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_getw(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != EOF || ferror(stream) == 0)
+        STDIO_RECORD_READ(stream, sizeof(int), tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+/* NOTE: some glibc versions use __isoc99_fscanf as the underlying symbol
+ * rather than fscanf
+ */
+int DARSHAN_DECL(__isoc99_fscanf)(FILE *stream, const char *format, ...)
+{
+    int ret;
+    double tm1, tm2;
+    va_list ap;
+    long start_off, end_off;
+
+    MAP_OR_FAIL(vfscanf);
+
+    tm1 = darshan_core_wtime();
+    /* NOTE: we intentionally switch to vfscanf here to handle the variable
+     * length arguments.
+     */
+    start_off = ftell(stream);
+    va_start(ap, format);
+    ret = __real_vfscanf(stream, format, ap);
+    va_end(ap);
+    end_off = ftell(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != 0)
+        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+int DARSHAN_DECL(fscanf)(FILE *stream, const char *format, ...)
+{
+    int ret;
+    double tm1, tm2;
+    va_list ap;
+    long start_off, end_off;
+
+    MAP_OR_FAIL(vfscanf);
+
+    tm1 = darshan_core_wtime();
+    /* NOTE: we intentionally switch to vfscanf here to handle the variable
+     * length arguments.
+     */
+    start_off = ftell(stream);
+    va_start(ap, format);
+    ret = __real_vfscanf(stream, format, ap);
+    va_end(ap);
+    end_off = ftell(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != 0)
+        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+int DARSHAN_DECL(vfscanf)(FILE *stream, const char *format, va_list ap)
+{
+    int ret;
+    double tm1, tm2;
+    long start_off, end_off;
+
+    MAP_OR_FAIL(vfscanf);
+
+    tm1 = darshan_core_wtime();
+    start_off = ftell(stream);
+    ret = __real_vfscanf(stream, format, ap);
+    end_off = ftell(stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != 0)
+        STDIO_RECORD_READ(stream, end_off-start_off, tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+char* DARSHAN_DECL(fgets)(char *s, int size, FILE *stream)
+{
+    char *ret;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fgets);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fgets(s, size, stream);
+    tm2 = darshan_core_wtime();
+
+    STDIO_PRE_RECORD();
+    if(ret != NULL)
+        STDIO_RECORD_READ(stream, strlen(ret), tm1, tm2);
+    STDIO_POST_RECORD();
+
+    return(ret);
+}
+
+
+void DARSHAN_DECL(rewind)(FILE *stream)
+{
+    double tm1, tm2;
+    struct stdio_file_record_ref *rec_ref;
+
+    MAP_OR_FAIL(rewind);
+
+    tm1 = darshan_core_wtime();
+    __real_rewind(stream);
+    tm2 = darshan_core_wtime();
+
+    /* NOTE: we don't use STDIO_PRE_RECORD here because there is no return
+     * value in this wrapper.
+     */
+    STDIO_LOCK();
+    if(!stdio_runtime && !instrumentation_disabled) stdio_runtime_initialize();
+    if(!stdio_runtime) {
+        STDIO_UNLOCK();
+        return;
+    }
+
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+
+    if(rec_ref)
+    {
+        rec_ref->offset = 0;
+        DARSHAN_TIMER_INC_NO_OVERLAP(
+            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+            tm1, tm2, rec_ref->last_meta_end);
+        rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+    }
+    STDIO_POST_RECORD();
+
+    return;
+}
+
+int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
+{
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fseek);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fseek(stream, offset, whence);
+    tm2 = darshan_core_wtime();
+
+    if(ret >= 0)
+    {
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
+        {
+            rec_ref->offset = ftell(stream);
+            DARSHAN_TIMER_INC_NO_OVERLAP(
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+        }
+        STDIO_POST_RECORD();
+    }
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
+{
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fseeko);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fseeko(stream, offset, whence);
+    tm2 = darshan_core_wtime();
+
+    if(ret >= 0)
+    {
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
+        {
+            rec_ref->offset = ftell(stream);
+            DARSHAN_TIMER_INC_NO_OVERLAP(
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+        }
+        STDIO_POST_RECORD();
+    }
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fseeko64)(FILE *stream, off_t offset, int whence)
+{
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fseeko64);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fseeko64(stream, offset, whence);
+    tm2 = darshan_core_wtime();
+
+    if(ret >= 0)
+    {
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
+        {
+            rec_ref->offset = ftell(stream);
+            DARSHAN_TIMER_INC_NO_OVERLAP(
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+        }
+        STDIO_POST_RECORD();
+    }
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
+{
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fsetpos);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fsetpos(stream, pos);
+    tm2 = darshan_core_wtime();
+
+    if(ret >= 0)
+    {
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
+        {
+            rec_ref->offset = ftell(stream);
+            DARSHAN_TIMER_INC_NO_OVERLAP(
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+        }
+        STDIO_POST_RECORD();
+    }
+
+    return(ret);
+}
+
+int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos64_t *pos)
+{
+    int ret;
+    struct stdio_file_record_ref *rec_ref;
+    double tm1, tm2;
+
+    MAP_OR_FAIL(fsetpos64);
+
+    tm1 = darshan_core_wtime();
+    ret = __real_fsetpos64(stream, pos);
+    tm2 = darshan_core_wtime();
+
+    if(ret >= 0)
+    {
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
+        {
+            rec_ref->offset = ftell(stream);
+            DARSHAN_TIMER_INC_NO_OVERLAP(
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
+        }
+        STDIO_POST_RECORD();
+    }
+
+    return(ret);
+}
+
+
+/**********************************************************
+ * Internal functions for manipulating STDIO module state *
+ **********************************************************/
+
+/* initialize internal STDIO module data structures and register with darshan-core */
+static void stdio_runtime_initialize()
+{
+    int stdio_buf_size;
+
+    /* try to store default number of records for this module */
+    stdio_buf_size = DARSHAN_DEF_MOD_REC_COUNT * sizeof(struct darshan_stdio_file);
+
+    /* don't do anything if already initialized or instrumenation is disabled */
+    if(stdio_runtime || instrumentation_disabled)
+        return;
+
+    /* register the stdio module with darshan core */
+    darshan_core_register_module(
+        DARSHAN_STDIO_MOD,
+        &stdio_shutdown,
+        &stdio_buf_size,
+        &my_rank,
+        &darshan_mem_alignment);
+
+    /* return if darshan-core does not provide enough module memory */
+    if(stdio_buf_size < sizeof(struct darshan_stdio_file))
+    {
+        darshan_core_unregister_module(DARSHAN_POSIX_MOD);
+        return;
+    }
+
+    stdio_runtime = malloc(sizeof(*stdio_runtime));
+    if(!stdio_runtime)
+    {
+        darshan_core_unregister_module(DARSHAN_STDIO_MOD);
+        return;
+    }
+    memset(stdio_runtime, 0, sizeof(*stdio_runtime));
+}
+
+/************************************************************************
+ * Functions exported by this module for coordinating with darshan-core *
+ ************************************************************************/
+
+static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
+    int *len, MPI_Datatype *datatype)
+{
+    struct darshan_stdio_file tmp_file;
+    struct darshan_stdio_file *infile = infile_v;
+    struct darshan_stdio_file *inoutfile = inoutfile_v;
+    int i, j;
+
+    assert(stdio_runtime);
+
+    for(i=0; i<*len; i++)
+    {
+        memset(&tmp_file, 0, sizeof(struct darshan_stdio_file));
+        tmp_file.base_rec.id = infile->base_rec.id;
+        tmp_file.base_rec.rank = -1;
+
+        /* sum */
+        for(j=STDIO_OPENS; j<=STDIO_BYTES_READ; j++)
+        {
+            tmp_file.counters[j] = infile->counters[j] + inoutfile->counters[j];
+        }
+        
+        /* max */
+        for(j=STDIO_MAX_BYTE_READ; j<=STDIO_MAX_BYTE_WRITTEN; j++)
+        {
+            if(infile->counters[j] > inoutfile->counters[j])
+                tmp_file.counters[j] = infile->counters[j];
+            else
+                tmp_file.counters[j] = inoutfile->counters[j];
+        }
+
+        /* sum */
+        for(j=STDIO_F_META_TIME; j<=STDIO_F_READ_TIME; j++)
+        {
+            tmp_file.fcounters[j] = infile->fcounters[j] + inoutfile->fcounters[j];
+        }
+
+        /* min non-zero (if available) value */
+        for(j=STDIO_F_OPEN_START_TIMESTAMP; j<=STDIO_F_READ_START_TIMESTAMP; j++)
+        {
+            if((infile->fcounters[j] < inoutfile->fcounters[j] &&
+               infile->fcounters[j] > 0) || inoutfile->fcounters[j] == 0) 
+                tmp_file.fcounters[j] = infile->fcounters[j];
+            else
+                tmp_file.fcounters[j] = inoutfile->fcounters[j];
+        }
+
+        /* max */
+        for(j=STDIO_F_OPEN_END_TIMESTAMP; j<=STDIO_F_READ_END_TIMESTAMP; j++)
+        {
+            if(infile->fcounters[j] > inoutfile->fcounters[j])
+                tmp_file.fcounters[j] = infile->fcounters[j];
+            else
+                tmp_file.fcounters[j] = inoutfile->fcounters[j];
+        }
+
+        /* update pointers */
+        *inoutfile = tmp_file;
+        inoutfile++;
+        infile++;
+    }
+
+    return;
+}
+
+static void stdio_shutdown(
+    MPI_Comm mod_comm,
+    darshan_record_id *shared_recs,
+    int shared_rec_count,
+    void **stdio_buf,
+    int *stdio_buf_sz)
+{
+    struct stdio_file_record_ref *rec_ref;
+    struct darshan_stdio_file *stdio_rec_buf = *(struct darshan_stdio_file **)stdio_buf;
+    int i;
+    struct darshan_stdio_file *red_send_buf = NULL;
+    struct darshan_stdio_file *red_recv_buf = NULL;
+    MPI_Datatype red_type;
+    MPI_Op red_op;
+    int stdio_rec_count;
+
+    STDIO_LOCK();
+    assert(stdio_runtime);
+    stdio_rec_count = stdio_runtime->file_rec_count;
+
+    /* if there are globally shared files, do a shared file reduction */
+    /* NOTE: the shared file reduction is also skipped if the 
+     * DARSHAN_DISABLE_SHARED_REDUCTION environment variable is set.
+     */
+    if(shared_rec_count && !getenv("DARSHAN_DISABLE_SHARED_REDUCTION"))
+    {
+        /* necessary initialization of shared records */
+        for(i = 0; i < shared_rec_count; i++)
+        {
+            rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash,
+                &shared_recs[i], sizeof(darshan_record_id));
+            assert(rec_ref);
+
+            rec_ref->file_rec->base_rec.rank = -1;
+        }
+
+        /* sort the array of files descending by rank so that we get all of the 
+         * shared files (marked by rank -1) in a contiguous portion at end 
+         * of the array
+         */
+        darshan_record_sort(stdio_rec_buf, stdio_rec_count, sizeof(struct darshan_stdio_file));
+
+        /* make *send_buf point to the shared files at the end of sorted array */
+        red_send_buf = &(stdio_rec_buf[stdio_rec_count-shared_rec_count]);
+
+        /* allocate memory for the reduction output on rank 0 */
+        if(my_rank == 0)
+        {
+            red_recv_buf = malloc(shared_rec_count * sizeof(struct darshan_stdio_file));
+            if(!red_recv_buf)
+            {
+                return;
+            }
+        }
+
+        /* construct a datatype for a STDIO file record.  This is serving no purpose
+         * except to make sure we can do a reduction on proper boundaries
+         */
+        DARSHAN_MPI_CALL(PMPI_Type_contiguous)(sizeof(struct darshan_stdio_file),
+            MPI_BYTE, &red_type);
+        DARSHAN_MPI_CALL(PMPI_Type_commit)(&red_type);
+
+        /* register a STDIO file record reduction operator */
+        DARSHAN_MPI_CALL(PMPI_Op_create)(stdio_record_reduction_op, 1, &red_op);
+
+        /* reduce shared STDIO file records */
+        DARSHAN_MPI_CALL(PMPI_Reduce)(red_send_buf, red_recv_buf,
+            shared_rec_count, red_type, red_op, 0, mod_comm);
+
+        /* clean up reduction state */
+        if(my_rank == 0)
+        {
+            int tmp_ndx = stdio_rec_count - shared_rec_count;
+            memcpy(&(stdio_rec_buf[tmp_ndx]), red_recv_buf,
+                shared_rec_count * sizeof(struct darshan_stdio_file));
+            free(red_recv_buf);
+        }
+        else
+        {
+            stdio_rec_count -= shared_rec_count;
+        }
+
+        DARSHAN_MPI_CALL(PMPI_Type_free)(&red_type);
+        DARSHAN_MPI_CALL(PMPI_Op_free)(&red_op);
+    }
+
+    /* update output buffer size to account for shared file reduction */
+    *stdio_buf_sz = stdio_rec_count * sizeof(struct darshan_stdio_file);
+
+    /* shutdown internal structures used for instrumenting */
+    stdio_cleanup_runtime();
+
+    /* disable further instrumentation */
+    instrumentation_disabled = 1;
+
+    STDIO_UNLOCK();
+    
+    return;
+}
+
+static struct stdio_file_record_ref *stdio_track_new_file_record(
+    darshan_record_id rec_id, const char *path)
+{
+    struct darshan_stdio_file *file_rec = NULL;
+    struct stdio_file_record_ref *rec_ref = NULL;
+    int ret;
+
+    rec_ref = malloc(sizeof(*rec_ref));
+    if(!rec_ref)
+        return(NULL);
+    memset(rec_ref, 0, sizeof(*rec_ref));
+
+    /* add a reference to this file record based on record id */
+    ret = darshan_add_record_ref(&(stdio_runtime->rec_id_hash), &rec_id,
+        sizeof(darshan_record_id), rec_ref);
+    if(ret == 0)
+    {
+        free(rec_ref);
+        return(NULL);
+    }
+
+    /* register the actual file record with darshan-core so it is persisted
+     * in the log file
+     */
+    file_rec = darshan_core_register_record(
+        rec_id,
+        path,
+        DARSHAN_STDIO_MOD,
+        sizeof(struct darshan_stdio_file),
+        NULL);
+
+    if(!file_rec)
+    {
+        darshan_delete_record_ref(&(stdio_runtime->rec_id_hash),
+            &rec_id, sizeof(darshan_record_id));
+        free(rec_ref);
+        return(NULL);
+    }
+
+    /* registering this file record was successful, so initialize some fields */
+    file_rec->base_rec.id = rec_id;
+    file_rec->base_rec.rank = my_rank;
+    rec_ref->file_rec = file_rec;
+    stdio_runtime->file_rec_count++;
+
+    return(rec_ref);
+
+}
+
+static void stdio_cleanup_runtime()
+{
+    darshan_clear_record_refs(&(stdio_runtime->stream_hash), 0);
+    darshan_clear_record_refs(&(stdio_runtime->rec_id_hash), 1);
+
+    free(stdio_runtime);
+    stdio_runtime = NULL;
+
+    return;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */


=====================================
darshan-runtime/share/ld-opts/darshan-base-ld-opts.in
=====================================
--- a/darshan-runtime/share/ld-opts/darshan-base-ld-opts.in
+++ b/darshan-runtime/share/ld-opts/darshan-base-ld-opts.in
@@ -3,3 +3,4 @@
 @@darshan_share_path@/ld-opts/darshan-posix-ld-opts
 @@darshan_share_path@/ld-opts/darshan-hdf5-ld-opts
 @@darshan_share_path@/ld-opts/darshan-pnetcdf-ld-opts
+@@darshan_share_path@/ld-opts/darshan-stdio-ld-opts


=====================================
darshan-runtime/share/ld-opts/darshan-posix-ld-opts
=====================================
--- a/darshan-runtime/share/ld-opts/darshan-posix-ld-opts
+++ b/darshan-runtime/share/ld-opts/darshan-posix-ld-opts
@@ -2,8 +2,6 @@
 --wrap=open64
 --wrap=creat
 --wrap=creat64
---wrap=fopen
---wrap=fopen64
 --wrap=mkstemp
 --wrap=mkostemp
 --wrap=mkstemps
@@ -16,11 +14,8 @@
 --wrap=pwrite64
 --wrap=readv
 --wrap=writev
---wrap=fread
---wrap=fwrite
 --wrap=lseek
 --wrap=lseek64
---wrap=fseek
 --wrap=__xstat
 --wrap=__xstat64
 --wrap=__lxstat
@@ -32,7 +27,6 @@
 --wrap=fsync
 --wrap=fdatasync
 --wrap=close
---wrap=fclose
 --wrap=aio_read
 --wrap=aio_write
 --wrap=aio_read64


=====================================
darshan-runtime/share/ld-opts/darshan-stdio-ld-opts
=====================================
--- /dev/null
+++ b/darshan-runtime/share/ld-opts/darshan-stdio-ld-opts
@@ -0,0 +1,29 @@
+--undefined=__wrap_fopen
+--wrap=fopen
+--wrap=fopen64
+--wrap=fdopen
+--wrap=freopen
+--wrap=freopen64
+--wrap=fflush
+--wrap=fclose
+--wrap=fwrite
+--wrap=fread
+--wrap=fgetc
+--wrap=fscanf
+--wrap=vfscanf
+--wrap=_IO_getc
+--wrap=_IO_putc
+--wrap=getw
+--wrap=fgets
+--wrap=fseek
+--wrap=fseeko
+--wrap=fseeko64
+--wrap=fprintf
+--wrap=vfprintf
+--wrap=fputc
+--wrap=fputs
+--wrap=putw
+--wrap=fsetpos
+--wrap=fsetpos64
+--wrap=rewind
+--wrap=__isoc99_fscanf


=====================================
darshan-stdio-log-format.h
=====================================
--- /dev/null
+++ b/darshan-stdio-log-format.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 University of Chicago.
+ * See COPYRIGHT notice in top-level directory.
+ *
+ */
+
+#ifndef __DARSHAN_STDIO_LOG_FORMAT_H
+#define __DARSHAN_STDIO_LOG_FORMAT_H
+
+/* current log format version, to support backwards compatibility */
+#define DARSHAN_STDIO_VER 1
+
+#define STDIO_COUNTERS \
+    /* count of fopens */\
+    X(STDIO_OPENS) \
+    /* number of reads */ \
+    X(STDIO_READS) \
+    /* number of writes */ \
+    X(STDIO_WRITES) \
+    /* count of seeks */\
+    X(STDIO_SEEKS) \
+    /* count of flushes */\
+    X(STDIO_FLUSHES) \
+    /* total bytes written */ \
+    X(STDIO_BYTES_WRITTEN) \
+    /* total bytes read */ \
+    X(STDIO_BYTES_READ) \
+    /* maximum byte (offset) read */\
+    X(STDIO_MAX_BYTE_READ) \
+    /* maximum byte (offset) written */\
+    X(STDIO_MAX_BYTE_WRITTEN) \
+    /* end of counters */\
+    X(STDIO_NUM_INDICES)
+
+#define STDIO_F_COUNTERS \
+    /* cumulative meta time */\
+    X(STDIO_F_META_TIME) \
+    /* cumulative write time */\
+    X(STDIO_F_WRITE_TIME) \
+    /* cumulative read time */\
+    X(STDIO_F_READ_TIME) \
+    /* timestamp of first open */\
+    X(STDIO_F_OPEN_START_TIMESTAMP) \
+    /* timestamp of first close */\
+    X(STDIO_F_CLOSE_START_TIMESTAMP) \
+    /* timestamp of first write */\
+    X(STDIO_F_WRITE_START_TIMESTAMP) \
+    /* timestamp of first read */\
+    X(STDIO_F_READ_START_TIMESTAMP) \
+    /* timestamp of last open completion */\
+    X(STDIO_F_OPEN_END_TIMESTAMP) \
+    /* timestamp of last close completion */\
+    X(STDIO_F_CLOSE_END_TIMESTAMP) \
+    /* timestamp of last write completion */\
+    X(STDIO_F_WRITE_END_TIMESTAMP) \
+    /* timestamp of last read completion */\
+    X(STDIO_F_READ_END_TIMESTAMP) \
+    /* end of counters */\
+    X(STDIO_F_NUM_INDICES)
+
+#define X(a) a,
+/* integer counters for the "STDIO" module */
+enum darshan_stdio_indices
+{
+    STDIO_COUNTERS
+};
+
+/* floating point counters for the "STDIO" module */
+enum darshan_stdio_f_indices
+{
+    STDIO_F_COUNTERS
+};
+#undef X
+
+/* the darshan_stdio_record structure encompasses the high-level data/counters
+ * which would actually be logged to file by Darshan for the "STDIO"
+ * module. This logs the following data for each record:
+ *      - a corresponding Darshan record identifier
+ *      - the rank of the process responsible for the record
+ *      - integer I/O counters (operation counts, I/O sizes, etc.)
+ *      - floating point I/O counters (timestamps, cumulative timers, etc.)
+ */
+struct darshan_stdio_file
+{
+    struct darshan_base_record base_rec;
+    int64_t counters[STDIO_NUM_INDICES];
+    double fcounters[STDIO_F_NUM_INDICES];
+};
+
+#endif /* __DARSHAN_STDIO_LOG_FORMAT_H */


=====================================
darshan-test/regression/test-cases/fprintf-fscanf-test.sh
=====================================
--- /dev/null
+++ b/darshan-test/regression/test-cases/fprintf-fscanf-test.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+PROG=fprintf-fscanf-test
+
+# set log file path; remove previous log if present
+export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
+rm -f ${DARSHAN_LOGFILE}
+
+# compile
+$DARSHAN_CC $DARSHAN_TESTDIR/test-cases/src/${PROG}.c -o $DARSHAN_TMP/${PROG}
+if [ $? -ne 0 ]; then
+    echo "Error: failed to compile ${PROG}" 1>&2
+    exit 1
+fi
+
+# execute
+$DARSHAN_RUNJOB $DARSHAN_TMP/${PROG} -f $DARSHAN_TMP/${PROG}.tmp.dat
+if [ $? -ne 0 ]; then
+    echo "Error: failed to execute ${PROG}" 1>&2
+    exit 1
+fi
+
+# parse log
+$DARSHAN_PATH/bin/darshan-parser $DARSHAN_LOGFILE > $DARSHAN_TMP/${PROG}.darshan.txt
+if [ $? -ne 0 ]; then
+    echo "Error: failed to parse ${DARSHAN_LOGFILE}" 1>&2
+    exit 1
+fi
+
+# check results
+
+STDIO_OPENS=`grep STDIO_OPENS $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_OPENS" -eq 4 ]; then
+    echo "Error: STDIO open count of $STDIO_OPENS is incorrect" 1>&2
+    exit 1
+fi
+
+# this will check fprintf counting
+STDIO_BYTES_WRITTEN=`grep STDIO_BYTES_WRITTEN $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_BYTES_WRITTEN" -eq 15 ]; then
+    echo "Error: STDIO bytes written count of $STDIO_BYTES_WRITTEN is incorrect" 1>&2
+    exit 1
+fi
+
+# this will check fscanf counting
+STDIO_BYTES_READ=`grep STDIO_BYTES_READ $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_BYTES_READ" -eq 15 ]; then
+    echo "Error: STDIO bytes read count of $STDIO_BYTES_READ is incorrect" 1>&2
+    exit 1
+fi
+
+
+exit 0


=====================================
darshan-test/regression/test-cases/src/fprintf-fscanf-test.c
=====================================
--- /dev/null
+++ b/darshan-test/regression/test-cases/src/fprintf-fscanf-test.c
@@ -0,0 +1,106 @@
+/*
+ * (C) 1995-2001 Clemson University and Argonne National Laboratory.
+ *
+ * See COPYING in top-level directory.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <mpi.h>
+#include <errno.h>
+#include <getopt.h>
+
+/* DEFAULT VALUES FOR OPTIONS */
+static char    opt_file[256] = "test-fprintf-fscanf.out";
+
+/* function prototypes */
+static int parse_args(int argc, char **argv);
+static void usage(void);
+
+/* global vars */
+static int mynod = 0;
+static int nprocs = 1;
+
+int main(int argc, char **argv)
+{
+   int namelen;
+   char processor_name[MPI_MAX_PROCESSOR_NAME];
+   FILE *file;
+   char buffer[128] = {0};
+   int number = 0;
+
+   /* startup MPI and determine the rank of this process */
+   MPI_Init(&argc,&argv);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+   MPI_Comm_rank(MPI_COMM_WORLD, &mynod);
+   MPI_Get_processor_name(processor_name, &namelen); 
+   
+   /* parse the command line arguments */
+   parse_args(argc, argv);
+
+   if (mynod == 0) printf("# Using stdio calls.\n");
+
+   file = fopen(opt_file, "w+");
+   if(!file)
+   {
+      perror("fopen");
+      return(-1);
+   }
+
+   if(mynod == 0)
+   {
+      fprintf(file, "a number: %d", 12345);
+      fseek(file, 0, SEEK_SET);
+      fscanf(file, "a number: %d", &number);
+   }
+
+   fclose(file);
+
+   MPI_Finalize();
+   return(0);
+}
+
+static int parse_args(int argc, char **argv)
+{
+   int c;
+   
+   while ((c = getopt(argc, argv, "f:")) != EOF) {
+      switch (c) {
+         case 'f': /* filename */
+            strncpy(opt_file, optarg, 255);
+            break;
+         case '?': /* unknown */
+            if (mynod == 0)
+                usage();
+            exit(1);
+         default:
+            break;
+      }
+   }
+   return(0);
+}
+
+static void usage(void)
+{
+    printf("Usage: stdio-test [<OPTIONS>...]\n");
+    printf("\n<OPTIONS> is one of\n");
+    printf(" -f       filename [default: /foo/test.out]\n");
+    printf(" -h       print this help\n");
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 3
+ *  c-basic-offset: 3
+ *  tab-width: 3
+ *
+ * vim: ts=3
+ * End:
+ */ 
+
+


=====================================
darshan-test/regression/test-cases/src/stdio-test.c
=====================================
--- /dev/null
+++ b/darshan-test/regression/test-cases/src/stdio-test.c
@@ -0,0 +1,105 @@
+/*
+ * (C) 1995-2001 Clemson University and Argonne National Laboratory.
+ *
+ * See COPYING in top-level directory.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <mpi.h>
+#include <errno.h>
+#include <getopt.h>
+
+/* DEFAULT VALUES FOR OPTIONS */
+static char    opt_file[256] = "test.out";
+
+/* function prototypes */
+static int parse_args(int argc, char **argv);
+static void usage(void);
+
+/* global vars */
+static int mynod = 0;
+static int nprocs = 1;
+
+int main(int argc, char **argv)
+{
+   int namelen;
+   char processor_name[MPI_MAX_PROCESSOR_NAME];
+   FILE *file;
+   char buffer[128] = {0};
+
+   /* startup MPI and determine the rank of this process */
+   MPI_Init(&argc,&argv);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+   MPI_Comm_rank(MPI_COMM_WORLD, &mynod);
+   MPI_Get_processor_name(processor_name, &namelen); 
+   
+   /* parse the command line arguments */
+   parse_args(argc, argv);
+
+   if (mynod == 0) printf("# Using stdio calls.\n");
+
+   file = fopen(opt_file, "w+");
+   if(!file)
+   {
+      perror("fopen");
+      return(-1);
+   }
+
+   if(mynod == 0)
+   {
+      fwrite("hello", 1, 6, file);
+      fseek(file, 0, SEEK_SET);
+      fread(buffer, 1, 1024, file);
+   }
+
+   fclose(file);
+
+   MPI_Finalize();
+   return(0);
+}
+
+static int parse_args(int argc, char **argv)
+{
+   int c;
+   
+   while ((c = getopt(argc, argv, "f:")) != EOF) {
+      switch (c) {
+         case 'f': /* filename */
+            strncpy(opt_file, optarg, 255);
+            break;
+         case '?': /* unknown */
+            if (mynod == 0)
+                usage();
+            exit(1);
+         default:
+            break;
+      }
+   }
+   return(0);
+}
+
+static void usage(void)
+{
+    printf("Usage: stdio-test [<OPTIONS>...]\n");
+    printf("\n<OPTIONS> is one of\n");
+    printf(" -f       filename [default: /foo/test.out]\n");
+    printf(" -h       print this help\n");
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 3
+ *  c-basic-offset: 3
+ *  tab-width: 3
+ *
+ * vim: ts=3
+ * End:
+ */ 
+
+


=====================================
darshan-test/regression/test-cases/stdio-test.sh
=====================================
--- /dev/null
+++ b/darshan-test/regression/test-cases/stdio-test.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+PROG=stdio-test
+
+# set log file path; remove previous log if present
+export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
+rm -f ${DARSHAN_LOGFILE}
+
+# compile
+$DARSHAN_CC $DARSHAN_TESTDIR/test-cases/src/${PROG}.c -o $DARSHAN_TMP/${PROG}
+if [ $? -ne 0 ]; then
+    echo "Error: failed to compile ${PROG}" 1>&2
+    exit 1
+fi
+
+# execute
+$DARSHAN_RUNJOB $DARSHAN_TMP/${PROG} -f $DARSHAN_TMP/${PROG}.tmp.dat
+if [ $? -ne 0 ]; then
+    echo "Error: failed to execute ${PROG}" 1>&2
+    exit 1
+fi
+
+# parse log
+$DARSHAN_PATH/bin/darshan-parser $DARSHAN_LOGFILE > $DARSHAN_TMP/${PROG}.darshan.txt
+if [ $? -ne 0 ]; then
+    echo "Error: failed to parse ${DARSHAN_LOGFILE}" 1>&2
+    exit 1
+fi
+
+# check results
+
+# check at least one counter from each general open/read/write/seek category
+
+STDIO_OPENS=`grep STDIO_OPENS $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_OPENS" -gt 0 ]; then
+    echo "Error: STDIO open count of $STDIO_OPENS is incorrect" 1>&2
+    exit 1
+fi
+STDIO_SEEKS=`grep STDIO_SEEKS $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_SEEKS" -gt 0 ]; then
+    echo "Error: STDIO open count of $STDIO_SEEKS is incorrect" 1>&2
+    exit 1
+fi
+STDIO_BYTES_WRITTEN=`grep STDIO_BYTES_WRITTEN $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_BYTES_WRITTEN" -eq 6 ]; then
+    echo "Error: STDIO open count of $STDIO_BYTES_WRITTEN is incorrect" 1>&2
+    exit 1
+fi
+STDIO_BYTES_READ=`grep STDIO_BYTES_READ $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! "$STDIO_BYTES_READ" -eq 6 ]; then
+    echo "Error: STDIO open count of $STDIO_BYTES_READ is incorrect" 1>&2
+    exit 1
+fi
+
+
+# make sure that some of the floating point counters are valid
+# use bc for floating point comparison
+STDIO_F_OPEN_START_TIMESTAMP=`grep STDIO_F_OPEN_START_TIMESTAMP $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_OPEN_START_TIMESTAMP > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+STDIO_F_OPEN_END_TIMESTAMP=`grep STDIO_F_OPEN_END_TIMESTAMP $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_OPEN_END_TIMESTAMP > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+STDIO_F_META_TIME=`grep STDIO_F_META_TIME $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_META_TIME > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+STDIO_F_WRITE_TIME=`grep STDIO_F_WRITE_TIME $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_WRITE_TIME > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+STDIO_F_CLOSE_START_TIMESTAMP=`grep STDIO_F_CLOSE_START_TIMESTAMP $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_CLOSE_START_TIMESTAMP > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+STDIO_F_CLOSE_END_TIMESTAMP=`grep STDIO_F_CLOSE_END_TIMESTAMP $DARSHAN_TMP/${PROG}.darshan.txt | cut -f 5`
+if [ ! $(echo "$STDIO_F_CLOSE_END_TIMESTAMP > 0" | bc -l) ]; then
+    echo "Error: counter is incorrect" 1>&2
+    exit 1
+fi
+
+
+exit 0


=====================================
darshan-util/Makefile.in
=====================================
--- a/darshan-util/Makefile.in
+++ b/darshan-util/Makefile.in
@@ -13,10 +13,10 @@ libdir = $(DESTDIR)@libdir@
 pkgconfigdir = $(DESTDIR)$(libdir)/pkgconfig
 
 DARSHAN_LOG_FORMAT = $(srcdir)/../darshan-log-format.h
-DARSHAN_MOD_LOG_FORMATS = $(srcdir)/../darshan-posix-log-format.h $(srcdir)/../darshan-mpiio-log-format.h $(srcdir)/../darshan-hdf5-log-format.h $(srcdir)/../darshan-pnetcdf-log-format.h $(srcdir)/../darshan-lustre-log-format.h
-DARSHAN_MOD_LOGUTIL_HEADERS = darshan-posix-logutils.h darshan-mpiio-logutils.h darshan-hdf5-logutils.h darshan-pnetcdf-logutils.h darshan-lustre-logutils.h
-DARSHAN_STATIC_MOD_OBJS = darshan-posix-logutils.o darshan-mpiio-logutils.o darshan-hdf5-logutils.o darshan-pnetcdf-logutils.o darshan-bgq-logutils.o darshan-lustre-logutils.o
-DARSHAN_DYNAMIC_MOD_OBJS = darshan-posix-logutils.po darshan-mpiio-logutils.po darshan-hdf5-logutils.po darshan-pnetcdf-logutils.po darshan-bgq-logutils.po darshan-lustre-logutils.po
+DARSHAN_MOD_LOG_FORMATS = $(srcdir)/../darshan-posix-log-format.h $(srcdir)/../darshan-mpiio-log-format.h $(srcdir)/../darshan-hdf5-log-format.h $(srcdir)/../darshan-pnetcdf-log-format.h $(srcdir)/../darshan-bgq-log-format.h $(srcdir)/../darshan-lustre-log-format.h $(srcdir)/../darshan-stdio-log-format.h
+DARSHAN_MOD_LOGUTIL_HEADERS = darshan-posix-logutils.h darshan-mpiio-logutils.h darshan-hdf5-logutils.h darshan-pnetcdf-logutils.h darshan-bgq-logutils.h darshan-lustre-logutils.h darshan-stdio-logutils.h
+DARSHAN_STATIC_MOD_OBJS = darshan-posix-logutils.o darshan-mpiio-logutils.o darshan-hdf5-logutils.o darshan-pnetcdf-logutils.o darshan-bgq-logutils.o darshan-lustre-logutils.o darshan-stdio-logutils.o
+DARSHAN_DYNAMIC_MOD_OBJS = darshan-posix-logutils.po darshan-mpiio-logutils.po darshan-hdf5-logutils.po darshan-pnetcdf-logutils.po darshan-bgq-logutils.po darshan-lustre-logutils.po darshan-stdio-logutils.po
 
 DARSHAN_ENABLE_SHARED=@DARSHAN_ENABLE_SHARED@
 
@@ -86,6 +86,11 @@ darshan-lustre-logutils.o: darshan-lustre-logutils.c darshan-logutils.h darshan-
 darshan-lustre-logutils.po: darshan-lustre-logutils.c darshan-logutils.h darshan-lustre-logutils.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-lustre-log-format.h | uthash-1.9.2
 	$(CC) $(CFLAGS_SHARED) -c  $< -o $@
 
+darshan-stdio-logutils.o: darshan-stdio-logutils.c darshan-logutils.h darshan-stdio-logutils.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | uthash-1.9.2
+	$(CC) $(CFLAGS) -c  $< -o $@
+darshan-stdio-logutils.po: darshan-stdio-logutils.c darshan-logutils.h darshan-stdio-logutils.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | uthash-1.9.2
+	$(CC) $(CFLAGS_SHARED) -c  $< -o $@
+
 libdarshan-util.a: darshan-logutils.o $(DARSHAN_STATIC_MOD_OBJS)
 	ar rcs libdarshan-util.a $^
 
@@ -141,12 +146,14 @@ endif
 	install -m 644 $(srcdir)/darshan-pnetcdf-logutils.h $(includedir)
 	install -m 644 $(srcdir)/darshan-bgq-logutils.h $(includedir)
 	install -m 644 $(srcdir)/darshan-null-logutils.h $(includedir)
+	install -m 644 $(srcdir)/darshan-stdio-logutils.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-null-log-format.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-posix-log-format.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-mpiio-log-format.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-hdf5-log-format.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-pnetcdf-log-format.h $(includedir)
 	install -m 644 $(srcdir)/../darshan-bgq-log-format.h $(includedir)
+	install -m 644 $(srcdir)/../darshan-stdio-log-format.h $(includedir)
 	install -d $(includedir)/uthash-1.9.2
 	install -d $(includedir)/uthash-1.9.2/src
 	install -m 644 uthash-1.9.2/src/uthash.h $(includedir)/uthash-1.9.2/src/


=====================================
darshan-util/configure
=====================================
The diff for this file was not included because it is too large.

=====================================
darshan-util/darshan-logutils.h
=====================================
--- a/darshan-util/darshan-logutils.h
+++ b/darshan-util/darshan-logutils.h
@@ -126,6 +126,7 @@ extern struct darshan_mod_logutil_funcs *mod_logutils[];
 #include "darshan-pnetcdf-logutils.h"
 #include "darshan-bgq-logutils.h"
 #include "darshan-lustre-logutils.h"
+#include "darshan-stdio-logutils.h"
 
 darshan_fd darshan_log_open(const char *name);
 darshan_fd darshan_log_create(const char *name, enum darshan_comp_type comp_type,


=====================================
darshan-util/darshan-stdio-logutils.c
=====================================
--- /dev/null
+++ b/darshan-util/darshan-stdio-logutils.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2015 University of Chicago.
+ * See COPYRIGHT notice in top-level directory.
+ *
+ */
+
+#define _GNU_SOURCE
+#include "darshan-util-config.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "darshan-logutils.h"
+
+/* integer counter name strings for the STDIO module */
+#define X(a) #a,
+char *stdio_counter_names[] = {
+    STDIO_COUNTERS
+};
+
+/* floating point counter name strings for the STDIO module */
+char *stdio_f_counter_names[] = {
+    STDIO_F_COUNTERS
+};
+#undef X
+
+/* prototypes for each of the STDIO module's logutil functions */
+static int darshan_log_get_stdio_record(darshan_fd fd, void* stdio_buf);
+static int darshan_log_put_stdio_record(darshan_fd fd, void* stdio_buf, int ver);
+static void darshan_log_print_stdio_record(void *file_rec,
+    char *file_name, char *mnt_pt, char *fs_type, int ver);
+static void darshan_log_print_stdio_description(void);
+static void darshan_log_print_stdio_record_diff(void *file_rec1, char *file_name1,
+    void *file_rec2, char *file_name2);
+
+/* structure storing each function needed for implementing the darshan
+ * logutil interface. these functions are used for reading, writing, and
+ * printing module data in a consistent manner.
+ */
+struct darshan_mod_logutil_funcs stdio_logutils =
+{
+    .log_get_record = &darshan_log_get_stdio_record,
+    .log_put_record = &darshan_log_put_stdio_record,
+    .log_print_record = &darshan_log_print_stdio_record,
+    .log_print_description = &darshan_log_print_stdio_description,
+    .log_print_diff = &darshan_log_print_stdio_record_diff
+};
+
+/* retrieve a STDIO record from log file descriptor 'fd', storing the
+ * buffer in 'stdio_buf'. Return 1 on successful record read, 0 on no 
+ * more data, and -1 on error.
+ */
+static int darshan_log_get_stdio_record(darshan_fd fd, void* stdio_buf)
+{
+    struct darshan_stdio_file *file;
+    int i;
+    int ret;
+
+    /* read a STDIO module record from the darshan log file */
+    ret = darshan_log_get_mod(fd, DARSHAN_STDIO_MOD, stdio_buf,
+        sizeof(struct darshan_stdio_file));
+    if(ret < 0)
+        return(-1);
+    else if(ret < sizeof(struct darshan_stdio_file))
+        return(0);
+    else
+    {
+        /* if the read was successful, do any necessary byte-swapping */
+        file = (struct darshan_stdio_file *)stdio_buf;
+        if(fd->swap_flag)
+        {
+            /* swap bytes if necessary */
+            DARSHAN_BSWAP64(&file->base_rec.id);
+            DARSHAN_BSWAP64(&file->base_rec.rank);
+            for(i=0; i<STDIO_NUM_INDICES; i++)
+                DARSHAN_BSWAP64(&file->counters[i]);
+            for(i=0; i<STDIO_F_NUM_INDICES; i++)
+                DARSHAN_BSWAP64(&file->fcounters[i]);
+        }
+
+        return(1);
+    }
+}
+
+/* write the STDIO record stored in 'stdio_buf' to log file descriptor 'fd'.
+ * Return 0 on success, -1 on failure
+ */
+static int darshan_log_put_stdio_record(darshan_fd fd, void* stdio_buf, int ver)
+{
+    struct darshan_stdio_file *rec = (struct darshan_stdio_file *)stdio_buf;
+    int ret;
+
+    /* append STDIO record to darshan log file */
+    ret = darshan_log_put_mod(fd, DARSHAN_STDIO_MOD, rec,
+        sizeof(struct darshan_stdio_file), ver);
+    if(ret < 0)
+        return(-1);
+
+    return(0);
+}
+
+/* print all I/O data record statistics for the given STDIO record */
+static void darshan_log_print_stdio_record(void *file_rec, char *file_name,
+    char *mnt_pt, char *fs_type, int ver)
+{
+    int i;
+    struct darshan_stdio_file *stdio_rec =
+        (struct darshan_stdio_file *)file_rec;
+
+    /* print each of the integer and floating point counters for the STDIO module */
+    for(i=0; i<STDIO_NUM_INDICES; i++)
+    {
+        /* macro defined in darshan-logutils.h */
+        DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+            stdio_rec->base_rec.rank, stdio_rec->base_rec.id, stdio_counter_names[i],
+            stdio_rec->counters[i], file_name, mnt_pt, fs_type);
+    }
+
+    for(i=0; i<STDIO_F_NUM_INDICES; i++)
+    {
+        /* macro defined in darshan-logutils.h */
+        DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+            stdio_rec->base_rec.rank, stdio_rec->base_rec.id, stdio_f_counter_names[i],
+            stdio_rec->fcounters[i], file_name, mnt_pt, fs_type);
+    }
+
+    return;
+}
+
+/* print out a description of the STDIO module record fields */
+static void darshan_log_print_stdio_description()
+{
+    printf("\n# description of STDIO counters:\n");
+    printf("#   STDIO_{OPENS|WRITES|READS|SEEKS|FLUSHES} are types of operations.\n");
+    printf("#   STDIO_BYTES_*: total bytes read and written.\n");
+    printf("#   STDIO_MAX_BYTE_*: highest offset byte read and written.\n");
+    printf("#   STDIO_F_*_START_TIMESTAMP: timestamp of the first call to that type of function.\n");
+    printf("#   STDIO_F_*_END_TIMESTAMP: timestamp of the completion of the last call to that type of function.\n");
+    printf("#   STDIO_F_*_TIME: cumulative time spent in different types of functions.\n");
+
+    return;
+}
+
+static void darshan_log_print_stdio_record_diff(void *file_rec1, char *file_name1,
+    void *file_rec2, char *file_name2)
+{
+    struct darshan_stdio_file *file1 = (struct darshan_stdio_file *)file_rec1;
+    struct darshan_stdio_file *file2 = (struct darshan_stdio_file *)file_rec2;
+    int i;
+
+    /* NOTE: we assume that both input records are the same module format version */
+
+    for(i=0; i<STDIO_NUM_INDICES; i++)
+    {
+        if(!file2)
+        {
+            printf("- ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file1->base_rec.rank, file1->base_rec.id, stdio_counter_names[i],
+                file1->counters[i], file_name1, "", "");
+
+        }
+        else if(!file1)
+        {
+            printf("+ ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file2->base_rec.rank, file2->base_rec.id, stdio_counter_names[i],
+                file2->counters[i], file_name2, "", "");
+        }
+        else if(file1->counters[i] != file2->counters[i])
+        {
+            printf("- ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file1->base_rec.rank, file1->base_rec.id, stdio_counter_names[i],
+                file1->counters[i], file_name1, "", "");
+            printf("+ ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file2->base_rec.rank, file2->base_rec.id, stdio_counter_names[i],
+                file2->counters[i], file_name2, "", "");
+        }
+    }
+
+    for(i=0; i<STDIO_F_NUM_INDICES; i++)
+    {
+        if(!file2)
+        {
+            printf("- ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file1->base_rec.rank, file1->base_rec.id, stdio_f_counter_names[i],
+                file1->fcounters[i], file_name1, "", "");
+
+        }
+        else if(!file1)
+        {
+            printf("+ ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file2->base_rec.rank, file2->base_rec.id, stdio_f_counter_names[i],
+                file2->fcounters[i], file_name2, "", "");
+        }
+        else if(file1->fcounters[i] != file2->fcounters[i])
+        {
+            printf("- ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file1->base_rec.rank, file1->base_rec.id, stdio_f_counter_names[i],
+                file1->fcounters[i], file_name1, "", "");
+            printf("+ ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_STDIO_MOD],
+                file2->base_rec.rank, file2->base_rec.id, stdio_f_counter_names[i],
+                file2->fcounters[i], file_name2, "", "");
+        }
+    }
+
+    return;
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */


=====================================
darshan-util/darshan-stdio-logutils.h
=====================================
--- /dev/null
+++ b/darshan-util/darshan-stdio-logutils.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 University of Chicago.
+ * See COPYRIGHT notice in top-level directory.
+ *
+ */
+
+#ifndef __DARSHAN_STDIO_LOG_UTILS_H
+#define __DARSHAN_STDIO_LOG_UTILS_H
+
+/* declare STDIO module counter name strings and logutil definition as
+ * extern variables so they can be used in other utilities
+ */
+extern char *stdio_counter_names[];
+extern char *stdio_f_counter_names[];
+
+extern struct darshan_mod_logutil_funcs stdio_logutils;
+
+#endif


=====================================
darshan-util/darshan-util-config.h.in
=====================================
--- a/darshan-util/darshan-util-config.h.in
+++ b/darshan-util/darshan-util-config.h.in
@@ -54,6 +54,9 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 



View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/compare/2770f997eeb71e87401465da6348bc87b5d3c440...5c5e44529f283a8a2be44808af744b333133e756
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/darshan-commits/attachments/20160706/42eee583/attachment-0001.html>


More information about the Darshan-commits mailing list