darshan-posix.c 65.7 KB
Newer Older
1
/*
Shane Snyder's avatar
Shane Snyder committed
2 3 4
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
5 6
 */

7 8 9
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE

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

29
#include "uthash.h"
30 31
#include "utlist.h"

32
#include "darshan.h"
33
#include "darshan-posix-log-format.h"
34
#include "darshan-dynamic.h"
35

36
#ifndef HAVE_OFF64_T
37 38
typedef int64_t off64_t;
#endif
39 40 41
#ifndef HAVE_AIOCB64
#define aiocb64 aiocb
#endif
42

43 44
/* TODO: more libc, fgetc, etc etc etc. */

45 46
DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
47 48
DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
49 50
DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
51 52 53 54
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));
DARSHAN_FORWARD_DECL(mkostemps, int, (char *template, int suffixlen, int flags));
55 56 57 58 59 60 61 62
DARSHAN_FORWARD_DECL(read, ssize_t, (int fd, void *buf, size_t count));
DARSHAN_FORWARD_DECL(write, ssize_t, (int fd, const void *buf, size_t count));
DARSHAN_FORWARD_DECL(pread, ssize_t, (int fd, void *buf, size_t count, off_t offset));
DARSHAN_FORWARD_DECL(pwrite, ssize_t, (int fd, const 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(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));
63 64 65 66 67
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));
68 69 70 71 72 73
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));
DARSHAN_FORWARD_DECL(__lxstat64, int, (int vers, const char* path, struct stat64 *buf));
DARSHAN_FORWARD_DECL(__fxstat, int, (int vers, int fd, struct stat *buf));
DARSHAN_FORWARD_DECL(__fxstat64, int, (int vers, int fd, struct stat64 *buf));
Shane Snyder's avatar
Shane Snyder committed
74 75
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));
76 77
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
78
DARSHAN_FORWARD_DECL(close, int, (int fd));
79
DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
80 81 82 83 84 85 86 87
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));
DARSHAN_FORWARD_DECL(aio_write64, int, (struct aiocb64 *aiocbp));
DARSHAN_FORWARD_DECL(aio_return, ssize_t, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_return64, ssize_t, (struct aiocb64 *aiocbp));
DARSHAN_FORWARD_DECL(lio_listio, int, (int mode, struct aiocb *const aiocb_list[], int nitems, struct sigevent *sevp));
DARSHAN_FORWARD_DECL(lio_listio64, int, (int mode, struct aiocb64 *const aiocb_list[], int nitems, struct sigevent *sevp));
88

89 90 91 92 93 94 95 96
/* struct to track information about aio operations in flight */
struct posix_aio_tracker
{
    double tm1;
    void *aiocbp;
    struct posix_aio_tracker* next;
};

97 98 99 100 101 102
/* The posix_file_runtime structure maintains necessary runtime metadata
 * for the POSIX file record (darshan_posix_file structure, defined in
 * darshan-posix-log-format.h) pointed to by 'file_record'. This metadata
 * assists with the instrumenting of specific statistics in the file record.
 * 'hlink' is a hash table link structure used to add/remove this record
 * from the hash table of POSIX file records for this process. 
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
 *
 * RATIONALE: the POSIX module needs to track some stateful, volatile 
 * information about each open file (like the current file offset, most recent 
 * access time, etc.) to aid in instrumentation, but this information can't be
 * stored in the darshan_posix_file struct because we don't want it to appear in
 * the final darshan log file.  We therefore associate a posix_file_runtime
 * struct with each darshan_posix_file struct in order to track this information.
  *
 * NOTE: There is a one-to-one mapping of posix_file_runtime structs to
 * darshan_posix_file structs.
 *
 * NOTE: The posix_file_runtime struct contains a pointer to a darshan_posix_file
 * struct (see the *file_record member) rather than simply embedding an entire
 * darshan_posix_file struct.  This is done so that all of the darshan_posix_file
 * structs can be kept contiguous in memory as a single array to simplify
 * reduction, compression, and storage.
119
 */
120
struct posix_file_runtime
121
{
122
    struct darshan_posix_file* file_record;
123 124 125
    int64_t offset;
    int64_t last_byte_read;
    int64_t last_byte_written;
Shane Snyder's avatar
Shane Snyder committed
126
    enum darshan_io_type last_io_type;
127 128 129
    double last_meta_end;
    double last_read_end;
    double last_write_end;
130 131 132 133
    void* access_root;
    int access_count;
    void* stride_root;
    int stride_count;
134
    struct posix_aio_tracker* aio_list;
135
    UT_hash_handle hlink;
136
};
137

138 139 140 141 142 143 144 145 146 147 148
/* The posix_file_runtime_ref structure is used to associate a POSIX
 * file descriptor with an already existing POSIX file record. This is
 * necessary as many POSIX I/O functions take only an input file descriptor,
 * but POSIX file records are indexed by their full file paths (i.e., darshan
 * record identifiers for POSIX files are created by hashing the file path).
 * In other words, this structure is necessary as it allows us to look up a
 * file record either by a pathname (posix_file_runtime) or by POSIX file
 * descriptor (posix_file_runtime_ref), depending on which parameters are
 * available. This structure includes another hash table link, since separate
 * hashes are maintained for posix_file_runtime structures and posix_file_runtime_ref
 * structures.
149 150 151 152 153 154 155 156 157 158 159
 *
 * RATIONALE: In theory the fd information could be included in the
 * posix_file_runtime struct rather than in a separate structure here.  The
 * reason we don't do that is because the same file could be opened multiple
 * times by a given process with different file descriptors and thus
 * simulataneously referenced using different file descriptors.  This practice is
 * not common, but we must support it.
 *
 * NOTE: there are potentially multiple posix_file_runtime_ref structures
 * referring to a single posix_file_runtime structure.  Most of the time there is
 * only one, however.
160
 */
