darshan-stdio.c 33.3 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

Philip Carns's avatar
Philip Carns committed
7 8
/* TODO list (general) for this module:
 * - add stdio page to darshan-job-summary
Philip Carns's avatar
Philip Carns committed
9 10
 * - update darshan-parser to include stdio information in any relevant 
 *   performance estimate / summary modes
Philip Carns's avatar
Philip Carns committed
11 12
 * - figure out what to do about posix module compatibility
 *   - remove stdio counters in POSIX or keep and set to -1?
Philip Carns's avatar
Philip Carns committed
13 14 15 16 17
 *   - affected counters in posix module:
 *     - POSIX_FOPENS
 *     - POSIX_FREADS
 *     - POSIX_FWRITES
 *     - POSIX_FSEEKS
Philip Carns's avatar
Philip Carns committed
18 19
 */

Philip Carns's avatar
Philip Carns committed
20 21 22 23 24
/* catalog of stdio functions instrumented by this module
 *
 * functions for opening streams
 * --------------
 * FILE    *fdopen(int, const char *);                      DONE
Philip Carns's avatar
Philip Carns committed
25
 * FILE    *fopen(const char *, const char *);              DONE
Philip Carns's avatar
Philip Carns committed
26
 * FILE    *fopen64(const char *, const char *);            DONE
Philip Carns's avatar
Philip Carns committed
27
 * FILE    *freopen(const char *, const char *, FILE *);    DONE
Philip Carns's avatar
Philip Carns committed
28
 * FILE    *freopen64(const char *, const char *, FILE *);  DONE
Philip Carns's avatar
Philip Carns committed
29 30 31 32 33 34 35
 *
 * functions for closing streams
 * --------------
 * int      fclose(FILE *);                                 DONE
 *
 * functions for flushing streams
 * --------------
Philip Carns's avatar
Philip Carns committed
36
 * int      fflush(FILE *);                                 DONE
Philip Carns's avatar
Philip Carns committed
37 38 39
 *
 * functions for reading data
 * --------------
Philip Carns's avatar
Philip Carns committed
40
 * int      fgetc(FILE *);                                  DONE
Philip Carns's avatar
Philip Carns committed
41
 * char    *fgets(char *, int, FILE *);                     DONE
Philip Carns's avatar
Philip Carns committed
42
 * size_t   fread(void *, size_t, size_t, FILE *);          DONE
Philip Carns's avatar
Philip Carns committed
43 44
 * int      fscanf(FILE *, const char *, ...);              DONE
 * int      vfscanf(FILE *, const char *, va_list);         DONE
Philip Carns's avatar
Philip Carns committed
45
 * int      getc(FILE *);                                   DONE
Philip Carns's avatar
Philip Carns committed
46
 * int      getw(FILE *);                                   DONE
Philip Carns's avatar
Philip Carns committed
47 48 49
 *
 * functions for writing data
 * --------------
Philip Carns's avatar
Philip Carns committed
50 51
 * int      fprintf(FILE *, const char *, ...);             DONE
 * int      vfprintf(FILE *, const char *, va_list);        DONE
Philip Carns's avatar
Philip Carns committed
52
 * int      fputc(int, FILE *);                             DONE
Philip Carns's avatar
Philip Carns committed
53
 * int      fputs(const char *, FILE *);                    DONE
Philip Carns's avatar
Philip Carns committed
54
 * size_t   fwrite(const void *, size_t, size_t, FILE *);   DONE
Philip Carns's avatar
Philip Carns committed
55
 * int      putc(int, FILE *);                              DONE
Philip Carns's avatar
Philip Carns committed
56
 * int      putw(int, FILE *);                              DONE
Philip Carns's avatar
Philip Carns committed
57 58 59 60
 *
 * functions for changing file position
 * --------------
 * int      fseek(FILE *, long int, int);                   DONE
Philip Carns's avatar
Philip Carns committed
61
 * int      fseeko(FILE *, off_t, int);                     DONE
Philip Carns's avatar
Philip Carns committed
62
 * int      fseeko64(FILE *, off_t, int);                   DONE
Philip Carns's avatar
Philip Carns committed
63 64
 * int      fsetpos(FILE *, const fpos_t *);                DONE
 * int      fsetpos64(FILE *, const fpos_t *);              DONE
Philip Carns's avatar
Philip Carns committed
65
 * void     rewind(FILE *);                                 DONE
Philip Carns's avatar
Philip Carns committed
66
 *
67 68 69 70 71
 * 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()
Philip Carns's avatar
Philip Carns committed
72 73
 */

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#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));
Philip Carns's avatar
Philip Carns committed
100
DARSHAN_FORWARD_DECL(fdopen, FILE*, (int fd, const char *mode));
Philip Carns's avatar
Philip Carns committed
101
DARSHAN_FORWARD_DECL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
Philip Carns's avatar
Philip Carns committed
102
DARSHAN_FORWARD_DECL(freopen64, FILE*, (const char *path, const char *mode, FILE *stream));
103
DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
Philip Carns's avatar
Philip Carns committed
104
DARSHAN_FORWARD_DECL(fflush, int, (FILE *fp));
105
DARSHAN_FORWARD_DECL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
Philip Carns's avatar
Philip Carns committed
106
DARSHAN_FORWARD_DECL(fputc, int, (int c, FILE *stream));
Philip Carns's avatar
Philip Carns committed
107
DARSHAN_FORWARD_DECL(putw, int, (int w, FILE *stream));
Philip Carns's avatar
Philip Carns committed
108
DARSHAN_FORWARD_DECL(fputs, int, (const char *s, FILE *stream));
Philip Carns's avatar
Philip Carns committed
109 110
DARSHAN_FORWARD_DECL(fprintf, int, (FILE *stream, const char *format, ...));
DARSHAN_FORWARD_DECL(vfprintf, int, (FILE *stream, const char *format, va_list));
111
DARSHAN_FORWARD_DECL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
Philip Carns's avatar
Philip Carns committed
112
DARSHAN_FORWARD_DECL(fgetc, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
113
DARSHAN_FORWARD_DECL(getw, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
114
DARSHAN_FORWARD_DECL(_IO_getc, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
115
DARSHAN_FORWARD_DECL(_IO_putc, int, (int, FILE *stream));
Philip Carns's avatar
Philip Carns committed
116
DARSHAN_FORWARD_DECL(fscanf, int, (FILE *stream, const char *format, ...));
Philip Carns's avatar
Philip Carns committed
117
DARSHAN_FORWARD_DECL(__isoc99_fscanf, int, (FILE *stream, const char *format, ...));
Philip Carns's avatar
Philip Carns committed
118
DARSHAN_FORWARD_DECL(vfscanf, int, (FILE *stream, const char *format, va_list ap));
Philip Carns's avatar
Philip Carns committed
119
DARSHAN_FORWARD_DECL(fgets, char*, (char *s, int size, FILE *stream));
120
DARSHAN_FORWARD_DECL(fseek, int, (FILE *stream, long offset, int whence));
Philip Carns's avatar
Philip Carns committed
121
DARSHAN_FORWARD_DECL(fseeko, int, (FILE *stream, off_t offset, int whence));
Philip Carns's avatar
Philip Carns committed
122
DARSHAN_FORWARD_DECL(fseeko64, int, (FILE *stream, off_t offset, int whence));
Philip Carns's avatar
Philip Carns committed
123
DARSHAN_FORWARD_DECL(fsetpos, int, (FILE *stream, const fpos_t *pos));
124
DARSHAN_FORWARD_DECL(fsetpos64, int, (FILE *stream, const fpos64_t *pos));
Philip Carns's avatar
Philip Carns committed
125
DARSHAN_FORWARD_DECL(rewind, void, (FILE *stream));
126

127 128
/* structure to track stdio stats at runtime */
struct stdio_file_record_ref
129
{
130
    struct darshan_stdio_file* file_rec;
131 132 133 134 135 136 137 138 139 140 141 142
    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
{
143 144 145
    void *rec_id_hash;
    void *stream_hash;
    int file_rec_count;
146 147 148 149 150 151 152 153 154
};

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);
155 156 157 158 159 160
static void stdio_shutdown(
    MPI_Comm mod_comm,
    darshan_record_id *shared_recs,
    int shared_rec_count,
    void **stdio_buf,
    int *stdio_buf_sz);
161 162
static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
    int *len, MPI_Datatype *datatype);
163 164 165
static struct stdio_file_record_ref *stdio_track_new_file_record(
    darshan_record_id rec_id, const char *path);
static void stdio_cleanup_runtime();
166 167 168 169

#define STDIO_LOCK() pthread_mutex_lock(&stdio_runtime_mutex)
#define STDIO_UNLOCK() pthread_mutex_unlock(&stdio_runtime_mutex)

170 171 172 173 174 175 176 177 178 179 180 181 182
#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)

Philip Carns's avatar
Philip Carns committed
183
#define STDIO_RECORD_OPEN(__ret, __path, __tm1, __tm2) do { \
184 185 186
    darshan_record_id rec_id; \
    struct stdio_file_record_ref* rec_ref; \
    char *newpath; \
Philip Carns's avatar
Philip Carns committed
187
    if(__ret == NULL) break; \
188 189 190 191 192
    newpath = darshan_clean_file_path(__path); \
    if(!newpath) newpath = (char*)__path; \
    if(darshan_core_excluded_path(newpath)) { \
        if(newpath != (char*)__path) free(newpath); \
        break; \
Philip Carns's avatar
Philip Carns committed
193
    } \
194
    rec_id = darshan_core_gen_record_id(newpath); \
Philip Carns's avatar
Philip Carns committed
195
    rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash, &rec_id, sizeof(rec_id)); \
196 197 198 199 200 201 202 203 204 205 206 207 208 209
    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); \
