darshan-posix.c 39.1 KB
Newer Older
1 2 3 4 5
/*
 *  (C) 2009 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

6
#include "darshan-runtime-config.h"
7 8 9 10 11 12 13 14 15 16 17 18 19 20
#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>
21
#include <libgen.h>
22
#include <limits.h>
23
#include <aio.h>
24 25
#define __USE_GNU
#include <pthread.h>
26 27 28

#include "darshan.h"

29
#ifndef HAVE_OFF64_T
30 31
typedef int64_t off64_t;
#endif
32 33 34
#ifndef HAVE_AIOCB64
#define aiocb64 aiocb
#endif
35

36 37 38 39 40
#define DARSHAN_FORWARD_DECL(name,ret,args) \
  extern ret __real_ ## name args;

#define DARSHAN_DECL(__name) __wrap_ ## __name

41 42 43 44
#define MAP_OR_FAIL(func)

#define DARSHAN_MPI_CALL(func) func

45 46 47 48 49 50 51 52 53 54 55 56
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(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(close, int, (int fd));
DARSHAN_FORWARD_DECL(write, ssize_t, (int fd, const void *buf, size_t count));
DARSHAN_FORWARD_DECL(read, ssize_t, (int fd, void *buf, size_t count));
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(pread, ssize_t, (int fd, void *buf, size_t count, off_t offset));
DARSHAN_FORWARD_DECL(pread64, ssize_t, (int fd, void *buf, size_t count, off64_t offset));
DARSHAN_FORWARD_DECL(pwrite, ssize_t, (int fd, const void *buf, size_t count, off_t offset));
57
DARSHAN_FORWARD_DECL(pwrite64, ssize_t, (int fd, const void *buf, size_t count, off64_t offset));
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
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(__fxstat, int, (int vers, int fd, struct stat *buf));
DARSHAN_FORWARD_DECL(__fxstat64, int, (int vers, int fd, struct stat64 *buf));
DARSHAN_FORWARD_DECL(__lxstat, int, (int vers, const char* path, struct stat *buf));
DARSHAN_FORWARD_DECL(__lxstat64, int, (int vers, const char* path, struct stat64 *buf));
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(mmap, void*, (void *addr, size_t length, int prot, int flags, int fd, off_t offset));
DARSHAN_FORWARD_DECL(mmap64, void*, (void *addr, size_t length, int prot, int flags, int fd, off64_t offset));
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(fclose, int, (FILE *fp));
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(fseek, int, (FILE *stream, long offset, int whence));
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
76
DARSHAN_FORWARD_DECL(aio_read, int, (struct aiocb *aiocbp));
77
DARSHAN_FORWARD_DECL(aio_read64, int, (struct aiocb64 *aiocbp));
78
DARSHAN_FORWARD_DECL(aio_write, int, (struct aiocb *aiocbp));
79
DARSHAN_FORWARD_DECL(aio_write64, int, (struct aiocb64 *aiocbp));
80
DARSHAN_FORWARD_DECL(lio_listio, int, (int mode, struct aiocb *const aiocb_list[], int nitems, struct sigevent *sevp));
81
DARSHAN_FORWARD_DECL(lio_listio64, int, (int mode, struct aiocb64 *const aiocb_list[], int nitems, struct sigevent *sevp));
82
DARSHAN_FORWARD_DECL(aio_return, ssize_t, (struct aiocb *aiocbp));
83
DARSHAN_FORWARD_DECL(aio_return64, ssize_t, (struct aiocb64 *aiocbp));
84

85 86 87 88
/* struct to track information about aio operations in flight */
struct darshan_aio_tracker
{
    double tm1;
89
    void *aiocbp;
90 91 92
    struct darshan_aio_tracker* next;
};

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
/* these are paths that we will not trace */
static char* exclusions[] = {
"/etc/",
"/dev/",
"/usr/",
"/bin/",
"/boot/",
"/lib/",
"/opt/",
"/sbin/",
"/sys/",
"/proc/",
NULL
};

108 109 110 111
static int darshan_mem_alignment = 1;

static int posix_mod_initialized = 0;
static pthread_mutex_t posix_mod_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
112

113
static void posix_runtime_initialize(void);
114
static double posix_wtime(void);
115

116 117 118
static void posix_prepare_for_shutdown(void);
static void posix_get_output_data(void **buffer, int size);

119 120 121
#define POSIX_LOCK() pthread_mutex_lock(&posix_mod_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_mod_mutex)

122
#if 0
123
static void cp_access_counter(struct darshan_file_runtime* file, ssize_t size,     enum cp_counter_type type);
124 125
static void darshan_aio_tracker_add(int fd, void *aiocbp);
static struct darshan_aio_tracker* darshan_aio_tracker_del(int fd, void *aiocbp);
126
#endif
127

128
#if 0
Philip Carns's avatar
Philip Carns committed
129
#define CP_RECORD_WRITE(__ret, __fd, __count, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
130
    size_t stride; \