161
struct posix_file_runtime_ref
162
{
163
    struct posix_file_runtime* file;
164 165 166 167
    int fd;
    UT_hash_handle hlink;
};

168 169 170 171
/* The posix_runtime structure maintains necessary state for storing
 * POSIX file records and for coordinating with darshan-core at 
 * shutdown time.
 */
172 173
struct posix_runtime
{
174
    struct posix_file_runtime* file_runtime_array;
175
    struct darshan_posix_file* file_record_array;
176
    int file_array_size;
177
    int file_array_ndx;
178 179
    struct posix_file_runtime* file_hash;
    struct posix_file_runtime_ref* fd_hash;
180 181
};

182
static struct posix_runtime *posix_runtime = NULL;
183
static pthread_mutex_t posix_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Shane Snyder's avatar
Shane Snyder committed
184
static int instrumentation_disabled = 0;
185
static int my_rank = -1;
186
static int darshan_mem_alignment = 1;
187

188 189 190 191 192
static void posix_runtime_initialize(void);
static struct posix_file_runtime* posix_file_by_name(const char *name);
static struct posix_file_runtime* posix_file_by_name_setfd(const char* name, int fd);
static struct posix_file_runtime* posix_file_by_fd(int fd);
static void posix_file_close_fd(int fd);
193 194
static void posix_aio_tracker_add(int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(int fd, void *aiocbp);
195
static int posix_record_compare(const void* a, const void* b);
196 197
static void posix_record_reduction_op(void* infile_v, void* inoutfile_v,
    int *len, MPI_Datatype *datatype);
198 199 200
static void posix_shared_record_variance(MPI_Comm mod_comm,
    struct darshan_posix_file *inrec_array, struct darshan_posix_file *outrec_array,
    int shared_rec_count);
201 202 203 204

static void posix_begin_shutdown(void);
static void posix_get_output_data(MPI_Comm mod_comm, darshan_record_id *shared_recs,
    int shared_rec_count, void **posix_buf, int *posix_buf_sz);
205 206
static void posix_shutdown(void);

207 208
#define POSIX_LOCK() pthread_mutex_lock(&posix_runtime_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_runtime_mutex)
209

210
#define POSIX_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
211
    struct posix_file_runtime* file; \
212
    if(__ret < 0) break; \
213
    if(darshan_core_excluded_path(__path)) break; \
214
    file = posix_file_by_name_setfd(__path, __ret); \
215
    if(!file) break; \
216
    if(__mode) \
217
        file->file_record->counters[POSIX_MODE] = __mode; \
218 219 220
    file->offset = 0; \
    file->last_byte_written = 0; \
    file->last_byte_read = 0; \
221
    if(__stream_flag)\
222
        file->file_record->counters[POSIX_FOPENS] += 1; \
223
    else \
224 225 226 227
        file->file_record->counters[POSIX_OPENS] += 1; \
    if(file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0) \
        file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] = __tm1; \
    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_META_TIME], __tm1, __tm2, file->last_meta_end); \
228 229 230
} while(0)

#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
231
    size_t stride; \
232
    int64_t this_offset; \
233
    struct posix_file_runtime* file; \
234
    int64_t file_alignment; \
235 236 237 238
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
    file = posix_file_by_fd(__fd); \
    if(!file) break; \
239
    if(__pread_flag) \
240 241 242 243
        this_offset = __pread_offset; \
    else \
        this_offset = file->offset; \
    if(this_offset > file->last_byte_read) \
244
        file->file_record->counters[POSIX_SEQ_READS] += 1;  \
245
    if(this_offset == (file->last_byte_read + 1)) \
246
        file->file_record->counters[POSIX_CONSEC_READS] += 1;  \
247
    if(this_offset > 0 && this_offset > file->last_byte_read \
248 249 250
        && file->last_byte_read != 0) \
        stride = this_offset - file->last_byte_read - 1; \
    else \
251
        stride = 0; \
252 253
    file->last_byte_read = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
254 255 256 257 258 259 260 261 262 263
    if(file->file_record->counters[POSIX_MAX_BYTE_READ] < (this_offset + __ret - 1)) \
        file->file_record->counters[POSIX_MAX_BYTE_READ] = (this_offset + __ret - 1); \
    file->file_record->counters[POSIX_BYTES_READ] += __ret; \
    if(__stream_flag) \
        file->file_record->counters[POSIX_FREADS] += 1; \
    else \
        file->file_record->counters[POSIX_READS] += 1; \
    DARSHAN_BUCKET_INC(&(file->file_record->counters[POSIX_SIZE_READ_0_100]), __ret); \
    darshan_common_val_counter(&file->access_root, &file->access_count, __ret); \
    darshan_common_val_counter(&file->stride_root, &file->stride_count, stride); \
264
    if(!__aligned) \
265 266
        file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
267
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
268
        file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
Shane Snyder's avatar
Shane Snyder committed
269
    if(file->last_io_type == DARSHAN_IO_WRITE) \
270
        file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
Shane Snyder's avatar
Shane Snyder committed
271
    file->last_io_type = DARSHAN_IO_READ; \