Philip Carns's avatar
Philip Carns committed
210 211 212
} while(0)


213
#define STDIO_RECORD_READ(__fp, __bytes,  __tm1, __tm2) do{ \
214
    struct stdio_file_record_ref* rec_ref; \
215
    int64_t this_offset; \
Philip Carns's avatar
Philip Carns committed
216
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
217 218 219 220 221 222 223 224 225 226 227 228
    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); \
229 230
} while(0)

Philip Carns's avatar
Philip Carns committed
231
#define STDIO_RECORD_WRITE(__fp, __bytes,  __tm1, __tm2, __fflush_flag) do{ \
232
    struct stdio_file_record_ref* rec_ref; \
233
    int64_t this_offset; \
Philip Carns's avatar
Philip Carns committed
234
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
235 236 237 238 239 240
    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; \
Philip Carns's avatar
Philip Carns committed
241
    if(__fflush_flag) \
242
        rec_ref->file_rec->counters[STDIO_FLUSHES] += 1; \
Philip Carns's avatar
Philip Carns committed
243
    else \
244 245 246 247 248 249
        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); \
250
} while(0)
Philip Carns's avatar
Philip Carns committed
251

Philip Carns's avatar
Philip Carns committed
252
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
Philip Carns's avatar
Philip Carns committed
253 254 255 256
{
    FILE* ret;
    double tm1, tm2;

Philip Carns's avatar
Philip Carns committed
257
    MAP_OR_FAIL(fopen);
Philip Carns's avatar
Philip Carns committed
258 259

    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
260
    ret = __real_fopen(path, mode);
Philip Carns's avatar
Philip Carns committed
261 262
    tm2 = darshan_core_wtime();

263
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
264
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
265
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
266 267 268 269

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
270
FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
271 272
{
    FILE* ret;
Philip Carns's avatar
Philip Carns committed
273
    double tm1, tm2;
274 275 276

    MAP_OR_FAIL(fopen);

Philip Carns's avatar
Philip Carns committed
277
    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
278
    ret = __real_fopen64(path, mode);
Philip Carns's avatar
Philip Carns committed
279 280
    tm2 = darshan_core_wtime();

281
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
282
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
283
    STDIO_POST_RECORD();
284 285 286 287

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
288
FILE* DARSHAN_DECL(fdopen)(int fd, const char *mode)
289 290
{
    FILE* ret;
Philip Carns's avatar
Philip Carns committed
291
    double tm1, tm2;
292

Philip Carns's avatar
Philip Carns committed
293
    MAP_OR_FAIL(fdopen);
294

Philip Carns's avatar
Philip Carns committed
295
    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
296 297 298
    ret = __real_fdopen(fd, mode);
    tm2 = darshan_core_wtime();

299
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
300
    STDIO_RECORD_OPEN(ret, "UNKNOWN-FDOPEN", tm1, tm2);
301
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
302 303 304 305 306 307 308 309 310 311 312 313 314

    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);
Philip Carns's avatar
Philip Carns committed
315 316
    tm2 = darshan_core_wtime();

317
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
318
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
319
    STDIO_POST_RECORD();
320 321 322 323

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
324 325 326 327 328 329 330 331 332 333 334
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();

335
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
336
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
337
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
338 339 340 341 342

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
343 344 345 346 347 348 349 350 351 352 353
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();

354
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
355 356
    if(ret >= 0)
        STDIO_RECORD_WRITE(fp, 0, tm1, tm2, 1);
357
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
358 359 360 361

    return(ret);
}

362 363 364 365
int DARSHAN_DECL(fclose)(FILE *fp)
{
    double tm1, tm2;
    int ret;
366
    struct stdio_file_record_ref *rec_ref;
367 368 369 370 371 372 373

    MAP_OR_FAIL(fclose);

    tm1 = darshan_core_wtime();
    ret = __real_fclose(fp);
    tm2 = darshan_core_wtime();

374 375 376
    STDIO_PRE_RECORD();
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &fp, sizeof(fp));
    if(rec_ref)
377
    {
378 379 380 381
        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;
382
        DARSHAN_TIMER_INC_NO_OVERLAP(
383 384 385
            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));
386
    }
