darshan-core.c 7.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *  (C) 2009 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "darshan-runtime-config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vfs.h>
17
#include <pthread.h>
18 19

#include <mpi.h>
20

21
#include "darshan-core.h"
22
#include "utlist.h"
23 24 25

extern char* __progname_full;

26 27 28
static void darshan_core_initialize(int *argc, char ***argv);
static void darshan_core_shutdown(void);

29
/* internal variables */
30
static struct darshan_core_job_runtime *darshan_core_job = NULL;
31
static pthread_mutex_t darshan_mutex = PTHREAD_MUTEX_INITIALIZER;
32

33 34 35
#define DARSHAN_LOCK() pthread_mutex_lock(&darshan_mutex)
#define DARSHAN_UNLOCK() pthread_mutex_unlock(&darshan_mutex)

36 37 38 39 40 41 42 43 44
#define DARSHAN_MOD_REGISTER(__mod) \
    LL_PREPEND(darshan_core_job->mod_list_head, __mod)
#define DARSHAN_MOD_SEARCH(__mod, __tmp) \
    LL_SEARCH(darshan_core_job->mod_list_head, __mod, __tmp, mod_cmp)
#define DARSHAN_MOD_ITER(__mod, __tmp) \
    LL_FOREACH_SAFE(darshan_core_job->mod_list_head, __mod, __tmp)
#define DARSHAN_MOD_DELETE(__mod) \
   LL_DELETE(darshan_core_job->mod_list_head, __mod)

45 46 47 48 49 50 51 52 53 54 55
/* intercept MPI initialize and finalize to initialize darshan */
int MPI_Init(int *argc, char ***argv)
{
    int ret;

    ret = DARSHAN_MPI_CALL(PMPI_Init)(argc, argv);
    if(ret != MPI_SUCCESS)
    {
        return(ret);
    }

56
    darshan_core_initialize(argc, argv);
57 58 59 60

    return(ret);
}

61
int MPI_Init_thread(int *argc, char ***argv, int required, int *provided)
62 63 64 65
{
    int ret;

    ret = DARSHAN_MPI_CALL(PMPI_Init_thread)(argc, argv, required, provided);
66
    if(ret != MPI_SUCCESS)
67 68 69 70
    {
        return(ret);
    }

71
    darshan_core_initialize(argc, argv);
72 73 74 75 76 77 78 79

    return(ret);
}

int MPI_Finalize(void)
{
    int ret;

80
    darshan_core_shutdown();
81 82 83 84 85

    ret = DARSHAN_MPI_CALL(PMPI_Finalize)();
    return(ret);
}

86 87
/* *********************************** */

88
static void darshan_core_initialize(int *argc, char ***argv)
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
{
    int i;
    int nprocs;
    int rank;
    int internal_timing_flag = 0;
    double init_start, init_time, init_max;
    char* truncate_string = "<TRUNCATED>";
    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, &rank);

    if(getenv("DARSHAN_INTERNAL_TIMING"))
        internal_timing_flag = 1;

105
    if(internal_timing_flag)
106 107 108
        init_start = DARSHAN_MPI_CALL(PMPI_Wtime)();

    /* setup darshan runtime if darshan is enabled and hasn't been initialized already */
109
    if(!getenv("DARSHAN_DISABLE") && !darshan_core_job)
110
    {
111 112 113
        /* allocate structure to track darshan_core_job information */
        darshan_core_job = malloc(sizeof(*darshan_core_job));
        if(darshan_core_job)
114
        {
115
            memset(darshan_core_job, 0, sizeof(*darshan_core_job));
116

117
            if(getenv("DARSHAN_DISABLE_TIMING"))
118
            {
119
                darshan_core_job->flags |= CP_FLAG_NOTIMING;
120 121
            }

122 123 124 125 126 127
            strcpy(darshan_core_job->log_job.version_string, CP_VERSION);
            darshan_core_job->log_job.magic_nr = CP_MAGIC_NR;
            darshan_core_job->log_job.uid = getuid();
            darshan_core_job->log_job.start_time = time(NULL);
            darshan_core_job->log_job.nprocs = nprocs;
            darshan_core_job->wtime_offset = DARSHAN_MPI_CALL(PMPI_Wtime)();
128 129 130 131

            /* record exe and arguments */
            for(i=0; i<(*argc); i++)
            {
132 133
                chars_left = CP_EXE_LEN-strlen(darshan_core_job->exe);
                strncat(darshan_core_job->exe, *(argv[i]), chars_left);
134 135
                if(i < ((*argc)-1))
                {
136 137
                    chars_left = CP_EXE_LEN-strlen(darshan_core_job->exe);
                    strncat(darshan_core_job->exe, " ", chars_left);
138 139 140 141 142 143 144 145
                }
            }

            /* if we don't see any arguments, then use glibc symbol to get
             * program name at least (this happens in fortran)
             */
            if(argc == 0)
            {
146 147 148 149
                chars_left = CP_EXE_LEN-strlen(darshan_core_job->exe);
                strncat(darshan_core_job->exe, __progname_full, chars_left);
                chars_left = CP_EXE_LEN-strlen(darshan_core_job->exe);
                strncat(darshan_core_job->exe, " <unknown args>", chars_left);
150 151 152 153 154 155
            }

            if(chars_left == 0)
            {
                /* we ran out of room; mark that string was truncated */
                truncate_offset = CP_EXE_LEN - strlen(truncate_string);
156
                sprintf(&darshan_core_job->exe[truncate_offset], "%s",
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
                    truncate_string);
            }
        }
    }

    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(rank == 0)
        {
            printf("#darshan:<op>\t<nprocs>\t<time>\n");
            printf("darshan:init\t%d\t%f\n", nprocs, init_max);
        }
    }

    return;
}