272 273 274 275 276 277 278
    if(file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0) \
        file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] = __tm1; \
    file->file_record->fcounters[POSIX_F_READ_END_TIMESTAMP] = __tm2; \
    if(file->file_record->fcounters[POSIX_F_MAX_READ_TIME] < __elapsed) { \
        file->file_record->fcounters[POSIX_F_MAX_READ_TIME] = __elapsed; \
        file->file_record->counters[POSIX_MAX_READ_TIME_SIZE] = __ret; } \
    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_READ_TIME], __tm1, __tm2, file->last_read_end); \
279 280 281
} while(0)

#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
282
    size_t stride; \
283
    int64_t this_offset; \
284
    struct posix_file_runtime* file; \
285
    int64_t file_alignment; \
286 287 288 289
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
    file = posix_file_by_fd(__fd); \
    if(!file) break; \
290
    if(__pwrite_flag) \
291 292 293 294
        this_offset = __pwrite_offset; \
    else \
        this_offset = file->offset; \
    if(this_offset > file->last_byte_written) \
295
        file->file_record->counters[POSIX_SEQ_WRITES] += 1; \
296
    if(this_offset == (file->last_byte_written + 1)) \
297
        file->file_record->counters[POSIX_CONSEC_WRITES] += 1; \
298
    if(this_offset > 0 && this_offset > file->last_byte_written \
299 300
        && file->last_byte_written != 0) \
        stride = this_offset - file->last_byte_written - 1; \
301
    else \
302
        stride = 0; \
303 304
    file->last_byte_written = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
305 306 307
    if(file->file_record->counters[POSIX_MAX_BYTE_WRITTEN] < (this_offset + __ret - 1)) \
        file->file_record->counters[POSIX_MAX_BYTE_WRITTEN] = (this_offset + __ret - 1); \
    file->file_record->counters[POSIX_BYTES_WRITTEN] += __ret; \
308
    if(__stream_flag) \
309
        file->file_record->counters[POSIX_FWRITES] += 1; \
310
    else \
311 312 313 314
        file->file_record->counters[POSIX_WRITES] += 1; \
    DARSHAN_BUCKET_INC(&(file->file_record->counters[POSIX_SIZE_WRITE_0_100]), __ret); \
    darshan_common_val_counter(&file->access_root, &file->access_count, __ret); \
    darshan_common_val_counter(&file->stride_root, &file->stride_count, stride); \
315
    if(!__aligned) \
316 317
        file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
318
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
319
        file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
Shane Snyder's avatar
Shane Snyder committed
320
    if(file->last_io_type == DARSHAN_IO_READ) \
321
        file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
Shane Snyder's avatar
Shane Snyder committed
322
    file->last_io_type = DARSHAN_IO_WRITE; \
323 324 325 326 327 328 329
    if(file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0) \
        file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] = __tm1; \
    file->file_record->fcounters[POSIX_F_WRITE_END_TIMESTAMP] = __tm2; \
    if(file->file_record->fcounters[POSIX_F_MAX_WRITE_TIME] < __elapsed) { \
        file->file_record->fcounters[POSIX_F_MAX_WRITE_TIME] = __elapsed; \
        file->file_record->counters[POSIX_MAX_WRITE_TIME_SIZE] = __ret; } \
    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_WRITE_TIME], __tm1, __tm2, file->last_write_end); \
330
} while(0)
331

332 333
#define POSIX_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
    struct posix_file_runtime* file; \
334
    if(darshan_core_excluded_path(__path)) break; \
335 336 337 338 339 340 341 342
    file = posix_file_by_name(__path); \
    if(file) \
    { \
        POSIX_RECORD_STAT(file, __statbuf, __tm1, __tm2); \
    } \
} while(0)

#define POSIX_RECORD_STAT(__file, __statbuf, __tm1, __tm2) do { \
343 344
    DARSHAN_TIMER_INC_NO_OVERLAP((__file)->file_record->fcounters[POSIX_F_META_TIME], __tm1, __tm2, (__file)->last_meta_end); \
    (__file)->file_record->counters[POSIX_STATS] += 1; \
345 346
} while(0)

347 348 349 350 351 352 353 354 355 356
static double psx_wrap_time = 0.0;

#define PSX_PRE_WRAP() \
    double pre_wrap = darshan_core_wtime();

#define PSX_POST_WRAP() \
    double post_wrap = darshan_core_wtime(); \
    psx_wrap_time += (post_wrap-pre_wrap);


357 358 359 360
/**********************************************************
 *      Wrappers for POSIX I/O functions of interest      * 
 **********************************************************/

361
int DARSHAN_DECL(open)(const char *path, int flags, ...)
362 363 364 365 366
{
    int mode = 0;
    int ret;
    double tm1, tm2;

367 368
    PSX_PRE_WRAP();

369 370
    MAP_OR_FAIL(open);

371
    if(flags & O_CREAT) 
372 373 374 375 376 377
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

378
        tm1 = darshan_core_wtime();
379
        ret = __real_open(path, flags, mode);
380
        tm2 = darshan_core_wtime();
381 382 383
    }
    else
    {
384
        tm1 = darshan_core_wtime();
385
        ret = __real_open(path, flags);
386
        tm2 = darshan_core_wtime();
387 388
    }

389 390
    POSIX_LOCK();
    posix_runtime_initialize();
391
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
392
    POSIX_UNLOCK();
393

394 395
    PSX_POST_WRAP();

396 397 398
    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