387
    STDIO_POST_RECORD();
388 389 390 391

    return(ret);
}

392 393 394 395 396 397 398 399 400 401 402
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();

403
    STDIO_PRE_RECORD();
404
    if(ret > 0)
Philip Carns's avatar
Philip Carns committed
405
        STDIO_RECORD_WRITE(stream, size*ret, tm1, tm2, 0);
406
    STDIO_POST_RECORD();
407 408 409 410

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
411 412 413 414 415 416 417 418 419 420 421 422

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();

423
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
424 425
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
426
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
427 428 429 430

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
431 432 433 434 435 436 437 438 439 440 441
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();

442
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
443 444
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, sizeof(int), tm1, tm2, 0);
445
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
446 447 448 449 450

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
451 452 453 454 455 456 457 458 459 460 461 462

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();

463
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
464 465
    if(ret != EOF && ret > 0)
        STDIO_RECORD_WRITE(stream, strlen(s), tm1, tm2, 0);
466
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
467 468 469 470

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
471 472 473 474 475 476 477 478 479 480 481 482 483 484
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();

485
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
486 487
    if(ret > 0)
        STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
488
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513

    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();

514
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
515 516
    if(ret > 0)
        STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
517
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
518 519 520 521

    return(ret);
}

522 523 524 525 526 527 528 529 530 531 532
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();