Philip Carns's avatar
Philip Carns committed
131
    int64_t this_offset; \
132 133
    int64_t file_alignment; \
    struct darshan_file_runtime* file; \
134
    double __elapsed = __tm2-__tm1; \
135 136 137
    if(__ret < 0) break; \
    file = darshan_file_by_fd(__fd); \
    if(!file) break; \
Philip Carns's avatar
Philip Carns committed
138 139 140 141
    if(__pwrite_flag) \
        this_offset = __pwrite_offset; \
    else \
        this_offset = file->offset; \
142
    file_alignment = CP_VALUE(file, CP_FILE_ALIGNMENT); \
Philip Carns's avatar
Philip Carns committed
143
    if(this_offset > file->last_byte_written) \
144
        CP_INC(file, CP_SEQ_WRITES, 1); \
Philip Carns's avatar
Philip Carns committed
145
    if(this_offset == (file->last_byte_written + 1)) \
146
        CP_INC(file, CP_CONSEC_WRITES, 1); \
Philip Carns's avatar
Philip Carns committed
147
    if(this_offset > 0 && this_offset > file->last_byte_written \
148
        && file->last_byte_written != 0) \
Philip Carns's avatar
Philip Carns committed
149
        stride = this_offset - file->last_byte_written - 1; \
150 151
    else \
        stride = 0; \
Philip Carns's avatar
Philip Carns committed
152 153 154
    file->last_byte_written = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
    CP_MAX(file, CP_MAX_BYTE_WRITTEN, (this_offset + __ret -1)); \
155 156 157 158 159 160 161 162 163
    CP_INC(file, CP_BYTES_WRITTEN, __ret); \
    if(__stream_flag) \
        CP_INC(file, CP_POSIX_FWRITES, 1); \
    else \
        CP_INC(file, CP_POSIX_WRITES, 1); \
    CP_BUCKET_INC(file, CP_SIZE_WRITE_0_100, __ret); \
    cp_access_counter(file, stride, CP_COUNTER_STRIDE); \
    if(!__aligned) \
        CP_INC(file, CP_MEM_NOT_ALIGNED, 1); \
164
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
165 166 167 168 169
        CP_INC(file, CP_FILE_NOT_ALIGNED, 1); \
    cp_access_counter(file, __ret, CP_COUNTER_ACCESS); \
    if(file->last_io_type == CP_READ) \
        CP_INC(file, CP_RW_SWITCHES, 1); \
    file->last_io_type = CP_WRITE; \
170
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
171 172 173
    if(CP_F_VALUE(file, CP_F_WRITE_START_TIMESTAMP) == 0) \
        CP_F_SET(file, CP_F_WRITE_START_TIMESTAMP, __tm1); \
    CP_F_SET(file, CP_F_WRITE_END_TIMESTAMP, __tm2); \
174 175 176
    if(CP_F_VALUE(file, CP_F_MAX_WRITE_TIME) < __elapsed){ \
        CP_F_SET(file, CP_F_MAX_WRITE_TIME, __elapsed); \
        CP_SET(file, CP_MAX_WRITE_TIME_SIZE, __ret); } \
177 178
} while(0)

179
#define CP_RECORD_READ(__ret, __fd, __count, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
180
    size_t stride; \
181
    int64_t this_offset; \
182 183
    struct darshan_file_runtime* file; \
    int64_t file_alignment; \
184
    double __elapsed = __tm2-__tm1; \
185 186 187
    if(__ret < 0) break; \
    file = darshan_file_by_fd(__fd); \
    if(!file) break; \
188 189 190 191
    if(__pread_flag)\
        this_offset = __pread_offset; \
    else \
        this_offset = file->offset; \
192
    file_alignment = CP_VALUE(file, CP_FILE_ALIGNMENT); \
193
    if(this_offset > file->last_byte_read) \
194
        CP_INC(file, CP_SEQ_READS, 1); \
195
    if(this_offset == (file->last_byte_read + 1)) \
196
        CP_INC(file, CP_CONSEC_READS, 1); \
197
    if(this_offset > 0 && this_offset > file->last_byte_read \
198
        && file->last_byte_read != 0) \
199
        stride = this_offset - file->last_byte_read - 1; \
200 201
    else \
        stride = 0; \
202 203 204
    file->last_byte_read = this_offset + __ret - 1; \
    CP_MAX(file, CP_MAX_BYTE_READ, (this_offset + __ret -1)); \
    file->offset = this_offset + __ret; \
205 206 207 208 209 210 211 212 213
    CP_INC(file, CP_BYTES_READ, __ret); \
    if(__stream_flag)\
        CP_INC(file, CP_POSIX_FREADS, 1); \
    else\
        CP_INC(file, CP_POSIX_READS, 1); \
    CP_BUCKET_INC(file, CP_SIZE_READ_0_100, __ret); \
    cp_access_counter(file, stride, CP_COUNTER_STRIDE); \
    if(!__aligned) \
        CP_INC(file, CP_MEM_NOT_ALIGNED, 1); \
