darshan-posix.c 65.4 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>
Philip Carns's avatar
Philip Carns committed
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-dynamic.h"
34

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

42 43
DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
44 45
DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
46 47
DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
48 49 50 51
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));
52 53 54 55 56 57 58 59
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));
60 61 62 63 64
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));
65 66 67 68 69 70
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
71 72
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));
73 74
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
75
DARSHAN_FORWARD_DECL(close, int, (int fd));
76
DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
77 78 79 80 81 82 83 84
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));
85

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

94 95 96 97 98 99
/* 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. 
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
 *
 * 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.
116
 */
117
struct posix_file_runtime
118
{
119
    struct darshan_posix_file* file_record;
120 121 122
    int64_t offset;
    int64_t last_byte_read;
    int64_t last_byte_written;
Shane Snyder's avatar
Shane Snyder committed
123
    enum darshan_io_type last_io_type;
124 125 126
    double last_meta_end;
    double last_read_end;
    double last_write_end;
127 128 129 130
    void* access_root;
    int access_count;
    void* stride_root;
    int stride_count;
131
    struct posix_aio_tracker* aio_list;
132
    UT_hash_handle hlink;
133
};
134

135 136 137 138 139 140 141 142 143 144 145
/* 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.
146 147 148 149 150 151 152 153 154 155 156
 *
 * 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.
157
 */
158
struct posix_file_runtime_ref
159
{
160
    struct posix_file_runtime* file;
161 162 163 164
    int fd;
    UT_hash_handle hlink;
};

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

178
static struct posix_runtime *posix_runtime = NULL;
179
static pthread_mutex_t posix_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Shane Snyder's avatar
Shane Snyder committed
180
static int instrumentation_disabled = 0;
181
static int my_rank = -1;
182
static int darshan_mem_alignment = 1;
183

184 185 186 187 188
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);
189 190
static void posix_aio_tracker_add(int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(int fd, void *aiocbp);
191
static int posix_record_compare(const void* a, const void* b);
192 193
static void posix_record_reduction_op(void* infile_v, void* inoutfile_v,
    int *len, MPI_Datatype *datatype);
194 195 196
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);
197 198 199 200

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);
201 202
static void posix_shutdown(void);

203 204
#define POSIX_LOCK() pthread_mutex_lock(&posix_runtime_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_runtime_mutex)
205

206
#define POSIX_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
207
    struct posix_file_runtime* file; \
208
    if(__ret < 0) break; \
209
    if(darshan_core_excluded_path(__path)) break; \
210
    file = posix_file_by_name_setfd(__path, __ret); \
211
    if(!file) break; \
212
    if(__mode) \
213
        file->file_record->counters[POSIX_MODE] = __mode; \
214 215 216
    file->offset = 0; \
    file->last_byte_written = 0; \
    file->last_byte_read = 0; \
217
    if(__stream_flag)\
218
        file->file_record->counters[POSIX_FOPENS] += 1; \
219
    else \
220 221 222 223
        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); \
224 225 226
} while(0)

#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
227
    size_t stride; \
228
    int64_t this_offset; \
229
    struct posix_file_runtime* file; \
230
    int64_t file_alignment; \
231 232 233 234
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
    file = posix_file_by_fd(__fd); \
    if(!file) break; \
235
    if(__pread_flag) \
236 237 238 239
        this_offset = __pread_offset; \
    else \
        this_offset = file->offset; \
    if(this_offset > file->last_byte_read) \
240
        file->file_record->counters[POSIX_SEQ_READS] += 1;  \
241
    if(this_offset == (file->last_byte_read + 1)) \
242
        file->file_record->counters[POSIX_CONSEC_READS] += 1;  \
243
    if(this_offset > 0 && this_offset > file->last_byte_read \
244 245 246
        && file->last_byte_read != 0) \
        stride = this_offset - file->last_byte_read - 1; \
    else \
247
        stride = 0; \
248 249
    file->last_byte_read = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
250 251 252 253 254 255 256 257 258 259
    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); \
260
    if(!__aligned) \
261 262
        file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
263
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
264
        file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
Shane Snyder's avatar
Shane Snyder committed
265
    if(file->last_io_type == DARSHAN_IO_WRITE) \
266
        file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
Shane Snyder's avatar
Shane Snyder committed
267
    file->last_io_type = DARSHAN_IO_READ; \
268 269 270 271 272 273 274
    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); \
275 276 277
} while(0)

#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
278
    size_t stride; \
279
    int64_t this_offset; \
280
    struct posix_file_runtime* file; \
281
    int64_t file_alignment; \
282 283 284 285
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
    file = posix_file_by_fd(__fd); \
    if(!file) break; \
286
    if(__pwrite_flag) \
287 288 289 290
        this_offset = __pwrite_offset; \
    else \
        this_offset = file->offset; \
    if(this_offset > file->last_byte_written) \
291
        file->file_record->counters[POSIX_SEQ_WRITES] += 1; \
292
    if(this_offset == (file->last_byte_written + 1)) \