533
    STDIO_PRE_RECORD();
534 535
    if(ret > 0)
        STDIO_RECORD_READ(stream, size*ret, tm1, tm2);
536
    STDIO_POST_RECORD();
537 538 539 540

    return(ret);
}

541
int DARSHAN_DECL(fgetc)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
542 543 544 545 546 547 548 549 550 551
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(fgetc);

    tm1 = darshan_core_wtime();
    ret = __real_fgetc(stream);
    tm2 = darshan_core_wtime();

552
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
553 554
    if(ret != EOF)
        STDIO_RECORD_READ(stream, 1, tm1, tm2);
555
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
556 557 558 559 560

    return(ret);
}

/* NOTE: stdio.h typically implements getc() as a macro pointing to _IO_getc */
561
int DARSHAN_DECL(_IO_getc)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
562 563 564 565 566 567 568 569 570 571
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(_IO_getc);

    tm1 = darshan_core_wtime();
    ret = __real__IO_getc(stream);
    tm2 = darshan_core_wtime();

572
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
573 574
    if(ret != EOF)
        STDIO_RECORD_READ(stream, 1, tm1, tm2);
575
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
576 577 578 579

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
580
/* NOTE: stdio.h typically implements putc() as a macro pointing to _IO_putc */
581
int DARSHAN_DECL(_IO_putc)(int c, FILE *stream)
Philip Carns's avatar
Philip Carns committed
582 583 584 585 586 587 588 589 590 591
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(_IO_putc);

    tm1 = darshan_core_wtime();
    ret = __real__IO_putc(c, stream);
    tm2 = darshan_core_wtime();