214
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
215 216 217 218 219
        CP_INC(file, CP_FILE_NOT_ALIGNED, 1); \
    cp_access_counter(file, __ret, CP_COUNTER_ACCESS); \
    if(file->last_io_type == CP_WRITE) \
        CP_INC(file, CP_RW_SWITCHES, 1); \
    file->last_io_type = CP_READ; \
220
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_read_end, CP_F_POSIX_READ_TIME); \
221 222 223
    if(CP_F_VALUE(file, CP_F_READ_START_TIMESTAMP) == 0) \
        CP_F_SET(file, CP_F_READ_START_TIMESTAMP, __tm1); \
    CP_F_SET(file, CP_F_READ_END_TIMESTAMP, __tm2); \
224 225 226
    if(CP_F_VALUE(file, CP_F_MAX_READ_TIME) < __elapsed){ \
        CP_F_SET(file, CP_F_MAX_READ_TIME, __elapsed); \
        CP_SET(file, CP_MAX_READ_TIME_SIZE, __ret); } \
227 228
} while(0)

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
#define CP_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
    char* exclude; \
    int tmp_index = 0; \
    struct darshan_file_runtime* file; \
    while((exclude = exclusions[tmp_index])) { \
        if(!(strncmp(exclude, __path, strlen(exclude)))) \
            break; \
        tmp_index++; \
    } \
    if(exclude) break; \
    file = darshan_file_by_name(__path); \
    if (file) \
    { \
        CP_RECORD_STAT(file, __statbuf, __tm1, __tm2); \
    } \
} while(0)

    
247
#define CP_RECORD_STAT(__file, __statbuf, __tm1, __tm2) do { \
248
    if(!CP_VALUE((__file), CP_POSIX_STATS) && !CP_VALUE((__file), CP_POSIX_OPENS)){ \
249 250 251 252
        CP_SET((__file), CP_FILE_ALIGNMENT, (__statbuf)->st_blksize); \
        CP_SET((__file), CP_SIZE_AT_OPEN, (__statbuf)->st_size); \
    }\
    (__file)->log_file->rank = my_rank; \
253
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME); \
254 255 256
    CP_INC(__file, CP_POSIX_STATS, 1); \
} while(0)

257
#ifdef __CP_STAT_AT_OPEN
258
#define CP_STAT_FILE(_f, _p, _r) do { \
259
    if(!CP_VALUE((_f), CP_POSIX_STATS) && !CP_VALUE((_f), CP_POSIX_OPENS)){ \
260
        if(fstat64(_r, &cp_stat_buf) == 0) { \
261 262 263 264 265 266
            CP_SET(_f, CP_FILE_ALIGNMENT, cp_stat_buf.st_blksize); \
            CP_SET(_f, CP_SIZE_AT_OPEN, cp_stat_buf.st_size); \
        }\
    }\
}while(0)
#else
267
#define CP_STAT_FILE(_f, _p, _r) do { }while(0)
268 269
#endif

270 271 272 273 274 275 276 277 278 279 280
#define CP_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
    struct darshan_file_runtime* file; \
    char* exclude; \
    int tmp_index = 0; \
    if(__ret < 0) break; \
    while((exclude = exclusions[tmp_index])) { \
        if(!(strncmp(exclude, __path, strlen(exclude)))) \
            break; \
        tmp_index++; \
    } \
    if(exclude) break; \
281
    file = darshan_file_by_name_setfd(__path, __ret); \
282
    if(!file) break; \
283
    CP_STAT_FILE(file, __path, __ret); \
284 285 286 287 288 289 290 291 292 293 294
    file->log_file->rank = my_rank; \
    if(__mode) \
        CP_SET(file, CP_MODE, __mode); \
    file->offset = 0; \
    file->last_byte_written = 0; \
    file->last_byte_read = 0; \
    if(__stream_flag)\
        CP_INC(file, CP_POSIX_FOPENS, 1); \
    else \
        CP_INC(file, CP_POSIX_OPENS, 1); \
    if(CP_F_VALUE(file, CP_F_OPEN_TIMESTAMP) == 0) \
295
        CP_F_SET(file, CP_F_OPEN_TIMESTAMP, __tm1); \
296
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME); \
297
} while (0)
298
#endif
299

300
int DARSHAN_DECL(close)(int fd)
301 302 303 304 305 306
{
    struct darshan_file_runtime* file;
    int tmp_fd = fd;
    double tm1, tm2;
    int ret;

307 308
    MAP_OR_FAIL(close);

309
    tm1 = darshan_core_wtime();
310
    ret = __real_close(fd);
311
    tm2 = darshan_core_wtime();
312

313 314 315 316
    POSIX_LOCK();
    posix_runtime_initialize();

#if 0
317 318 319 320 321
    file = darshan_file_by_fd(tmp_fd);
    if(file)
    {
        file->last_byte_written = 0;
        file->last_byte_read = 0;
322
        CP_F_SET(file, CP_F_CLOSE_TIMESTAMP, posix_wtime());
323
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
324
        darshan_file_close_fd(tmp_fd);
325
    }
326 327 328
#endif

    POSIX_UNLOCK();    
329 330 331 332

    return(ret);
}