399 400 401 402 403 404
int DARSHAN_DECL(open64)(const char *path, int flags, ...)
{
    int mode = 0;
    int ret;
    double tm1, tm2;

405 406
    PSX_PRE_WRAP();

407
    MAP_OR_FAIL(open64);
Shane Snyder's avatar
Shane Snyder committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428

    if(flags & O_CREAT)
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

        tm1 = darshan_core_wtime();
        ret = __real_open64(path, flags, mode);
        tm2 = darshan_core_wtime();
    }
    else
    {
        tm1 = darshan_core_wtime();
        ret = __real_open64(path, flags);
        tm2 = darshan_core_wtime();
    }

    POSIX_LOCK();
    posix_runtime_initialize();
429 430 431
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();

432 433
    PSX_POST_WRAP();

434 435 436 437 438 439 440 441
    return(ret);
}

int DARSHAN_DECL(creat)(const char* path, mode_t mode)
{
    int ret;
    double tm1, tm2;

442 443
    PSX_PRE_WRAP();

444 445 446 447 448 449 450 451 452 453 454
    MAP_OR_FAIL(creat);

    tm1 = darshan_core_wtime();
    ret = __real_creat(path, mode);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();

455 456
    PSX_POST_WRAP();

457 458 459 460 461 462 463 464
    return(ret);
}

int DARSHAN_DECL(creat64)(const char* path, mode_t mode)
{
    int ret;
    double tm1, tm2;

465 466
    PSX_PRE_WRAP();

467
    MAP_OR_FAIL(creat64);
Shane Snyder's avatar
Shane Snyder committed
468

469 470 471 472 473 474
    tm1 = darshan_core_wtime();
    ret = __real_creat64(path, mode);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
Shane Snyder's avatar
Shane Snyder committed
475 476 477
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();

478 479
    PSX_POST_WRAP();

Shane Snyder's avatar
Shane Snyder committed
480 481 482
    return(ret);
}

483 484 485 486 487 488
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
{
    FILE* ret;
    int fd;
    double tm1, tm2;

489 490
    PSX_PRE_WRAP();

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
    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_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    POSIX_UNLOCK();

507 508
    PSX_POST_WRAP();

509 510 511 512 513 514 515 516 517
    return(ret);
}

FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
{
    FILE* ret;
    int fd;
    double tm1, tm2;

518 519
    PSX_PRE_WRAP();

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
    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_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    POSIX_UNLOCK();

536 537
    PSX_POST_WRAP();

538 539 540
    return(ret);
}

541 542 543 544 545
int DARSHAN_DECL(mkstemp)(char* template)
{
    int ret;
    double tm1, tm2;

546 547
    PSX_PRE_WRAP();

548 549 550 551 552 553 554 555 556 557 558
    MAP_OR_FAIL(mkstemp);

    tm1 = darshan_core_wtime();
    ret = __real_mkstemp(template);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
    POSIX_UNLOCK();

559 560
    PSX_POST_WRAP();

561 562 563 564 565 566 567 568
    return(ret);
}

int DARSHAN_DECL(mkostemp)(char* template, int flags)
{
    int ret;
    double tm1, tm2;

569 570
    PSX_PRE_WRAP();

571 572 573 574 575 576 577 578 579 580 581
    MAP_OR_FAIL(mkostemp);

    tm1 = darshan_core_wtime();
    ret = __real_mkostemp(template, flags);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
    POSIX_UNLOCK();

582 583
    PSX_POST_WRAP();

584 585 586 587 588 589 590 591
    return(ret);
}

int DARSHAN_DECL(mkstemps)(char* template, int suffixlen)
{
    int ret;
    double tm1, tm2;

592 593
    PSX_PRE_WRAP();

594 595 596 597 598 599 600 601 602 603 604
    MAP_OR_FAIL(mkstemps);

    tm1 = darshan_core_wtime();
    ret = __real_mkstemps(template, suffixlen);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
    POSIX_UNLOCK();

605 606
    PSX_POST_WRAP();

607 608 609 610 611 612 613 614
    return(ret);
}

int DARSHAN_DECL(mkostemps)(char* template, int suffixlen, int flags)
{
    int ret;
    double tm1, tm2;

615 616
    PSX_PRE_WRAP();

617 618 619 620 621 622 623 624 625 626 627
    MAP_OR_FAIL(mkostemps);

    tm1 = darshan_core_wtime();
    ret = __real_mkostemps(template, suffixlen, flags);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_OPEN(ret, template, 0, 0, tm1, tm2);
    POSIX_UNLOCK();

628 629
    PSX_POST_WRAP();

630 631 632
    return(ret);
}

633 634 635 636 637 638
ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

639 640
    PSX_PRE_WRAP();

641
    MAP_OR_FAIL(read);
642

643
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
644 645 646 647 648 649 650 651 652 653

    tm1 = darshan_core_wtime();
    ret = __real_read(fd, buf, count);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

654 655
    PSX_POST_WRAP();

656 657 658 659 660 661 662 663 664
    return(ret);
}

ssize_t DARSHAN_DECL(write)(int fd, const void *buf, size_t count)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

665 666
    PSX_PRE_WRAP();

667 668
    MAP_OR_FAIL(write);

669
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
670 671 672 673 674 675 676 677 678 679

    tm1 = darshan_core_wtime();
    ret = __real_write(fd, buf, count);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

680 681
    PSX_POST_WRAP();

682 683 684 685 686 687 688 689 690
    return(ret);
}

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

691 692
    PSX_PRE_WRAP();

693 694
    MAP_OR_FAIL(pread);

695
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
696 697 698 699 700 701 702 703 704 705

    tm1 = darshan_core_wtime();
    ret = __real_pread(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

706 707
    PSX_POST_WRAP();

708 709 710 711 712 713 714 715 716
    return(ret);
}

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