592
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
593 594
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
595
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
596 597 598

    return(ret);
}
599 600

int DARSHAN_DECL(getw)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
601 602 603 604 605 606 607 608 609 610
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(getw);

    tm1 = darshan_core_wtime();
    ret = __real_getw(stream);
    tm2 = darshan_core_wtime();

611
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
612 613
    if(ret != EOF || ferror(stream) == 0)
        STDIO_RECORD_READ(stream, sizeof(int), tm1, tm2);
614
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
615 616 617 618

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
/* 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();

642
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
643 644
    if(ret != 0)
        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
645
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
646 647 648 649

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
650

Philip Carns's avatar
Philip Carns committed
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
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();

671
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
672
    if(ret != 0)
Philip Carns's avatar
Philip Carns committed
673
        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
674
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692

    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();

693
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
694 695
    if(ret != 0)
        STDIO_RECORD_READ(stream, end_off-start_off, tm1, tm2);
696
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
697 698 699 700 701

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
702 703 704 705 706 707 708 709 710 711 712
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();

713
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
714 715
    if(ret != NULL)
        STDIO_RECORD_READ(stream, strlen(ret), tm1, tm2);
716
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
717 718 719 720 721

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
722 723 724
void DARSHAN_DECL(rewind)(FILE *stream)
{
    double tm1, tm2;
725
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
726 727 728 729 730 731 732

    MAP_OR_FAIL(rewind);

    tm1 = darshan_core_wtime();
    __real_rewind(stream);
    tm2 = darshan_core_wtime();

733 734 735
    /* NOTE: we don't use STDIO_PRE_RECORD here because there is no return
     * value in this wrapper.
     */
Philip Carns's avatar
Philip Carns committed
736
    STDIO_LOCK();
737 738 739 740 741 742 743 744 745
    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)
Philip Carns's avatar
Philip Carns committed
746
    {
747
        rec_ref->offset = 0;
Philip Carns's avatar
Philip Carns committed
748
        DARSHAN_TIMER_INC_NO_OVERLAP(
749 750 751
            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
            tm1, tm2, rec_ref->last_meta_end);
        rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
752
    }
753
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
754 755 756 757

    return;
}