333
#if 0
334
int DARSHAN_DECL(fclose)(FILE *fp)
335 336 337 338 339 340
{
    struct darshan_file_runtime* file;
    int tmp_fd = fileno(fp);
    double tm1, tm2;
    int ret;

341 342
    MAP_OR_FAIL(fclose);

343
    tm1 = darshan_core_wtime();
344
    ret = __real_fclose(fp);
345
    tm2 = darshan_core_wtime();
346 347 348 349 350 351 352
    
    CP_LOCK();
    file = darshan_file_by_fd(tmp_fd);
    if(file)
    {
        file->last_byte_written = 0;
        file->last_byte_read = 0;
353
        CP_F_SET(file, CP_F_CLOSE_TIMESTAMP, posix_wtime());
354
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
355
        darshan_file_close_fd(tmp_fd);
356 357 358 359 360 361 362
    }
    CP_UNLOCK();

    return(ret);
}


363
int DARSHAN_DECL(fsync)(int fd)
364 365 366 367 368
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

369 370
    MAP_OR_FAIL(fsync);

371
    tm1 = darshan_core_wtime();
372
    ret = __real_fsync(fd);
373
    tm2 = darshan_core_wtime();
374 375 376 377 378 379 380 381

    if(ret < 0)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
382
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
383 384 385 386 387 388 389
        CP_INC(file, CP_POSIX_FSYNCS, 1);
    }
    CP_UNLOCK();

    return(ret);
}

390
int DARSHAN_DECL(fdatasync)(int fd)
391 392 393 394 395
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

396 397
    MAP_OR_FAIL(fdatasync);

398
    tm1 = darshan_core_wtime();
399
    ret = __real_fdatasync(fd);
400
    tm2 = darshan_core_wtime();
401 402 403 404 405 406 407
    if(ret < 0)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
408
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
409 410 411 412 413 414 415 416
        CP_INC(file, CP_POSIX_FDSYNCS, 1);
    }
    CP_UNLOCK();

    return(ret);
}


417
void* DARSHAN_DECL(mmap64)(void *addr, size_t length, int prot, int flags,
418 419 420 421 422
    int fd, off64_t offset)
{
    void* ret;
    struct darshan_file_runtime* file;

423 424
    MAP_OR_FAIL(mmap64);

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    ret = __real_mmap64(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
        CP_INC(file, CP_POSIX_MMAPS, 1);
    }
    CP_UNLOCK();

    return(ret);
}


441
void* DARSHAN_DECL(mmap)(void *addr, size_t length, int prot, int flags,
442 443 444 445 446
    int fd, off_t offset)
{
    void* ret;
    struct darshan_file_runtime* file;

447 448
    MAP_OR_FAIL(mmap);

449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    ret = __real_mmap(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
        CP_INC(file, CP_POSIX_MMAPS, 1);
    }
    CP_UNLOCK();

    return(ret);
}

464
int DARSHAN_DECL(creat)(const char* path, mode_t mode)
465 466 467 468
{
    int ret;
    double tm1, tm2;

469 470
    MAP_OR_FAIL(creat);

471
    tm1 = darshan_core_wtime();
472
    ret = __real_creat(path, mode);
473
    tm2 = darshan_core_wtime();
474 475 476 477 478 479 480 481

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

482
int DARSHAN_DECL(creat64)(const char* path, mode_t mode)
483 484 485 486
{
    int ret;
    double tm1, tm2;

487 488
    MAP_OR_FAIL(creat64);

489
    tm1 = darshan_core_wtime();
490
    ret = __real_creat64(path, mode);
491
    tm2 = darshan_core_wtime();
492 493 494 495 496 497 498 499

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

500
int DARSHAN_DECL(open64)(const char* path, int flags, ...)
501 502 503 504 505
{
    int mode = 0;
    int ret;
    double tm1, tm2;

506 507
    MAP_OR_FAIL(open64);

508 509 510 511 512 513 514
    if (flags & O_CREAT) 
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

515
        tm1 = darshan_core_wtime();
516
        ret = __real_open64(path, flags, mode);
517
        tm2 = darshan_core_wtime();
518 519 520
    }
    else
    {
521
        tm1 = darshan_core_wtime();
522
        ret = __real_open64(path, flags);
523
        tm2 = darshan_core_wtime();
524 525 526 527 528 529 530 531
    }

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}
532
#endif
533

534
int DARSHAN_DECL(open)(const char *path, int flags, ...)
535 536 537 538 539
{
    int mode = 0;
    int ret;
    double tm1, tm2;

540 541
    MAP_OR_FAIL(open);

542 543 544 545 546 547 548
    if (flags & O_CREAT) 
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

549
        tm1 = darshan_core_wtime();
550
        ret = __real_open(path, flags, mode);
551
        tm2 = darshan_core_wtime();
552 553 554
    }
    else
    {
555
        tm1 = darshan_core_wtime();
556
        ret = __real_open(path, flags);
557
        tm2 = darshan_core_wtime();
558 559
    }

560 561 562 563 564
    POSIX_LOCK();
    posix_runtime_initialize();

//    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();
565 566 567 568

    return(ret);
}