293
        file->file_record->counters[POSIX_CONSEC_WRITES] += 1; \
294
    if(this_offset > 0 && this_offset > file->last_byte_written \
295 296
        && file->last_byte_written != 0) \
        stride = this_offset - file->last_byte_written - 1; \
297
    else \
298
        stride = 0; \
299 300
    file->last_byte_written = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
301 302 303
    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; \
304
    if(__stream_flag) \
305
        file->file_record->counters[POSIX_FWRITES] += 1; \
306
    else \
307 308 309 310
        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); \
311
    if(!__aligned) \
312 313
        file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
314
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
315
        file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
Shane Snyder's avatar
Shane Snyder committed
316
    if(file->last_io_type == DARSHAN_IO_READ) \
317
        file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
Shane Snyder's avatar
Shane Snyder committed
318
    file->last_io_type = DARSHAN_IO_WRITE; \
319 320 321 322 323 324 325
    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); \
326
} while(0)
327

328 329
#define POSIX_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
    struct posix_file_runtime* file; \
330
    if(darshan_core_excluded_path(__path)) break; \
331 332 333 334 335 336 337 338
    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 { \
339 340
    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; \
341 342
} while(0)

343 344 345 346 347 348 349 350 351 352
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);


353 354 355 356
/**********************************************************
 *      Wrappers for POSIX I/O functions of interest      * 
 **********************************************************/

357
int DARSHAN_DECL(open)(const char *path, int flags, ...)
358 359 360 361 362
{
    int mode = 0;
    int ret;
    double tm1, tm2;

363 364
    PSX_PRE_WRAP();

365 366
    MAP_OR_FAIL(open);

367
    if(flags & O_CREAT) 
368 369 370 371 372 373
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

374
        tm1 = darshan_core_wtime();
375
        ret = __real_open(path, flags, mode);
376
        tm2 = darshan_core_wtime();
377 378 379
    }
    else
    {
380
        tm1 = darshan_core_wtime();
381
        ret = __real_open(path, flags);
382
        tm2 = darshan_core_wtime();
383 384
    }

385 386
    POSIX_LOCK();
    posix_runtime_initialize();
387
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
388
    POSIX_UNLOCK();
389

390 391
    PSX_POST_WRAP();

392 393 394
    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
395 396 397 398 399 400
int DARSHAN_DECL(open64)(const char *path, int flags, ...)
{
    int mode = 0;
    int ret;
    double tm1, tm2;

401 402
    PSX_PRE_WRAP();

403
    MAP_OR_FAIL(open64);
Shane Snyder's avatar
Shane Snyder committed
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424

    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();
425 426 427
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();

428 429
    PSX_POST_WRAP();

430 431 432 433 434 435 436 437
    return(ret);
}

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

438 439
    PSX_PRE_WRAP();

440 441 442 443 444 445 446 447 448 449 450
    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();

451 452
    PSX_POST_WRAP();

453 454 455 456 457 458 459 460
    return(ret);
}

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

461 462
    PSX_PRE_WRAP();

463
    MAP_OR_FAIL(creat64);
Shane Snyder's avatar
Shane Snyder committed
464

465 466 467 468 469 470
    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
471 472 473
    POSIX_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    POSIX_UNLOCK();

474 475
    PSX_POST_WRAP();

Shane Snyder's avatar
Shane Snyder committed
476 477 478
    return(ret);
}

479 480 481 482 483 484
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
{
    FILE* ret;
    int fd;
    double tm1, tm2;

485 486
    PSX_PRE_WRAP();

487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    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();

503 504
    PSX_POST_WRAP();

505 506 507 508 509 510 511 512 513
    return(ret);
}

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

514 515
    PSX_PRE_WRAP();

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
    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();

532 533
    PSX_POST_WRAP();

534 535 536
    return(ret);
}

537 538 539 540 541
int DARSHAN_DECL(mkstemp)(char* template)
{
    int ret;
    double tm1, tm2;

542 543
    PSX_PRE_WRAP();

544 545 546 547 548 549 550 551 552 553 554
    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();

555 556
    PSX_POST_WRAP();

557 558 559 560 561 562 563 564
    return(ret);
}

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

565 566
    PSX_PRE_WRAP();

567 568 569 570 571 572 573 574 575 576 577
    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();

578 579
    PSX_POST_WRAP();

580 581 582 583 584 585 586 587
    return(ret);
}

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

588 589
    PSX_PRE_WRAP();

590 591 592 593 594 595 596 597 598 599 600
    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();

601 602
    PSX_POST_WRAP();

603 604 605 606 607 608 609 610
    return(ret);
}

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

611 612
    PSX_PRE_WRAP();

613 614 615 616 617 618 619 620 621 622 623
    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();

624 625
    PSX_POST_WRAP();

626 627 628
    return(ret);
}

629 630 631 632 633 634
ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

635 636
    PSX_PRE_WRAP();

Shane Snyder's avatar
Shane Snyder committed
637
    MAP_OR_FAIL(read);
638

639
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
640 641 642 643 644 645 646 647 648 649

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