717 718
    PSX_PRE_WRAP();

719 720
    MAP_OR_FAIL(pwrite);

721
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
722 723 724 725 726 727 728 729 730 731

    tm1 = darshan_core_wtime();
    ret = __real_pwrite(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

732 733
    PSX_POST_WRAP();

734 735 736 737 738 739 740 741 742
    return(ret);
}

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

743 744
    PSX_PRE_WRAP();

745 746
    MAP_OR_FAIL(pread64);

747
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
748 749 750 751 752 753 754 755 756 757

    tm1 = darshan_core_wtime();
    ret = __real_pread64(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

758 759
    PSX_POST_WRAP();

760 761 762 763 764 765 766 767 768
    return(ret);
}

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

769 770
    PSX_PRE_WRAP();

771 772
    MAP_OR_FAIL(pwrite64);

773
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
774 775 776 777 778 779 780 781 782 783

    tm1 = darshan_core_wtime();
    ret = __real_pwrite64(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

784 785
    PSX_POST_WRAP();

786 787 788 789 790 791
    return(ret);
}

ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
792
    int aligned_flag = 1;
793 794 795
    int i;
    double tm1, tm2;

796 797
    PSX_PRE_WRAP();

798
    MAP_OR_FAIL(readv);
799

800 801 802 803
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
804
    }
805 806 807 808 809 810

    tm1 = darshan_core_wtime();
    ret = __real_readv(fd, iov, iovcnt);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
811
    posix_runtime_initialize();
812 813 814
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

815 816
    PSX_POST_WRAP();

817 818 819 820 821 822
    return(ret);
}

ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
823
    int aligned_flag = 1;
824 825 826
    int i;
    double tm1, tm2;

827 828
    PSX_PRE_WRAP();

829
    MAP_OR_FAIL(writev);
830

831 832 833 834
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
835
    }
836 837 838 839 840 841

    tm1 = darshan_core_wtime();
    ret = __real_writev(fd, iov, iovcnt);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
842
    posix_runtime_initialize();
843 844 845
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

846 847
    PSX_POST_WRAP();

848 849 850
    return(ret);
}

851 852 853 854 855 856
size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
    size_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

857 858
    PSX_PRE_WRAP();

859 860
    MAP_OR_FAIL(fread);

861
    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880

    tm1 = darshan_core_wtime();
    ret = __real_fread(ptr, size, nmemb, stream);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    if(ret > 0)
    {
        POSIX_RECORD_READ(size*ret, fileno(stream), 0, 0,
            aligned_flag, 1, tm1, tm2);
    }
    else
    {
        POSIX_RECORD_READ(ret, fileno(stream), 0, 0,
            aligned_flag, 1, tm1, tm2);
    }
    POSIX_UNLOCK();

881 882
    PSX_POST_WRAP();

883 884 885 886 887 888 889 890 891
    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;
    double tm1, tm2;

892 893
    PSX_PRE_WRAP();

894 895
    MAP_OR_FAIL(fwrite);

896
    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915

    tm1 = darshan_core_wtime();
    ret = __real_fwrite(ptr, size, nmemb, stream);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    if(ret > 0)
    {
        POSIX_RECORD_WRITE(size*ret, fileno(stream), 0, 0,
            aligned_flag, 1, tm1, tm2);
    }
    else
    {
        POSIX_RECORD_WRITE(ret, fileno(stream), 0, 0,
            aligned_flag, 1, tm1, tm2);
    }
    POSIX_UNLOCK();

916 917
    PSX_POST_WRAP();

918 919 920 921 922 923 924 925 926
    return(ret);
}

off_t DARSHAN_DECL(lseek)(int fd, off_t offset, int whence)
{
    off_t ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

927 928
    PSX_PRE_WRAP();

929 930 931 932 933 934 935 936 937 938 939 940 941 942
    MAP_OR_FAIL(lseek);

    tm1 = darshan_core_wtime();
    ret = __real_lseek(fd, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        file = posix_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
943 944 945 946
            DARSHAN_TIMER_INC_NO_OVERLAP(
                file->file_record->fcounters[POSIX_F_META_TIME],
                tm1, tm2, file->last_meta_end);
            file->file_record->counters[POSIX_SEEKS] += 1;
947 948 949 950
        }
        POSIX_UNLOCK();
    }

951 952
    PSX_POST_WRAP();

953 954 955 956 957 958 959 960 961
    return(ret);
}

off_t DARSHAN_DECL(lseek64)(int fd, off_t offset, int whence)
{
    off_t ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

962 963
    PSX_PRE_WRAP();

964 965 966 967 968 969 970 971 972 973 974 975 976 977
    MAP_OR_FAIL(lseek64);

    tm1 = darshan_core_wtime();
    ret = __real_lseek64(fd, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        file = posix_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
978 979 980 981
            DARSHAN_TIMER_INC_NO_OVERLAP(
                file->file_record->fcounters[POSIX_F_META_TIME],
                tm1, tm2, file->last_meta_end);
            file->file_record->counters[POSIX_SEEKS] += 1;
982 983 984 985
        }
        POSIX_UNLOCK();
    }

986 987
    PSX_POST_WRAP();

988 989 990 991 992 993 994 995 996
    return(ret);
}

int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
{
    int ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

997 998
    PSX_PRE_WRAP();

999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
    MAP_OR_FAIL(fseek);

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

    if(ret >= 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        file = posix_file_by_fd(fileno(stream));
        if(file)
        {
1012
            file->offset = ftell(stream);
1013 1014 1015 1016
            DARSHAN_TIMER_INC_NO_OVERLAP(
                file->file_record->fcounters[POSIX_F_META_TIME],
                tm1, tm2, file->last_meta_end);
            file->file_record->counters[POSIX_FSEEKS] += 1;
1017 1018 1019 1020
        }
        POSIX_UNLOCK();
    }

1021 1022
    PSX_POST_WRAP();

1023 1024 1025
    return(ret);
}

1026 1027 1028 1029 1030
int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
{
    int ret;
    double tm1, tm2;

1031 1032
    PSX_PRE_WRAP();

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
    MAP_OR_FAIL(__xstat);

    tm1 = darshan_core_wtime();
    ret = __real___xstat(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
    POSIX_UNLOCK();

1047 1048
    PSX_POST_WRAP();

1049 1050 1051 1052 1053 1054 1055 1056
    return(ret);
}

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

1057 1058
    PSX_PRE_WRAP();

1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
    MAP_OR_FAIL(__xstat64);

    tm1 = darshan_core_wtime();
    ret = __real___xstat64(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
    POSIX_UNLOCK();

1073 1074
    PSX_POST_WRAP();

1075 1076 1077 1078 1079 1080 1081 1082
    return(ret);
}

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

1083 1084
    PSX_PRE_WRAP();

1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    MAP_OR_FAIL(__lxstat);

    tm1 = darshan_core_wtime();
    ret = __real___lxstat(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
    POSIX_UNLOCK();

1099 1100
    PSX_POST_WRAP();

1101 1102 1103 1104 1105 1106 1107 1108
    return(ret);
}

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

1109 1110
    PSX_PRE_WRAP();

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
    MAP_OR_FAIL(__lxstat64);

    tm1 = darshan_core_wtime();
    ret = __real___lxstat64(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
    POSIX_UNLOCK();

1125 1126
    PSX_POST_WRAP();

1127 1128 1129 1130 1131 1132 1133 1134 1135
    return(ret);
}

int DARSHAN_DECL(__fxstat)(int vers, int fd, struct stat *buf)
{
    int ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

1136 1137
    PSX_PRE_WRAP();

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    MAP_OR_FAIL(__fxstat);

    tm1 = darshan_core_wtime();
    ret = __real___fxstat(vers, fd, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
        POSIX_RECORD_STAT(file, buf, tm1, tm2);
    }
    POSIX_UNLOCK();

1156 1157
    PSX_POST_WRAP();

1158 1159 1160 1161 1162 1163 1164 1165 1166
    return(ret);
}

int DARSHAN_DECL(__fxstat64)(int vers, int fd, struct stat64 *buf)
{
    int ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

1167 1168
    PSX_PRE_WRAP();

1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
    MAP_OR_FAIL(__fxstat64);

    tm1 = darshan_core_wtime();
    ret = __real___fxstat64(vers, fd, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
        POSIX_RECORD_STAT(file, buf, tm1, tm2);
    }
    POSIX_UNLOCK();

1187 1188
    PSX_POST_WRAP();

1189 1190 1191
    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
1192 1193 1194 1195 1196 1197
void* DARSHAN_DECL(mmap)(void *addr, size_t length, int prot, int flags,
    int fd, off_t offset)
{
    void* ret;
    struct posix_file_runtime* file;

1198 1199
    PSX_PRE_WRAP();

Shane Snyder's avatar
Shane Snyder committed
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
    MAP_OR_FAIL(mmap);

    ret = __real_mmap(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
1211
        file->file_record->counters[POSIX_MMAPS] += 1;
Shane Snyder's avatar
Shane Snyder committed
1212 1213 1214
    }
    POSIX_UNLOCK();

1215 1216
    PSX_POST_WRAP();

Shane Snyder's avatar
Shane Snyder committed
1217 1218 1219 1220 1221 1222 1223 1224 1225
    return(ret);
}

void* DARSHAN_DECL(mmap64)(void *addr, size_t length, int prot, int flags,
    int fd, off64_t offset)
{
    void* ret;
    struct posix_file_runtime* file;

1226 1227
    PSX_PRE_WRAP();

Shane Snyder's avatar
Shane Snyder committed
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
    MAP_OR_FAIL(mmap64);

    ret = __real_mmap64(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
1239
        file->file_record->counters[POSIX_MMAPS] += 1;
Shane Snyder's avatar
Shane Snyder committed
1240 1241 1242
    }
    POSIX_UNLOCK();

1243 1244
    PSX_POST_WRAP();

Shane Snyder's avatar
Shane Snyder committed
1245 1246 1247
    return(ret);
}

1248 1249 1250 1251 1252 1253
int DARSHAN_DECL(fsync)(int fd)
{
    int ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

1254 1255
    PSX_PRE_WRAP();

1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
    MAP_OR_FAIL(fsync);

    tm1 = darshan_core_wtime();
    ret = __real_fsync(fd);
    tm2 = darshan_core_wtime();

    if(ret < 0)
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
1270 1271 1272 1273
        DARSHAN_TIMER_INC_NO_OVERLAP(
            file->file_record->fcounters[POSIX_F_WRITE_TIME],
            tm1, tm2, file->last_write_end);
        file->file_record->counters[POSIX_FSYNCS] += 1;
1274 1275 1276
    }
    POSIX_UNLOCK();

1277 1278
    PSX_POST_WRAP();

1279 1280 1281 1282 1283 1284 1285 1286 1287
    return(ret);
}

int DARSHAN_DECL(fdatasync)(int fd)
{
    int ret;
    struct posix_file_runtime* file;
    double tm1, tm2;

1288 1289
    PSX_PRE_WRAP();

1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
    MAP_OR_FAIL(fdatasync);

    tm1 = darshan_core_wtime();
    ret = __real_fdatasync(fd);
    tm2 = darshan_core_wtime();

    if(ret < 0)
        return(ret);

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
1304 1305 1306 1307
        DARSHAN_TIMER_INC_NO_OVERLAP(
            file->file_record->fcounters[POSIX_F_WRITE_TIME],
            tm1, tm2, file->last_write_end);
        file->file_record->counters[POSIX_FDSYNCS] += 1;
1308 1309 1310
    }
    POSIX_UNLOCK();

1311 1312
    PSX_POST_WRAP();

1313 1314 1315
    return(ret);
}

1316 1317
int DARSHAN_DECL(close)(int fd)
{
1318
    struct posix_file_runtime* file;
1319 1320 1321
    double tm1, tm2;
    int ret;

1322 1323
    PSX_PRE_WRAP();

1324 1325 1326 1327 1328 1329 1330 1331
    MAP_OR_FAIL(close);

    tm1 = darshan_core_wtime();
    ret = __real_close(fd);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
Shane Snyder's avatar
Shane Snyder committed
1332 1333 1334
    file = posix_file_by_fd(fd);
    if(file)
    {
1335 1336
        file->last_byte_written = 0;
        file->last_byte_read = 0;
1337 1338 1339 1340 1341
        file->file_record->fcounters[POSIX_F_CLOSE_TIMESTAMP] =
            darshan_core_wtime();
        DARSHAN_TIMER_INC_NO_OVERLAP(
            file->file_record->fcounters[POSIX_F_META_TIME],
            tm1, tm2, file->last_meta_end);
Shane Snyder's avatar
Shane Snyder committed
1342 1343
        posix_file_close_fd(fd);
    }
1344 1345
    POSIX_UNLOCK();    

1346 1347
    PSX_POST_WRAP();

1348 1349 1350
    return(ret);
}

1351 1352 1353 1354 1355 1356 1357
int DARSHAN_DECL(fclose)(FILE *fp)
{
    struct posix_file_runtime* file;
    int fd = fileno(fp);
    double tm1, tm2;
    int ret;

1358 1359
    PSX_PRE_WRAP();

1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
    MAP_OR_FAIL(fclose);

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

    POSIX_LOCK();
    posix_runtime_initialize();
    file = posix_file_by_fd(fd);
    if(file)
    {
        file->last_byte_written = 0;
        file->last_byte_read = 0;
1373 1374 1375 1376 1377
        file->file_record->fcounters[POSIX_F_CLOSE_TIMESTAMP] =
            darshan_core_wtime();
        DARSHAN_TIMER_INC_NO_OVERLAP(
            file->file_record->fcounters[POSIX_F_META_TIME],
            tm1, tm2, file->last_meta_end);
1378 1379 1380 1381
        posix_file_close_fd(fd);
    }
    POSIX_UNLOCK();

1382 1383
    PSX_POST_WRAP();

1384 1385 1386
    return(ret);
}

1387 1388 1389 1390
int DARSHAN_DECL(aio_read)(struct aiocb *aiocbp)
{
    int ret;

1391 1392
    PSX_PRE_WRAP();

1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
    MAP_OR_FAIL(aio_read);

    ret = __real_aio_read(aiocbp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        posix_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
        POSIX_UNLOCK();
    }

1404 1405
    PSX_POST_WRAP();

1406 1407 1408 1409 1410 1411 1412
    return(ret);
}

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

1413 1414
    PSX_PRE_WRAP();

1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
    MAP_OR_FAIL(aio_write);

    ret = __real_aio_write(aiocbp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        posix_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
        POSIX_UNLOCK();
    }

1426 1427
    PSX_POST_WRAP();

1428 1429 1430 1431 1432 1433 1434
    return(ret);
}

int DARSHAN_DECL(aio_read64)(struct aiocb64 *aiocbp)
{
    int ret;

1435 1436
    PSX_PRE_WRAP();

1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
    MAP_OR_FAIL(aio_read64);

    ret = __real_aio_read64(aiocbp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        posix_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
        POSIX_UNLOCK();
    }

1448 1449
    PSX_POST_WRAP();

1450 1451 1452 1453 1454 1455 1456
    return(ret);
}

int DARSHAN_DECL(aio_write64)(struct aiocb64 *aiocbp)
{
    int ret;

1457 1458
    PSX_PRE_WRAP();

1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
    MAP_OR_FAIL(aio_write64);

    ret = __real_aio_write64(aiocbp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        posix_aio_tracker_add(aiocbp->aio_fildes, aiocbp);
        POSIX_UNLOCK();
    }

1470 1471
    PSX_POST_WRAP();

1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
    return(ret);
}

ssize_t DARSHAN_DECL(aio_return)(struct aiocb *aiocbp)
{
    int ret;
    double tm2;
    struct posix_aio_tracker *tmp;
    int aligned_flag = 0;

1482 1483
    PSX_PRE_WRAP();

1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
    MAP_OR_FAIL(aio_return);

    ret = __real_aio_return(aiocbp);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    tmp = posix_aio_tracker_del(aiocbp->aio_fildes, aiocbp);
    if (tmp)
    {
        if((unsigned long)aiocbp->aio_buf % darshan_mem_alignment == 0)
            aligned_flag = 1;
        if(aiocbp->aio_lio_opcode == LIO_WRITE)
        {
            POSIX_RECORD_WRITE(ret, aiocbp->aio_fildes,
                1, aiocbp->aio_offset, aligned_flag, 0,
                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,
                tmp->tm1, tm2);
        }
        free(tmp);
    }
    POSIX_UNLOCK();

1512 1513
    PSX_POST_WRAP();

1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
    return(ret);
}