569
#if 0
570
FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
571 572 573 574 575
{
    FILE* ret;
    int fd;
    double tm1, tm2;

576 577
    MAP_OR_FAIL(fopen64);

578
    tm1 = darshan_core_wtime();
579
    ret = __real_fopen64(path, mode);
580
    tm2 = darshan_core_wtime();
581 582 583 584 585 586 587 588 589 590 591 592
    if(ret == 0)
        fd = -1;
    else
        fd = fileno(ret);

    CP_LOCK();
    CP_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

593
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
594 595 596 597 598
{
    FILE* ret;
    int fd;
    double tm1, tm2;

599 600
    MAP_OR_FAIL(fopen);

601
    tm1 = darshan_core_wtime();
602
    ret = __real_fopen(path, mode);
603
    tm2 = darshan_core_wtime();
604 605 606 607 608 609 610 611 612 613 614 615
    if(ret == 0)
        fd = -1;
    else
        fd = fileno(ret);

    CP_LOCK();
    CP_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

616
int DARSHAN_DECL(__xstat64)(int vers, const char *path, struct stat64 *buf)
617 618 619 620
{
    int ret;
    double tm1, tm2;

621 622
    MAP_OR_FAIL(__xstat64);

623
    tm1 = darshan_core_wtime();
624
    ret = __real___xstat64(vers, path, buf);
625
    tm2 = darshan_core_wtime();
626 627 628 629
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
630
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
631 632 633 634 635
    CP_UNLOCK();

    return(ret);
}

636
int DARSHAN_DECL(__lxstat64)(int vers, const char *path, struct stat64 *buf)
637 638 639 640
{
    int ret;
    double tm1, tm2;

641 642
    MAP_OR_FAIL(__lxstat64);

643
    tm1 = darshan_core_wtime();
644
    ret = __real___lxstat64(vers, path, buf);
645
    tm2 = darshan_core_wtime();
646 647 648 649
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
650
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
651 652 653 654 655
    CP_UNLOCK();

    return(ret);
}

656
int DARSHAN_DECL(__fxstat64)(int vers, int fd, struct stat64 *buf)
657 658 659 660 661
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

662 663
    MAP_OR_FAIL(__fxstat64);

664
    tm1 = darshan_core_wtime();
665
    ret = __real___fxstat64(vers, fd, buf);
666
    tm2 = darshan_core_wtime();
667 668 669 670 671 672 673 674 675 676 677
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    /* skip logging if this was triggered internally */
    if(buf == &cp_stat_buf)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
678
        CP_RECORD_STAT(file, buf, tm1, tm2);
679 680 681 682 683 684 685
    }
    CP_UNLOCK();

    return(ret);
}


686
int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
687 688 689 690
{
    int ret;
    double tm1, tm2;

691 692
    MAP_OR_FAIL(__xstat);

693
    tm1 = darshan_core_wtime();
694
    ret = __real___xstat(vers, path, buf);
695
    tm2 = darshan_core_wtime();
696 697 698 699
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
700
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
701 702 703 704 705
    CP_UNLOCK();

    return(ret);
}

706
int DARSHAN_DECL(__lxstat)(int vers, const char *path, struct stat *buf)
707 708 709 710
{
    int ret;
    double tm1, tm2;

711 712
    MAP_OR_FAIL(__lxstat);

713
    tm1 = darshan_core_wtime();
714
    ret = __real___lxstat(vers, path, buf);
715
    tm2 = darshan_core_wtime();
716 717 718 719
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
720
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
721 722 723 724 725
    CP_UNLOCK();

    return(ret);
}

726
int DARSHAN_DECL(__fxstat)(int vers, int fd, struct stat *buf)
727 728 729 730 731
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

732 733
    MAP_OR_FAIL(__fxstat);

734
    tm1 = darshan_core_wtime();
735
    ret = __real___fxstat(vers, fd, buf);
736
    tm2 = darshan_core_wtime();
737 738 739 740
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    /* skip logging if this was triggered internally */
741
    if((void*)buf == (void*)&cp_stat_buf)
742 743 744 745 746 747
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
748
        CP_RECORD_STAT(file, buf, tm1, tm2);
749 750 751 752 753 754
    }
    CP_UNLOCK();

    return(ret);
}

755
ssize_t DARSHAN_DECL(pread64)(int fd, void *buf, size_t count, off64_t offset)
756 757 758 759 760
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

761 762
    MAP_OR_FAIL(pread64);

763
    if((unsigned long)buf % darshan_mem_alignment == 0)
764 765
        aligned_flag = 1;

766
    tm1 = darshan_core_wtime();