758 759 760
int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
{
    int ret;
761
    struct stdio_file_record_ref *rec_ref;
762 763 764 765 766 767 768 769 770 771
    double tm1, tm2;

    MAP_OR_FAIL(fseek);

    tm1 = darshan_core_wtime();
    ret = __real_fseek(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
772 773 774
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
775
        {
776
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
777
            DARSHAN_TIMER_INC_NO_OVERLAP(
778 779 780
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
781
        }
782
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
783 784 785 786 787 788 789 790
    }

    return(ret);
}

int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
{
    int ret;
791
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
792 793 794 795 796 797 798 799 800 801
    double tm1, tm2;

    MAP_OR_FAIL(fseeko);

    tm1 = darshan_core_wtime();
    ret = __real_fseeko(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
802 803 804
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
805
        {
806
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
807
            DARSHAN_TIMER_INC_NO_OVERLAP(
808 809 810
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
811
        }
812
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
813 814 815 816 817 818 819 820
    }

    return(ret);
}

int DARSHAN_DECL(fseeko64)(FILE *stream, off_t offset, int whence)
{
    int ret;
821
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
822 823 824 825 826 827 828 829 830 831
    double tm1, tm2;

    MAP_OR_FAIL(fseeko64);

    tm1 = darshan_core_wtime();
    ret = __real_fseeko64(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
832 833 834
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
835
        {
836
            rec_ref->offset = ftell(stream);
837
            DARSHAN_TIMER_INC_NO_OVERLAP(
838 839 840
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
841
        }
842
        STDIO_POST_RECORD();
843 844 845 846 847
    }

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
848 849 850
int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
{
    int ret;
851
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
852 853 854 855 856 857 858 859 860 861
    double tm1, tm2;

    MAP_OR_FAIL(fsetpos);

    tm1 = darshan_core_wtime();
    ret = __real_fsetpos(stream, pos);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
862 863 864
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
865
        {
866
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
867
            DARSHAN_TIMER_INC_NO_OVERLAP(
868 869 870
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
871
        }
872
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
873 874 875 876 877
    }

    return(ret);
}

878
int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos64_t *pos)
Philip Carns's avatar
Philip Carns committed
879 880
{
    int ret;
881
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
882 883 884 885 886 887 888 889 890 891
    double tm1, tm2;

    MAP_OR_FAIL(fsetpos64);

    tm1 = darshan_core_wtime();
    ret = __real_fsetpos64(stream, pos);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
892 893 894
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
895
        {
896
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
897
            DARSHAN_TIMER_INC_NO_OVERLAP(
898 899 900
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
901
        }
902
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
903 904 905 906 907 908
    }

    return(ret);
}


909 910 911 912 913 914 915
/**********************************************************
 * Internal functions for manipulating STDIO module state *
 **********************************************************/

/* initialize internal STDIO module data structures and register with darshan-core */
static void stdio_runtime_initialize()
{
916 917 918 919
    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);
920 921 922 923 924 925 926 927

    /* 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,
928 929
        &stdio_shutdown,
        &stdio_buf_size,
930
        &my_rank,
931 932
        &darshan_mem_alignment);

933 934 935 936
    /* 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);
937
        return;
938
    }
939 940 941 942

    stdio_runtime = malloc(sizeof(*stdio_runtime));
    if(!stdio_runtime)
    {
943
        darshan_core_unregister_module(DARSHAN_STDIO_MOD);
944 945
        return;
    }
946
    memset(stdio_runtime, 0, sizeof(*stdio_runtime));
947 948
}

949 950 951
/************************************************************************
 * Functions exported by this module for coordinating with darshan-core *
 ************************************************************************/
952

953 954
static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
    int *len, MPI_Datatype *datatype)
955
{
956 957 958 959
    struct darshan_stdio_file tmp_file;
    struct darshan_stdio_file *infile = infile_v;
    struct darshan_stdio_file *inoutfile = inoutfile_v;
    int i, j;
960

961
    assert(stdio_runtime);
962

963
    for(i=0; i<*len; i++)
964
    {
965 966 967
        memset(&tmp_file, 0, sizeof(struct darshan_stdio_file));
        tmp_file.base_rec.id = infile->base_rec.id;
        tmp_file.base_rec.rank = -1;
968

969 970 971 972 973 974 975 976 977 978 979 980 981 982
        /* 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];
        }
983

984 985 986 987 988
        /* sum */
        for(j=STDIO_F_META_TIME; j<=STDIO_F_READ_TIME; j++)
        {
            tmp_file.fcounters[j] = infile->fcounters[j] + inoutfile->fcounters[j];
        }
989

990 991 992 993 994 995 996 997 998
        /* 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];
        }
999

1000 1001 1002 1003 1004 1005 1006 1007
        /* 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];
        }
1008

1009 1010 1011 1012
        /* update pointers */
        *inoutfile = tmp_file;
        inoutfile++;
        infile++;
1013 1014 1015 1016 1017
    }

    return;
}

1018
static void stdio_shutdown(
1019 1020 1021 1022 1023 1024
    MPI_Comm mod_comm,
    darshan_record_id *shared_recs,
    int shared_rec_count,
    void **stdio_buf,
    int *stdio_buf_sz)
{
1025 1026
    struct stdio_file_record_ref *rec_ref;
    struct darshan_stdio_file *stdio_rec_buf = *(struct darshan_stdio_file **)stdio_buf;
1027
    int i;
1028 1029
    struct darshan_stdio_file *red_send_buf = NULL;
    struct darshan_stdio_file *red_recv_buf = NULL;
1030 1031
    MPI_Datatype red_type;
    MPI_Op red_op;
1032
    int stdio_rec_count;
1033

1034
    STDIO_LOCK();
1035
    assert(stdio_runtime);
1036
    stdio_rec_count = stdio_runtime->file_rec_count;
1037

1038 1039 1040 1041 1042 1043 1044 1045 1046
    /* 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++)
        {
1047 1048 1049
            rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash,
                &shared_recs[i], sizeof(darshan_record_id));
            assert(rec_ref);
1050

1051
            rec_ref->file_rec->base_rec.rank = -1;