ssize_t DARSHAN_DECL(aio_return64)(struct aiocb64 *aiocbp)
{
    int ret;
    double tm2;
    struct posix_aio_tracker *tmp;
    int aligned_flag = 0;

1524 1525
    PSX_PRE_WRAP();

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
    MAP_OR_FAIL(aio_return64);

    ret = __real_aio_return64(aiocbp);
    tm2 = darshan_core_wtime();

    POSIX_LOCK();
    posix_runtime_initialize();
    tmp = posix_aio_tracker_del(aiocbp->aio_fildes, aiocbp);
    if (tmp)
    {
        if((unsigned long)aiocbp->aio_buf % darshan_mem_alignment == 0)
            aligned_flag = 1;
        if(aiocbp->aio_lio_opcode == LIO_WRITE)
        {
            POSIX_RECORD_WRITE(ret, aiocbp->aio_fildes,
                1, aiocbp->aio_offset, aligned_flag, 0,
                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,
                tmp->tm1, tm2);
        }
        free(tmp);
    }
    POSIX_UNLOCK();

1554 1555
    PSX_POST_WRAP();

1556 1557 1558 1559 1560 1561 1562 1563 1564
    return(ret);
}

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

1565 1566
    PSX_PRE_WRAP();

1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
    MAP_OR_FAIL(lio_listio);

    ret = __real_lio_listio(mode, aiocb_list, nitems, sevp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        for(i = 0; i < nitems; i++)
        {
            posix_aio_tracker_add(aiocb_list[i]->aio_fildes, aiocb_list[i]);
        }
        POSIX_UNLOCK();
    }

1581 1582
    PSX_POST_WRAP();

1583 1584 1585 1586 1587 1588 1589 1590 1591
    return(ret);
}

int DARSHAN_DECL(lio_listio64)(int mode, struct aiocb64 *const aiocb_list[],
    int nitems, struct sigevent *sevp)
{
    int ret;
    int i;

1592 1593
    PSX_PRE_WRAP();

1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
    MAP_OR_FAIL(lio_listio64);

    ret = __real_lio_listio64(mode, aiocb_list, nitems, sevp);
    if(ret == 0)
    {
        POSIX_LOCK();
        posix_runtime_initialize();
        for(i = 0; i < nitems; i++)
        {
            posix_aio_tracker_add(aiocb_list[i]->aio_fildes, aiocb_list[i]);
        }
        POSIX_UNLOCK();
    }

1608 1609
    PSX_POST_WRAP();

1610 1611 1612
    return(ret);
}

1613 1614 1615
/**********************************************************
 * Internal functions for manipulating POSIX module state *
 **********************************************************/
1616

1617
/* initialize internal POSIX module data structures and register with darshan-core */
1618
static void posix_runtime_initialize()
1619
{
1620 1621
    struct darshan_module_funcs posix_mod_fns =
    {
1622
        .begin_shutdown = &posix_begin_shutdown,
1623
        .get_output_data = &posix_get_output_data,
1624
        .shutdown = &posix_shutdown
1625
    };
1626 1627
    void *psx_buf;
    int psx_buf_size;
1628

Shane Snyder's avatar
Shane Snyder committed
1629 1630
    /* don't do anything if already initialized or instrumenation is disabled */
    if(posix_runtime || instrumentation_disabled)
1631
        return;
1632

1633 1634
    /* register the posix module with darshan core */
    darshan_core_register_module(
1635
        DARSHAN_POSIX_MOD,
1636
        &posix_mod_fns,
1637 1638
        &psx_buf,
        &psx_buf_size,
1639
        &my_rank,
1640
        &darshan_mem_alignment);
1641

1642 1643
    /* return if no memory assigned by darshan-core */
    if(psx_buf_size == 0)
1644 1645 1646 1647 1648 1649 1650 1651 1652
        return;

    posix_runtime = malloc(sizeof(*posix_runtime));
    if(!posix_runtime)
        return;
    memset(posix_runtime, 0, sizeof(*posix_runtime));

    /* set maximum number of file records according to max memory limit */
    /* NOTE: maximum number of records is based on the size of a posix file record */
1653
    posix_runtime->file_array_size = psx_buf_size / sizeof(struct darshan_posix_file);
1654
    posix_runtime->file_array_ndx = 0;
1655 1656

    /* allocate array of runtime file records */
1657
    posix_runtime->file_runtime_array = malloc(posix_runtime->file_array_size *
1658
                                               sizeof(struct posix_file_runtime));
1659
    if(!posix_runtime->file_runtime_array)
1660 1661 1662 1663
    {
        posix_runtime->file_array_size = 0;
        return;
    }
1664
    memset(posix_runtime->file_runtime_array, 0, posix_runtime->file_array_size *
1665
           sizeof(struct posix_file_runtime));
1666

1667 1668
    /* store pointer to POSIX record buffer given by darshan-core */
    posix_runtime->file_record_array = (struct darshan_posix_file *)psx_buf;
1669

1670 1671
    return;
}
1672

1673
/* get a POSIX file record for the given file path */
1674
static struct posix_file_runtime* posix_file_by_name(const char *name)
1675
{
1676
    struct posix_file_runtime *file = NULL;
1677
    char *newname = NULL;
1678
    darshan_record_id file_id;
1679
    int file_alignment;
1680