177
static void darshan_core_shutdown()
178
{
179
    struct darshan_core_module *mod, *tmp;
180 181 182 183 184
    int internal_timing_flag = 0;

    if(getenv("DARSHAN_INTERNAL_TIMING"))
        internal_timing_flag = 1;

185 186 187 188 189 190 191 192 193 194
    /* TODO: coordinate shutdown accross all registered modules */
    DARSHAN_MOD_ITER(mod, tmp)
    {
        printf("Shutting down %s module\n", mod->name);

        DARSHAN_MOD_DELETE(mod);
        free(mod);
    };

    free(darshan_core_job);
195 196 197 198

    return;
}

199 200 201 202 203
static int mod_cmp(struct darshan_core_module* a, struct darshan_core_module* b)
{
    return strcmp(a->name, b->name);
}

204
/* ********************************************************* */
205 206 207 208 209 210

void darshan_core_register_module(
    char *name,
    struct darshan_module_funcs *funcs,
    int *runtime_mem_limit)
{
211 212
    struct darshan_core_module tmp;
    struct darshan_core_module* mod;
213

214
    *runtime_mem_limit = 0;
215
    if(!darshan_core_job)
216 217 218
        return;

    DARSHAN_LOCK();
219 220 221 222 223

    /* see if this module is already registered */
    strncpy(tmp.name, name, DARSHAN_MOD_NAME_LEN);
    DARSHAN_MOD_SEARCH(mod, &tmp);
    if(mod)
224
    {
225 226 227 228 229 230
        /* if module is already registered, update module_funcs and return */
        /* NOTE: we do not recalculate memory limit here, just set to 0 */
        mod->mod_funcs = *funcs;

        DARSHAN_UNLOCK();
        return;
231 232
    }

233 234 235
    /* this module has not been registered yet, allocate and register it */
    mod = malloc(sizeof(*mod));
    if(!mod)
236 237 238 239
    {
        DARSHAN_UNLOCK();
        return;
    }
240
    memset(mod, 0, sizeof(*mod));
241

242 243 244
    strncpy(mod->name, name, DARSHAN_MOD_NAME_LEN);
    mod->mod_funcs = *funcs;
    DARSHAN_MOD_REGISTER(mod);
245

246 247
    /* TODO: something smarter than just 2 MiB per module */
    *runtime_mem_limit = 2 * 1024 * 1024;
248

249 250
    DARSHAN_UNLOCK();

251 252 253 254 255 256 257 258 259
    return;
}

void darshan_core_lookup_id(
    void *name,
    int len,
    int printable_flag,
    darshan_file_id *id)
{
260
    darshan_file_id tmp_id;
261

262
    if(!darshan_core_job)
263 264 265 266 267 268 269 270 271 272
        return;

    /* TODO: what do you do with printable flag? */

    /* hash the input name to get a unique id for this record */
    tmp_id = darshan_hash(name, len, 0);
    
    /* TODO: how to store the filename to hash mapping? */

    *id = tmp_id;
273 274 275
    return;
}

276 277
double darshan_core_wtime()
{
278
    if(!darshan_core_job || darshan_core_job->flags & CP_FLAG_NOTIMING)
279 280 281 282 283 284
    {
        return(0);
    }

    return DARSHAN_MPI_CALL(PMPI_Wtime)();
}
285 286 287 288 289 290 291 292 293

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */