Commit 5ecf4013 authored by Shane Snyder's avatar Shane Snyder

more docs + "NULL" example module implementation

parent 233f1607
/*
* (C) 2009 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#ifndef __DARSHAN_LOG_FORMAT_H
......@@ -39,7 +40,8 @@ typedef uint64_t darshan_record_id;
#define DARSHAN_MAX_MODS 16
typedef enum
{
DARSHAN_POSIX_MOD = 0,
DARSHAN_NULL_MOD = 0,
DARSHAN_POSIX_MOD,
DARSHAN_MPIIO_MOD,
DARSHAN_HDF5_MOD,
DARSHAN_PNETCDF_MOD,
......@@ -47,6 +49,7 @@ typedef enum
static char * const darshan_module_names[] =
{
"NULL",
"POSIX",
"MPI-IO",
"HDF5",
......
/*
* (C) 2015 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#ifndef __DARSHAN_MPIIO_LOG_FORMAT_H
......
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#ifndef __DARSHAN_NULL_LOG_FORMAT_H
#define __DARSHAN_NULL_LOG_FORMAT_H
#include "darshan-log-format.h"
/* integer counters for the "NULL" example module */
enum darshan_null_indices
{
NULL_BARS, /* count of number of 'bar' function calls */
NULL_BAR_DAT, /* arbitrary data value set by last call to 'bar' */
NULL_NUM_INDICES,
};
/* floating point counters for the "NULL" example module */
enum darshan_null_f_indices
{
NULL_F_BAR_TIMESTAMP, /* timestamp of the first call to function 'bar' */
NULL_F_BAR_DURATION, /* timer indicating duration of last call to 'bar' */
NULL_F_NUM_INDICES,
};
/* the darshan_null_record structure encompasses the high-level data/counters
* which would actually be logged to file by Darshan for the "NULL" example
* module. This example implementation logs the following data for each
* record:
* - a corresponding Darshan record identifier
* - the rank of the process responsible for the record
* - integer I/O counters (operation counts, I/O sizes, etc.)
* - floating point I/O counters (timestamps, cumulative timers, etc.)
*/
struct darshan_null_record
{
darshan_record_id f_id;
int64_t rank;
int64_t counters[NULL_NUM_INDICES];
double fcounters[NULL_F_NUM_INDICES];
};
#endif /* __DARSHAN_NULL_LOG_FORMAT_H */
all: lib/libdarshan.a
all: lib/libdarshan.a lib/darshan-null.o
DESTDIR =
srcdir = @srcdir@
......@@ -19,7 +19,7 @@ DARSHAN_LOG_FORMAT = $(srcdir)/../darshan-log-format.h
DARSHAN_VERSION = @DARSHAN_VERSION@
ifndef DISABLE_LDPRELOAD
all: lib/libdarshan.so
all: lib/libdarshan.so lib/darshan-null.po
endif
VPATH = $(srcdir)
......@@ -51,16 +51,22 @@ lib/darshan-common.o: lib/darshan-common.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
lib/darshan-common.po: lib/darshan-common.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/darshan-posix.o: lib/darshan-posix.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
lib/darshan-null.o: lib/darshan-null.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-null-log-format.h | lib
$(CC) $(CFLAGS) -c $< -o $@
lib/darshan-posix.po: lib/darshan-posix.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
lib/darshan-null.po: lib/darshan-null.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-null-log-format.h | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/darshan-mpiio.o: lib/darshan-mpiio.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
lib/darshan-posix.o: lib/darshan-posix.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-posix-log-format.h | lib
$(CC) $(CFLAGS) -c $< -o $@
lib/darshan-mpiio.po: lib/darshan-mpiio.c darshan.h $(DARSHAN_LOG_FORMAT) | lib
lib/darshan-posix.po: lib/darshan-posix.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-posix-log-format.h | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/darshan-mpiio.o: lib/darshan-mpiio.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-mpiio-log-format.h | lib
$(CC) $(CFLAGS) -c $< -o $@
lib/darshan-mpiio.po: lib/darshan-mpiio.c darshan.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-mpiio-log-format.h | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/lookup3.o: lib/lookup3.c
......
......@@ -34,38 +34,43 @@
#include <dlfcn.h>
#include <stdlib.h>
#define DARSHAN_FORWARD_DECL(name,ret,args) \
ret (*__real_ ## name)args = NULL
#define DARSHAN_FORWARD_DECL(__func,__ret,__args) \
__ret (*__real_ ## __func)__args = NULL
#define DARSHAN_DECL(__name) __name
#define DARSHAN_DECL(__func) __func
#define DARSHAN_MPI_CALL(func) __real_ ## func
#define DARSHAN_MPI_CALL(__func) __real_ ## __func
#define MAP_OR_FAIL(func) \
if (!(__real_ ## func)) \
#define MAP_OR_FAIL(__func) \
if (!(__real_ ## __func)) \
{ \
__real_ ## func = dlsym(RTLD_NEXT, #func); \
if(!(__real_ ## func)) { \
fprintf(stderr, "Darshan failed to map symbol: %s\n", #func); \
__real_ ## __func = dlsym(RTLD_NEXT, #__func); \
if(!(__real_ ## __func)) { \
fprintf(stderr, "Darshan failed to map symbol: %s\n", #__func); \
exit(1); \
} \
}
#else
#define DARSHAN_FORWARD_DECL(name,ret,args) \
extern ret __real_ ## name args;
#define DARSHAN_FORWARD_DECL(__name,__ret,__args) \
extern __ret __real_ ## __name __args;
#define DARSHAN_DECL(__name) __wrap_ ## __name
#define DARSHAN_MPI_CALL(func) func
#define DARSHAN_MPI_CALL(__func) __func
#define MAP_OR_FAIL(func)
#define MAP_OR_FAIL(__func)
#endif
/* macros for manipulating module's counter variables */
/* NOTE: */
/* macros for manipulating a module's counter variables */
/* NOTE: These macros assume a module's record stores integer
* and floating point counters in arrays, named counters and
* fcounters, respectively. __rec_p is the a pointer to the
* data record, __counter is the counter in question, and
* __value is the corresponding data value.
*/
#define DARSHAN_COUNTER_SET(__rec_p, __counter, __value) do{ \
(__rec_p)->counters[__counter] = __value; \
} while(0)
......@@ -102,6 +107,11 @@
(__rec_p)->counters[__counter] = __value; \
} while(0)
/* NOTE: This macro is for storing histogram counters with 10
* distinct buckets. For an example of how it is used, consult
* the POSIX module implementation, which stores histograms of
* access sizes for POSIX I/O functions.
*/
#define DARSHAN_BUCKET_INC(__rec_p, __counter_base, __value) do {\
if(__value < 101) \
(__rec_p)->counters[__counter_base] += 1; \
......@@ -128,10 +138,10 @@
/* module developers provide the following functions to darshan-core */
struct darshan_module_funcs
{
/* disable futher instrumentation within a module */
void (*disable_instrumentation)(void);
/* perform any necessary pre-shutdown steps */
void (*begin_shutdown)(void);
/* perform any necessary steps prior to reducing */
void (*prepare_for_reduction)(
void (*setup_reduction)(
darshan_record_id *shared_recs, /* input list of shared records */
int *shared_rec_count, /* in/out shared record count */
void **send_buf, /* send buffer for shared file reduction */
......
......@@ -258,14 +258,15 @@ void darshan_core_shutdown()
darshan_core = NULL;
/* we also need to set which modules were registered on this process and
* disable tracing within those modules while we shutdown
* call into those modules and give them a chance to perform any necessary
* pre-shutdown steps.
*/
for(i = 0; i < DARSHAN_MAX_MODS; i++)
{
if(final_core->mod_array[i])
{
local_mod_use[i] = 1;
final_core->mod_array[i]->mod_funcs.disable_instrumentation();
final_core->mod_array[i]->mod_funcs.begin_shutdown();
}
}
DARSHAN_CORE_UNLOCK();
......@@ -492,10 +493,10 @@ void darshan_core_shutdown()
}
/* if there are globally shared files, do a shared file reduction */
if(shared_rec_count && this_mod->mod_funcs.prepare_for_reduction &&
if(shared_rec_count && this_mod->mod_funcs.setup_reduction &&
this_mod->mod_funcs.record_reduction_op)
{
this_mod->mod_funcs.prepare_for_reduction(mod_shared_recs, &shared_rec_count,
this_mod->mod_funcs.setup_reduction(mod_shared_recs, &shared_rec_count,
&red_send_buf, &red_recv_buf, &rec_sz);
if(shared_rec_count)
......
......@@ -114,7 +114,7 @@ static int my_rank = -1;
#define MPIIO_UNLOCK() pthread_mutex_unlock(&mpiio_runtime_mutex)
static void mpiio_runtime_initialize(void);
static void mpiio_disable_instrumentation(void);
static void mpiio_begin_shutdown(void);
static void mpiio_shutdown(void);
static void mpiio_get_output_data(
void **buffer,
......@@ -123,7 +123,7 @@ static struct mpiio_file_runtime* mpiio_file_by_name_setfh(const char* name, MPI
static struct mpiio_file_runtime* mpiio_file_by_name(const char *name);
static void mpiio_record_reduction_op(void* infile_v, void* inoutfile_v,
int *len, MPI_Datatype *datatype);
static void mpiio_prepare_for_reduction(darshan_record_id *shared_recs,
static void mpiio_setup_reduction(darshan_record_id *shared_recs,
int *shared_rec_count, void **send_buf, void **recv_buf, int *rec_size);
static int mpiio_file_compare(const void* a, const void* b);
......@@ -192,8 +192,8 @@ static void mpiio_runtime_initialize()
int mem_limit;
struct darshan_module_funcs mpiio_mod_fns =
{
.disable_instrumentation = &mpiio_disable_instrumentation,
.prepare_for_reduction = &mpiio_prepare_for_reduction,
.begin_shutdown = &mpiio_begin_shutdown,
.setup_reduction = &mpiio_setup_reduction,
.record_reduction_op = &mpiio_record_reduction_op,
.get_output_data = &mpiio_get_output_data,
.shutdown = &mpiio_shutdown
......@@ -245,7 +245,7 @@ static void mpiio_runtime_initialize()
return;
}
static void mpiio_disable_instrumentation()
static void mpiio_begin_shutdown()
{
assert(mpiio_runtime);
......@@ -444,7 +444,7 @@ static void mpiio_record_reduction_op(
return;
}
static void mpiio_prepare_for_reduction(
static void mpiio_setup_reduction(
darshan_record_id *shared_recs,
int *shared_rec_count,
void **send_buf,
......
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE
#include "darshan-runtime-config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "uthash.h"
#include "darshan.h"
#include "darshan-null-log-format.h"
/* The "NULL" module is an example instrumentation module implementation provided
* with Darshan, primarily to indicate how arbitrary modules may be integrated
* into Darshan. In particular, this module demonstrates how to develop wrapper
* functions for intercepting functions of interest, how to best manage necessary
* runtime data structures, and how to coordinate with the darshan-core component,
* among other things. This module is not linked with the darshan-runtime library;
* it is intended mainly to serve as a basic stubbed out module implementation
* that may be reused and expanded on by developers adding new instrumentation modules.
*/
/* TODO: this probably shouldn't be here -- LD_PRELOADing POSIX wrappers will cause MPI linker dependency */
#ifdef DARSHAN_PRELOAD
extern double (*__real_PMPI_Comm_rank)(MPI_Comm comm, int *rank);
#endif
/* The DARSHAN_FORWARD_DECL macro (defined in darshan.h) is used to provide forward
* declarations for wrapped funcions, regardless if Darshan is used with statically
* or dynamically linked executables.
*/
DARSHAN_FORWARD_DECL(foo, int, (const char *name, int arg1, int arg2));
/* The null_record_runtime structure maintains necessary runtime metadata
* for a "NULL" module data record (darshan_null_record structure, defined
* in darshan-null-log-format.h). This metadata assists with the instrumenting
* of specific statistics in the file record.
*
* RATIONALE: In general, a module may need to track some stateful, volatile
* information regarding specific I/O statistics to aid in the instrumentation
* process. However, this information should not be stored in the darshan_null_record
* struct because we don't want it to appear in the final darshan log file.
* We therefore associate a null_record_runtime structure with each darshan_null_record
* structure in order to track this information.
*
* NOTE: The null_record_runtime struct contains a pointer to a darshan_null_record
* struct (see the *record_p member) rather than simply embedding an entire
* darshan_null_record struct. This is done so that all of the darshan_null_record
* structs can be kept contiguous in memory as a single array to simplify
* reduction, compression, and storage.
*/
struct null_record_runtime
{
/* Darshan record for the "NULL" example module */
struct darshan_null_record* record_p;
/* ... other runtime data ... */
/* hash table link for this record */
/* NOTE: it is entirely up to the module developer how to persist module
* records in memory as the instrumented application runs. These records
* could just as easily be stored in an array or linked list. That said,
* the data structure selection should be mindful of the resulting memory
* footprint and search time complexity to attempt minimize Darshan overheads.
* hash table and linked list implementations are available in uthash.h and
* utlist.h, respectively.
*/
UT_hash_handle hlink;
};
/* The null_runtime structure simply encapsulates global data structures needed
* by the module for instrumenting functions of interest and providing the output
* I/O data for this module to the darshan-core component at shutdown time.
*/
struct null_runtime
{
/* runtime_record_array is the array of runtime records for the "NULL" module. */
struct null_record_runtime* runtime_record_array;
/* record_array is the array of high-level Darshan records for the "NULL" module,
* each corresponding to the the runtime record structure stored at the same array
* index in runtime_record_array.
*/
struct darshan_null_record* record_array;
/* file_array_size is the maximum amount of records that can be stored in
* record_array (and consequentially, runtime_record_array).
*/
int rec_array_size;
/* file_array_ndx is the current index into both runtime_record_array and
* record_array.
*/
int rec_array_ndx;
/* record_hash is a pointer to a hash table of null_record_runtime structures
* currently maintained by the "NULL" module.
*/
struct null_record_runtime* record_hash;
};
/* null_runtime is the global data structure encapsulating "NULL" module state */
static struct null_runtime *null_runtime = NULL;
/* The null_runtime_mutex is a lock used when updating the null_runtime global
* structure (or any other global data structures). This is necessary to avoid race
* conditions as multiple threads execute function wrappers and update module state.
* NOTE: Recursive mutexes are used in case functions wrapped by this module call
* other wrapped functions that would result in deadlock, otherwise. This mechanism
* may not be necessary for all instrumentation modules.
*/
static pthread_mutex_t null_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
/* the instrumentation_disabled flag is used to toggle wrapper functions on/off */
static int instrumentation_disabled = 0;
/* my_rank indicates the MPI rank of this process */
static int my_rank = -1;
/* internal helper functions for the "NULL" module */
static void null_runtime_initialize(void);
static struct null_record_runtime* null_record_by_name(const char *name);
/* forward declaration for module functions needed to interface with darshan-core */
static void null_begin_shutdown(void);
static void null_get_output_data(void **buffer, int *size);
static void null_shutdown(void);
/* macros for obtaining/releasing the "NULL" module lock */
#define NULL_LOCK() pthread_mutex_lock(&null_runtime_mutex)
#define NULL_UNLOCK() pthread_mutex_unlock(&null_runtime_mutex)
/* macro for instrumenting the "NULL" module's foo function */
/* NOTE: this macro makes use of the DARSHAN_COUNTER_* macros defined
* and documented in darshan.h.
*/
#define NULL_RECORD_FOO(__ret, __name, __dat, __tm1, __tm2) do{ \
struct null_record_runtime* rec; \
double elapsed = __tm2 - __tm1; \
/* if foo returns error (return code < 0), don't instrument anything */ \
if(__ret < 0) break; \
/* use '__name' to lookup a corresponding "NULL" record */ \
rec = null_record_by_name(__name); \
if(!rec) break; \
/* increment counter indicating number of calls to 'bar' */ \
DARSHAN_COUNTER_INC(rec->record_p, NULL_BARS, 1); \
/* store data value for most recent call to 'bar' */ \
DARSHAN_COUNTER_SET(rec->record_p, NULL_BAR_DAT, __dat); \
/* store timestamp of most recent call to 'bar' */ \
DARSHAN_COUNTER_F_SET(rec->record_p, NULL_F_BAR_TIMESTAMP, __tm1); \
/* store duration of most recent call to 'bar' */ \
DARSHAN_COUNTER_F_SET(rec->record_p, NULL_F_BAR_DURATION, elapsed); \
} while(0)
/**********************************************************
* Wrappers for "NULL" module functions of interest *
**********************************************************/
/* The DARSHAN_DECL macro provides the appropriate wrapper function names,
* depending on whether the Darshan library is statically or dynamically linked.
*/
int DARSHAN_DECL(foo)(const char* name, int arg1, int arg2)
{
ssize_t ret;
double tm1, tm2;
/* The MAP_OR_FAIL macro attempts to obtain the address of the actual
* underlying foo function call (__real_foo), in the case of LD_PRELOADing
* the Darshan library. For statically linked executables, this macro is
* just a NOP.
*/
MAP_OR_FAIL(foo);
/* In general, Darshan wrappers begin by calling the real version of the
* given wrapper function. Timers are used to record the duration of this
* operation. */
tm1 = darshan_core_wtime();
ret = __real_foo(name, arg1, arg2);
tm2 = darshan_core_wtime();
NULL_LOCK();
/* Before attempting to instrument I/O statistics for function foo, make
* sure the "NULL" module runtime environment has been initialized.
* NOTE: this runtime environment is initialized only once -- if the
* appropriate structures have already been initialized, this function simply
* returns.
*/
null_runtime_initialize();
/* Call macro for instrumenting data for foo function calls. */
NULL_RECORD_FOO(ret, name, arg1+arg2, tm1, tm2);
NULL_UNLOCK();
return(ret);
}
/**********************************************************
* Internal functions for manipulating POSIX module state *
**********************************************************/
/* Initialize internal POSIX module data structures and register with darshan-core. */
static void null_runtime_initialize()
{
/* struct of function pointers for interfacing with darshan-core */
struct darshan_module_funcs null_mod_fns =
{
.begin_shutdown = &null_begin_shutdown,
.setup_reduction = NULL, /* "NULL" module does not do reductions */
.record_reduction_op = NULL, /* "NULL" module does not do reductions */
.get_output_data = &null_get_output_data,
.shutdown = &null_shutdown
};
int mem_limit; /* max. memory this module can consume, dictated by darshan-core */
/* don't do anything if already initialized or instrumenation is disabled */
if(null_runtime || instrumentation_disabled)
return;
/* register the "NULL" module with the darshan-core component */
darshan_core_register_module(
DARSHAN_NULL_MOD, /* Darshan module identifier, defined in darshan-log-format.h */
&null_mod_fns,
&mem_limit,
NULL);
/* return if no memory assigned by darshan-core */
if(mem_limit == 0)
return;
/* initialize module's global state */
null_runtime = malloc(sizeof(*null_runtime));
if(!null_runtime)
return;
memset(null_runtime, 0, sizeof(*null_runtime));
/* Set the maximum number of data records this module may track, as indicated
* by mem_limit (set by darshan-core).
* NOTE: We interpret the maximum memory limit to be related to the maximum
* amount of data which may be written to log by a single process for a given
* module. We therefore use this maximum memory limit to determine how many
* darshan_null_record structures we can track per process.
*/
null_runtime->rec_array_size = mem_limit / sizeof(struct darshan_null_record);
null_runtime->rec_array_ndx = 0;
/* allocate both record arrays (runtime and high-level records) */
null_runtime->runtime_record_array = malloc(null_runtime->rec_array_size *
sizeof(struct null_record_runtime));
null_runtime->record_array = malloc(null_runtime->rec_array_size *
sizeof(struct darshan_null_record));
if(!null_runtime->runtime_record_array || !null_runtime->record_array)
{
null_runtime->rec_array_size = 0;
return;
}
memset(null_runtime->runtime_record_array, 0, null_runtime->rec_array_size *
sizeof(struct null_record_runtime));
memset(null_runtime->record_array, 0, null_runtime->rec_array_size *
sizeof(struct darshan_null_record));
/* TODO: we should move this out of here.. perhaps register_module returns rank? */
DARSHAN_MPI_CALL(PMPI_Comm_rank)(MPI_COMM_WORLD, &my_rank);
return;
}
/* Search for and return a "NULL" module record corresponding to name parameter. */
static struct null_record_runtime* null_record_by_name(const char *name)
{
struct null_record_runtime *rec = NULL;
darshan_record_id rec_id;
/* Don't search for a record if the "NULL" module is not initialized or
* if instrumentation has been toggled off.
*/
if(!null_runtime || instrumentation_disabled)
return(NULL);
/* get a unique record identifier for this record from darshan-core */
darshan_core_register_record(
(void*)name,
strlen(name),
1,
DARSHAN_NULL_MOD,
&rec_id,
NULL);
/* search the hash table for this file record, and return if found */
HASH_FIND(hlink, null_runtime->record_hash, &rec_id, sizeof(darshan_record_id), rec);
if(rec)
{
return(rec);
}
if(null_runtime->rec_array_ndx < null_runtime->rec_array_size);
{
/* no existing record, assign a new one from the global array */
rec = &(null_runtime->runtime_record_array[null_runtime->rec_array_ndx]);
rec->record_p = &(null_runtime->record_array[null_runtime->rec_array_ndx]);
/* set the darshan record id and corresponding process rank for this record */
rec->record_p->f_id = rec_id;
rec->record_p->rank = my_rank;
/* add new record to file hash table */
HASH_ADD(hlink, null_runtime->record_hash, record_p->f_id, sizeof(darshan_record_id), rec);
null_runtime->rec_array_ndx++;
}
return(rec);
}
/******************************************************************************
* Functions exported by the "NULL" module for coordinating with darshan-core *
******************************************************************************/
/* Perform any necessary steps prior to shutting down for the "NULL" module. */
static void null_begin_shutdown()
{
assert(null_runtime);
NULL_LOCK();
/* In general, we want to disable all wrappers while Darshan shuts down.
* This is to avoid race conditions and ensure data consistency, as
* executing wrappers could potentially modify module state while Darshan
* is in the process of shutting down.
*/
instrumentation_disabled = 1;
/* ... any other code which needs to be executed before beginning shutdown process ... */
NULL_UNLOCK();
return;
}
/* Pass output data for the "NULL" module back to darshan-core to log to file. */
static void null_get_output_data(
void **buffer,
int *size)
{
assert(null_runtime);
/* Just set the output buffer to point at the array of the "NULL" module's
* I/O records, and set the output size according to the number of records
* currently being tracked.
*/
*buffer = (void *)(null_runtime->record_array);
*size = null_runtime->rec_array_ndx * sizeof(struct darshan_null_record);
return;
}
/* Shutdown the "NULL" module by freeing up all data structures. */
static void null_shutdown()
{
assert(null_runtime);
HASH_CLEAR(hlink, null_runtime->record_hash); /* these hash entries are freed all at once below */
free(null_runtime->runtime_record_array);
free(null_runtime->record_array);
free(null_runtime);
null_runtime = NULL;
return;
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ts=8 sts=4 sw=4 expandtab
*/
......@@ -215,9 +215,9 @@ static void posix_walk_file_accesses(void);
static int posix_access_compare(const void* a_p, const void* b_p);
static int posix_file_compare(const void* a, const void* b);
static void posix_disable_instrumentation(void);
static void posix_prepare_for_reduction(darshan_record_id *shared_recs,
int *shared_rec_count, void **send_buf, void **recv_buf, int *rec_size);
static void posix_begin_shutdown(void);
static void posix_setup_reduction(darshan_record_id *shared_recs, int *shared_rec_count,
void **send_buf, void **recv_buf, int *rec_size);
static void posix_record_reduction_op(void* infile_v, void* inoutfile_v,
int *len, MPI_Datatype *datatype);
static void posix_get_output_data(void **buffer, int *size);
......@@ -1295,8 +1295,8 @@ static void posix_runtime_initialize()
int mem_limit;
struct darshan_module_funcs posix_mod_fns =
{
.disable_instrumentation = &posix_disable_instrumentation,
.prepare_for_reduction = &posix_prepare_for_reduction,
.begin_shutdown = &posix_begin_shutdown,
.setup_reduction = &posix_setup_reduction,
.record_reduction_op = &posix_record_reduction_op,
.get_output_data = &posix_get_output_data,
.shutdown = &posix_shutdown
......@@ -1627,21 +1627,25 @@ static int posix_file_compare(const void* a_p, const void* b_p)
* Functions exported by this module for coordinating with darshan-core *
************************************************************************/
static void posix_disable_instrumentation()
static void posix_begin_shutdown()
{
assert(posix_runtime);
POSIX_LOCK();
/* go through file access data for each record and set the 4 most common
* stride/access size counters.
*/
posix_walk_file_accesses();
/* disable further instrumentation while Darshan shuts down */
instrumentation_disabled = 1;
POSIX_UNLOCK();
return;
}
static void posix_prepare_for_reduction(
static void posix_setup_reduction(
darshan_record_id *shared_recs,
int *shared_rec_count,
void **send_buf,
......@@ -1980,6 +1984,8 @@ static void posix_shutdown()
{
struct posix_file_runtime_ref *ref, *tmp;
assert(posix_runtime);
HASH_ITER(hlink, posix_runtime->fd_hash, ref, tmp)
{