767
    ret = __real_pread64(fd, buf, count, offset);
768
    tm2 = darshan_core_wtime();
769
    CP_LOCK();
770
    CP_RECORD_READ(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
771 772 773 774
    CP_UNLOCK();
    return(ret);
}

775
ssize_t DARSHAN_DECL(pread)(int fd, void *buf, size_t count, off_t offset)
776 777 778 779 780
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

781 782
    MAP_OR_FAIL(pread);

783
    if((unsigned long)buf % darshan_mem_alignment == 0)
784 785
        aligned_flag = 1;

786
    tm1 = darshan_core_wtime();
787
    ret = __real_pread(fd, buf, count, offset);
788
    tm2 = darshan_core_wtime();
789
    CP_LOCK();
790
    CP_RECORD_READ(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
791 792 793 794 795
    CP_UNLOCK();
    return(ret);
}


796
ssize_t DARSHAN_DECL(pwrite)(int fd, const void *buf, size_t count, off_t offset)
797 798 799 800 801
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

802 803
    MAP_OR_FAIL(pwrite);

804
    if((unsigned long)buf % darshan_mem_alignment == 0)
805 806
        aligned_flag = 1;

807
    tm1 = darshan_core_wtime();
808
    ret = __real_pwrite(fd, buf, count, offset);
809
    tm2 = darshan_core_wtime();
810
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
811
    CP_RECORD_WRITE(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
812 813 814 815
    CP_UNLOCK();
    return(ret);
}

816
ssize_t DARSHAN_DECL(pwrite64)(int fd, const void *buf, size_t count, off64_t offset)
817 818 819 820 821
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

822 823
    MAP_OR_FAIL(pwrite64);

824
    if((unsigned long)buf % darshan_mem_alignment == 0)
825 826
        aligned_flag = 1;

827
    tm1 = darshan_core_wtime();
828
    ret = __real_pwrite64(fd, buf, count, offset);
829
    tm2 = darshan_core_wtime();
830
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
831
    CP_RECORD_WRITE(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
832 833 834 835
    CP_UNLOCK();
    return(ret);
}

