/* * (C) 2009 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #define _XOPEN_SOURCE 500 #define _GNU_SOURCE #include "darshan-runtime-config.h" #include #ifdef HAVE_MNTENT_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "uthash.h" #include "darshan-core.h" /* TODO is __progname_full needed here */ extern char* __progname; /* internal variable delcarations */ static struct darshan_core_runtime *darshan_core = NULL; static pthread_mutex_t darshan_core_mutex = PTHREAD_MUTEX_INITIALIZER; static int my_rank = -1; static int nprocs = -1; /* FS mount information */ #define DARSHAN_MAX_MNTS 64 #define DARSHAN_MAX_MNT_PATH 256 #define DARSHAN_MAX_MNT_TYPE 32 struct mnt_data { int64_t block_size; char path[DARSHAN_MAX_MNT_PATH]; char type[DARSHAN_MAX_MNT_TYPE]; }; static struct mnt_data mnt_data_array[DARSHAN_MAX_MNTS]; static int mnt_data_count = 0; /* prototypes for internal helper functions */ static void darshan_core_initialize( int *argc, char ***argv); static void darshan_core_shutdown( void); static void darshan_core_cleanup( struct darshan_core_runtime* core); static void darshan_get_logfile_name( char* logfile_name, int jobid, struct tm* start_tm); static void darshan_log_record_hints_and_ver( struct darshan_core_runtime* core); static void darshan_get_exe_and_mounts_root( struct darshan_core_runtime *core, char* trailing_data, int space_left); static char* darshan_get_exe_and_mounts( struct darshan_core_runtime *core); static void darshan_get_shared_record_ids( struct darshan_core_runtime *core, darshan_record_id *shared_recs); static int darshan_log_coll_open( char *logfile_name, MPI_File *log_fh); static int darshan_log_write_record_hash( MPI_File log_fh, struct darshan_core_record_ref *rec_hash, darshan_record_id *shared_recs, struct darshan_log_map *map); static int darshan_log_coll_write( MPI_File log_fh, void *buf, int count, struct darshan_log_map *map); #define DARSHAN_CORE_LOCK() pthread_mutex_lock(&darshan_core_mutex) #define DARSHAN_CORE_UNLOCK() pthread_mutex_unlock(&darshan_core_mutex) /* intercept MPI initialize and finalize to manage darshan core runtime */ int MPI_Init(int *argc, char ***argv) { int ret; ret = DARSHAN_MPI_CALL(PMPI_Init)(argc, argv); if(ret != MPI_SUCCESS) { return(ret); } darshan_core_initialize(argc, argv); return(ret); } int MPI_Init_thread(int *argc, char ***argv, int required, int *provided) { int ret; ret = DARSHAN_MPI_CALL(PMPI_Init_thread)(argc, argv, required, provided); if(ret != MPI_SUCCESS) { return(ret); } darshan_core_initialize(argc, argv); return(ret); } int MPI_Finalize(void) { int ret; darshan_core_shutdown(); ret = DARSHAN_MPI_CALL(PMPI_Finalize)(); return(ret); } /* *********************************** */ static void darshan_core_initialize(int *argc, char ***argv) { int i; int internal_timing_flag = 0; double init_start, init_time, init_max; char* truncate_string = ""; int truncate_offset; int chars_left = 0; DARSHAN_MPI_CALL(PMPI_Comm_size)(MPI_COMM_WORLD, &nprocs); DARSHAN_MPI_CALL(PMPI_Comm_rank)(MPI_COMM_WORLD, &my_rank); if(getenv("DARSHAN_INTERNAL_TIMING")) internal_timing_flag = 1; if(internal_timing_flag) init_start = DARSHAN_MPI_CALL(PMPI_Wtime)(); /* setup darshan runtime if darshan is enabled and hasn't been initialized already */ if(!getenv("DARSHAN_DISABLE") && !darshan_core) { /* TODO: darshan mem alignment code? */ /* allocate structure to track darshan_core_runtime information */ darshan_core = malloc(sizeof(*darshan_core)); if(darshan_core) { memset(darshan_core, 0, sizeof(*darshan_core)); darshan_core->log_job.uid = getuid(); darshan_core->log_job.start_time = time(NULL); darshan_core->log_job.nprocs = nprocs; darshan_core->wtime_offset = DARSHAN_MPI_CALL(PMPI_Wtime)(); /* record exe and arguments */ for(i=0; i<(*argc); i++) { chars_left = CP_EXE_LEN-strlen(darshan_core->exe); strncat(darshan_core->exe, (*argv)[i], chars_left); if(i < ((*argc)-1)) { chars_left = CP_EXE_LEN-strlen(darshan_core->exe); strncat(darshan_core->exe, " ", chars_left); } } /* if we don't see any arguments, then use glibc symbol to get * program name at least (this happens in fortran) */ if(argc == 0) { chars_left = CP_EXE_LEN-strlen(darshan_core->exe); strncat(darshan_core->exe, __progname, chars_left); chars_left = CP_EXE_LEN-strlen(darshan_core->exe); strncat(darshan_core->exe, " ", chars_left); } if(chars_left == 0) { /* we ran out of room; mark that string was truncated */ truncate_offset = CP_EXE_LEN - strlen(truncate_string); sprintf(&darshan_core->exe[truncate_offset], "%s", truncate_string); } /* collect information about command line and mounted file systems */ darshan_core->trailing_data = darshan_get_exe_and_mounts(darshan_core); } } if(internal_timing_flag) { init_time = DARSHAN_MPI_CALL(PMPI_Wtime)() - init_start; DARSHAN_MPI_CALL(PMPI_Reduce)(&init_time, &init_max, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); if(my_rank == 0) { printf("#darshan:\t\t