650 651
    PSX_POST_WRAP();

652 653 654 655 656 657 658 659 660
    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;

661 662
    PSX_PRE_WRAP();

663 664
    MAP_OR_FAIL(write);

665
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
666 667 668 669 670 671 672 673 674 675

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

676 677
    PSX_POST_WRAP();

678 679 680 681 682 683 684 685 686
    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;

687 688
    PSX_PRE_WRAP();

689 690
    MAP_OR_FAIL(pread);

691
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
692 693 694 695 696 697 698 699 700 701

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

702 703
    PSX_POST_WRAP();

704 705 706 707 708 709 710 711 712
    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;

713 714
    PSX_PRE_WRAP();

715 716
    MAP_OR_FAIL(pwrite);

717
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
718 719 720 721 722 723 724 725 726 727

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

728 729
    PSX_POST_WRAP();

730 731 732 733 734 735 736 737 738
    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;

739 740
    PSX_PRE_WRAP();

741 742
    MAP_OR_FAIL(pread64);

743
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
744 745 746 747 748 749 750 751 752 753

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

754 755
    PSX_POST_WRAP();

756 757 758 759 760 761 762 763 764
    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;

765 766
    PSX_PRE_WRAP();

767 768
    MAP_OR_FAIL(pwrite64);

769
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
770 771 772 773 774 775 776 777 778 779

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

780 781
    PSX_POST_WRAP();

782 783 784 785 786 787
    return(ret);
}

ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
788
    int aligned_flag = 1;
789 790 791
    int i;
    double tm1, tm2;

792 793
    PSX_PRE_WRAP();

794
    MAP_OR_FAIL(readv);
795

796 797 798 799
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
800
    }
801 802 803 804 805 806

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

    POSIX_LOCK();
807
    posix_runtime_initialize();
808 809 810
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

811 812
    PSX_POST_WRAP();

813 814 815 816 817 818
    return(ret);
}

ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
819
    int aligned_flag = 1;
820 821 822
    int i;
    double tm1, tm2;

823 824
    PSX_PRE_WRAP();

825
    MAP_OR_FAIL(writev);
826

827 828 829 830
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
831
    }
832 833 834 835 836 837

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

    POSIX_LOCK();
838
    posix_runtime_initialize();
839 840 841
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, 0, tm1, tm2);
    POSIX_UNLOCK();

842 843
    PSX_POST_WRAP();

844 845 846
    return(ret);
}

847 848 849 850 851 852
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;

853 854
    PSX_PRE_WRAP();

855 856
    MAP_OR_FAIL(fread);

857
    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876

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

877 878
    PSX_POST_WRAP();

879 880 881 882 883 884 885 886 887
    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;

888 889
    PSX_PRE_WRAP();

890 891
    MAP_OR_FAIL(fwrite);

892
    if((unsigned long)ptr % darshan_mem_alignment == 0) aligned_flag = 1;
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911

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

912 913
    PSX_POST_WRAP();

914 915 916 917 918 919 920 921 922
    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;

923 924
    PSX_PRE_WRAP();

925 926 927 928 929 930 931 932 933 934 935 936 937 938
    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;
939 940 941 942
            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;
943 944 945 946
        }
        POSIX_UNLOCK();
    }

947 948
    PSX_POST_WRAP();

949 950 951 952 953 954 955 956 957
    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;

958 959
    PSX_PRE_WRAP();

960 961 962 963 964 965 966 967 968 969 970 971 972 973
    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;
974 975 976 977
            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;
978 979 980 981
        }
        POSIX_UNLOCK();
    }

982 983
    PSX_POST_WRAP();

984 985 986 987 988 989 990 991 992
    return(ret);
}

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

993 994
    PSX_PRE_WRAP();

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
    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)
        {
1008
            file->offset = ftell(stream);
1009 1010 1011 1012
            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;
1013 1014 1015 1016
        }
        POSIX_UNLOCK();
    }

1017 1018
    PSX_POST_WRAP();

1019 1020 1021
    return(ret);
}

1022 1023 1024 1025 1026
int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
{
    int ret;
    double tm1, tm2;

1027 1028
    PSX_PRE_WRAP();

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
    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();

1043 1044
    PSX_POST_WRAP();

1045 1046 1047 1048 1049 1050 1051 1052
    return(ret);
}

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

1053 1054
    PSX_PRE_WRAP();

1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
    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();

1069 1070
    PSX_POST_WRAP();

1071 1072 1073 1074 1075 1076 1077 1078
    return(ret);
}

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

1079 1080
    PSX_PRE_WRAP();

1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
    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();

1095 1096
    PSX_POST_WRAP();

1097 1098 1099 1100 1101 1102 1103 1104
    return(ret);
}

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

1105 1106
    PSX_PRE_WRAP();

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
    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();

1121 1122
    PSX_POST_WRAP();

1123 1124 1125 1126 1127 1128 1129 1130 1131
    return(ret);
}

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

1132 1133
    PSX_PRE_WRAP();

1134 1135 1136