836
ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
837 838 839 840 841 842
{
    ssize_t ret;
    int aligned_flag = 1;
    int i;
    double tm1, tm2;

843 844
    MAP_OR_FAIL(readv);

845 846
    for(i=0; i<iovcnt; i++)
    {
847
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
848 849 850
            aligned_flag = 0;
    }

851
    tm1 = darshan_core_wtime();
852
    ret = __real_readv(fd, iov, iovcnt);
853
    tm2 = darshan_core_wtime();
854
    CP_LOCK();
855
    CP_RECORD_READ(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
856 857 858 859
    CP_UNLOCK();
    return(ret);
}

860
ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
861 862 863 864 865 866
{
    ssize_t ret;
    int aligned_flag = 1;
    int i;
    double tm1, tm2;

867 868
    MAP_OR_FAIL(writev);

869 870
    for(i=0; i<iovcnt; i++)
    {
871
        if(!((unsigned long)iov[i].iov_base % darshan_mem_alignment == 0))
872 873 874
            aligned_flag = 0;
    }

875
    tm1 = darshan_core_wtime();
876
    ret = __real_writev(fd, iov, iovcnt);
877
    tm2 = darshan_core_wtime();
878
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
879
    CP_RECORD_WRITE(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
880 881 882 883
    CP_UNLOCK();
    return(ret);
}

884
size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
885 886 887 888 889
{
    size_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

890 891
    MAP_OR_FAIL(fread);

892
    if((unsigned long)ptr % darshan_mem_alignment == 0)
893 894
        aligned_flag = 1;

895
    tm1 = darshan_core_wtime();
896
    ret = __real_fread(ptr, size, nmemb, stream);
897
    tm2 = darshan_core_wtime();
898 899
    CP_LOCK();
    if(ret > 0)
900
        CP_RECORD_READ(size*ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
901
    else
902
        CP_RECORD_READ(ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
903 904 905 906
    CP_UNLOCK();
    return(ret);
}

907
ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
908 909 910 911 912
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

913 914
    MAP_OR_FAIL(read);

915
    if((unsigned long)buf % darshan_mem_alignment == 0)
916 917
        aligned_flag = 1;

918
    tm1 = darshan_core_wtime();
919
    ret = __real_read(fd, buf, count);
920
    tm2 = darshan_core_wtime();
921
    CP_LOCK();
922
    CP_RECORD_READ(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
923 924 925 926
    CP_UNLOCK();
    return(ret);
}

927
ssize_t DARSHAN_DECL(write)(int fd, const void *buf, size_t count)
928 929 930 931 932
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

933 934
    MAP_OR_FAIL(write);

935
    if((unsigned long)buf % darshan_mem_alignment == 0)
936 937
        aligned_flag = 1;

938
    tm1 = darshan_core_wtime();
939
    ret = __real_write(fd, buf, count);
940
    tm2 = darshan_core_wtime();
941
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
942
    CP_RECORD_WRITE(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
943 944 945 946
    CP_UNLOCK();
    return(ret);
}

947
size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream)
948 949 950 951 952
{
    size_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

953 954
    MAP_OR_FAIL(fwrite);

955
    if((unsigned long)ptr % darshan_mem_alignment == 0)
956 957
        aligned_flag = 1;

958
    tm1 = darshan_core_wtime();
959
    ret = __real_fwrite(ptr, size, nmemb, stream);
960
    tm2 = darshan_core_wtime();
961 962
    CP_LOCK();
    if(ret > 0)
Philip Carns's avatar
Philip Carns committed
963
        CP_RECORD_WRITE(size*ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
964
    else
Philip Carns's avatar
Philip Carns committed
965
        CP_RECORD_WRITE(ret, fileno(stream), 0, 0, 0, aligned_flag, 1, tm1, tm2);
966 967 968 969
    CP_UNLOCK();
    return(ret);
}

970
off64_t DARSHAN_DECL(lseek64)(int fd, off64_t offset, int whence)
971
{
Philip Carns's avatar
Philip Carns committed
972
    off64_t ret;
973 974 975
    struct darshan_file_runtime* file;
    double tm1, tm2;

976 977
    MAP_OR_FAIL(lseek64);

978
    tm1 = darshan_core_wtime();
979
    ret = __real_lseek64(fd, offset, whence);
980
    tm2 = darshan_core_wtime();
981 982 983 984 985 986 987
    if(ret >= 0)
    {
        CP_LOCK();
        file = darshan_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
988
            CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
989 990 991 992 993 994 995
            CP_INC(file, CP_POSIX_SEEKS, 1);
        }
        CP_UNLOCK();
    }
    return(ret);
}

996
off_t DARSHAN_DECL(lseek)(int fd, off_t offset, int whence)
997 998 999 1000 1001
{
    off_t ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

1002 1003
    MAP_OR_FAIL(lseek);

1004
    tm1 = darshan_core_wtime();
1005
    ret = __real_lseek(fd, offset, whence);
1006
    tm2 = darshan_core_wtime();
1007 1008 1009 1010 1011 1012 1013
    if(ret >= 0)
    {
        CP_LOCK();
        file = darshan_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
1014
            CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
1015 1016 1017 1018 1019 1020 1021
            CP_INC(file, CP_POSIX_SEEKS, 1);
        }
        CP_UNLOCK();
    }
    return(ret);
}

1022
ssize_t DARSHAN_DECL(aio_return64)(struct aiocb64 *aiocbp)
1023 1024
{
    int ret;
1025 1026 1027
    double tm2;
    struct darshan_aio_tracker *tmp;
    int aligned_flag = 0;
1028 1029 1030 1031

    MAP_OR_FAIL(aio_return64);

    ret = __real_aio_return64(aiocbp);
1032
    tm2 = darshan_core_wtime();
1033
    tmp = darshan_aio_tracker_del(aiocbp->aio_fildes, aiocbp);
1034 1035 1036 1037 1038 1039

    if(tmp)
    {
        if((unsigned long)aiocbp->aio_buf % darshan_mem_alignment == 0)
            aligned_flag = 1;
        CP_LOCK();
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
        if(aiocbp->aio_lio_opcode == LIO_WRITE)
        {
            CP_RECORD_WRITE(ret, aiocbp->aio_fildes, aiocbp->aio_nbytes,
                1, aiocbp->aio_offset, aligned_flag, 0, tmp->tm1, tm2);
        }
        if(aiocbp->aio_lio_opcode == LIO_READ)
        {
            CP_RECORD_READ(ret, aiocbp->aio_fildes, aiocbp->aio_nbytes,
                1, aiocbp->aio_offset, aligned_flag, 0, tmp->tm1, tm2);
        }
1050 1051 1052
        CP_UNLOCK();
        free(tmp);
    }
1053 1054 1055 1056 1057 1058 1059

    return(ret);
}

ssize_t DARSHAN_DECL(aio_return)(struct aiocb *aiocbp)
{
    int ret;
1060 1061 1062
    double tm2;
    struct darshan_aio_tracker *tmp;
    int aligned_flag = 0;
1063 1064 1065 1066

    MAP_OR_FAIL(aio_return);

    ret = __real_aio_return(aiocbp);
1067
    tm2 = darshan_core_wtime();
1068
    tmp = darshan_aio_tracker_del(aiocbp->aio_fildes, aiocbp);
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079

    if(tmp)
    {
        if((unsigned long)aiocbp->aio_buf % darshan_mem_alignment == 0)
            aligned_flag = 1;
        CP_LOCK();
        CP_RECORD_WRITE(ret, aiocbp->aio_fildes, aiocbp->aio_nbytes,
            1, aiocbp->aio_offset, aligned_flag, 0, tmp->tm1, tm2);
        CP_UNLOCK();
        free(tmp);
    }
1080 1081 1082 1083 1084 1085 1086 1087

    return(ret);
}

int DARSHAN_DECL(lio_listio)(int mode, struct aiocb *const aiocb_list[],
    int nitems, struct sigevent *sevp)
{
    int ret;
1088
    int i;
1089 1090 1091 1092

    MAP_OR_FAIL(lio_listio);

    ret = __real_lio_listio(mode, aiocb_list, nitems, sevp);
1093 1094 1095 1096
    if(ret == 0)
    {
        for(i=0; i<nitems; i++)
        {
1097
            darshan_aio_tracker_add(aiocb_list[i]->aio_fildes, aiocb_list[i]);        
1098 1099
        }
    }
1100 1101 1102 1103

    return(ret);
}

1104
int DARSHAN_DECL(lio_listio64)(int mode, struct aiocb64 *const aiocb_list[],
1105 1106 1107
    int nitems, struct sigevent *sevp)
{
    int ret;
1108
    int i;
1109

1110
    MAP_OR_FAIL(lio_listio);
1111

1112
    ret = __real_lio_listio64(mode, aiocb_list, nitems, sevp);
1113 1114 1115 1116
    if(ret == 0)
    {
        for(i=0; i<nitems; i++)
        {
1117
            darshan_aio_tracker_add(aiocb_list[i]->aio_fildes, aiocb_list[i]);        
1118 1119
        }
    }
1120 1121 1122 1123

    return(ret);
}

1124
int DARSHAN_DECL(aio_write64)(struct aiocb64 *aiocbp)
1125 1126 1127 1128 1129 1130
{
    int ret;

    MAP_OR_FAIL(aio_write64);

    ret = __real_aio_write64(aiocbp);
1131
    if(ret == 0)
1132
        darshan_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143

    return(ret);
}

int DARSHAN_DECL(aio_write)(struct aiocb *aiocbp)
{
    int ret;

    MAP_OR_FAIL(aio_write);

    ret = __real_aio_write(aiocbp);
1144
    if(ret == 0)
1145
        darshan_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
1146 1147 1148 1149

    return(ret);
}

1150
int DARSHAN_DECL(aio_read64)(struct aiocb64 *aiocbp)
1151 1152 1153 1154 1155 1156
{
    int ret;

    MAP_OR_FAIL(aio_read64);

    ret = __real_aio_read64(aiocbp);
1157
    if(ret == 0)
1158
        darshan_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169

    return(ret);
}

int DARSHAN_DECL(aio_read)(struct aiocb *aiocbp)
{
    int ret;

    MAP_OR_FAIL(aio_read);

    ret = __real_aio_read(aiocbp);
1170
    if(ret == 0)
1171
        darshan_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
1172 1173 1174 1175

    return(ret);
}

1176
int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
1177 1178 1179 1180 1181
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

1182 1183
    MAP_OR_FAIL(fseek);

1184
    tm1 = darshan_core_wtime();
1185
    ret = __real_fseek(stream, offset, whence);
1186
    tm2 = darshan_core_wtime();
1187 1188 1189 1190 1191 1192 1193
    if(ret >= 0)
    {
        CP_LOCK();
        file = darshan_file_by_fd(fileno(stream));
        if(file)
        {
            file->offset = ret;
1194
            CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
1195 1196 1197 1198 1199 1200
            CP_INC(file, CP_POSIX_FSEEKS, 1);
        }
        CP_UNLOCK();
    }
    return(ret);
}
1201
#endif
1202

1203 1204 1205 1206 1207
static void posix_runtime_initialize()
{
    char *alignstr;
    int tmpval;
    int ret;
1208 1209 1210 1211 1212 1213
    int posix_mod_mem_limit = 0;
    struct darshan_module_funcs posix_mod_funcs =
    {
        .prepare_for_shutdown = &posix_prepare_for_shutdown,
        .get_output_data = &posix_get_output_data
    };
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245

    if (posix_mod_initialized)
        return;

    /* set the memory alignment according to config or environment variables */
    #if (__CP_MEM_ALIGNMENT < 1)
        #error Darshan must be configured with a positive value for --with-mem-align
    #endif
    alignstr = getenv("DARSHAN_MEMALIGN");
    if (alignstr)
    {
        ret = sscanf(alignstr, "%d", &tmpval);
        /* silently ignore if the env variable is set poorly */
        if(ret == 1 && tmpval > 0)
        {
            darshan_mem_alignment = tmpval;
        }
    }
    else
    {
        darshan_mem_alignment = __CP_MEM_ALIGNMENT;
    }

    /* avoid floating point errors on faulty input */
    if (darshan_mem_alignment < 1)
    {
        darshan_mem_alignment = 1;
    }

    /* register the posix module with darshan core */
    darshan_core_register_module("POSIX", &posix_mod_funcs, &posix_mod_mem_limit);

1246 1247
    /* TODO: allocate memory for saving i/o stats */

1248 1249 1250 1251
    posix_mod_initialized = 1;
    return;
}

1252
static double posix_wtime()
1253
{
1254
    return DARSHAN_MPI_CALL(PMPI_Wtime)();