Commit 96f35fd9 authored by Philip Carns's avatar Philip Carns

fix memory leaks

- unrelated to the purpose of this branch, but necessary to get asan to
  pass while testing changes.  One of these is important and would have
  leaked a small amount of memory with every blocking abt_io call
parent 85807d78
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignConsecutiveBitFields: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Left
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(margo)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: false
IndentPPDirectives: BeforeHash
IndentExternBlock: AfterExternBlock
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- MARGO_REGISTER
- MARGO_REGISTER_PROVIDER
- DEFINE_MARGO_RPC_HANDLER
- DECLARE_MARGO_RPC_HANDLER
- MERCURY_GEN_PROC
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- MERCURY_GEN_PROC
...
......@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67])
AC_INIT([abt-io], [0.4], [],[],[])
AC_INIT([abt-io], [0.5], [],[],[])
AC_CONFIG_MACRO_DIRS([m4])
LT_INIT
......@@ -50,11 +50,11 @@ LIBS="$ARGOBOTS_LIBS $LIBS"
CPPFLAGS="$ARGOBOTS_CFLAGS $CPPFLAGS"
CFLAGS="$ARGOBOTS_CFLAGS $CFLAGS"
PKG_CHECK_MODULES([MOCHICFG],[mochi-cfg],[],
[AC_MSG_ERROR([Could not find working mochi-cfg installation!])])
LIBS="$MOCHICFG_LIBS $LIBS"
CPPFLAGS="$MOCHICFG_CFLAGS $CPPFLAGS"
CFLAGS="$MOCHICFG_CFLAGS $CFLAGS"
PKG_CHECK_MODULES([JSONC],[json-c],[],
[AC_MSG_ERROR([Could not find working json-c installation!])])
LIBS="$JSONC_LIBS $LIBS"
CPPFLAGS="$JSONC_CFLAGS $CPPFLAGS"
CFLAGS="$JSONC_CFLAGS -DMARGO_USE_JSON_C $CFLAGS"
AC_MSG_CHECKING([for fallocate])
AC_TRY_COMPILE([
......
This diff is collapsed.
This diff is collapsed.
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
......@@ -17,45 +17,44 @@
#include "abt-io-config.h"
#ifndef HAVE_ODIRECT
#define O_DIRECT 0
#define O_DIRECT 0
#endif
struct worker_pthread_common
{
int opt_io;
int opt_compute;
int opt_unit_size;
int opt_num_units;
pthread_cond_t cond;
struct worker_pthread_common {
int opt_io;
int opt_compute;
int opt_unit_size;
int opt_num_units;
pthread_cond_t cond;
pthread_mutex_t mutex;
int completed;
int inflight_threads;
int completed;
int inflight_threads;
};
struct worker_pthread_arg
{
struct worker_pthread_common *common;
void* buffer;
struct worker_pthread_arg {
struct worker_pthread_common* common;
void* buffer;
};
static void *worker_pthread(void *_arg);
static void* worker_pthread(void* _arg);
static double wtime(void);
int main(int argc, char **argv)
int main(int argc, char** argv)
{
int ret;
double seconds;
double end, start;
int i;
struct worker_pthread_arg *arg_array;
int ret;
double seconds;
double end, start;
int i;
struct worker_pthread_arg* arg_array;
struct worker_pthread_common common;
pthread_attr_t attr;
pthread_t tid;
if(argc != 6)
{
fprintf(stderr, "Usage: pthread-overlap <compute> <io> <unit_size> <num_units> <inflight_threads>\n");
return(-1);
pthread_attr_t attr;
pthread_t tid;
if (argc != 6) {
fprintf(stderr,
"Usage: pthread-overlap <compute> <io> <unit_size> <num_units> "
"<inflight_threads>\n");
return (-1);
}
ret = sscanf(argv[1], "%d", &common.opt_compute);
......@@ -74,11 +73,10 @@ int main(int argc, char **argv)
pthread_mutex_init(&common.mutex, NULL);
common.completed = 0;
arg_array = malloc(sizeof(*arg_array)*common.opt_num_units);
arg_array = malloc(sizeof(*arg_array) * common.opt_num_units);
assert(arg_array);
for(i=0; i<common.opt_num_units; i++)
{
for (i = 0; i < common.opt_num_units; i++) {
arg_array[i].common = &common;
ret = posix_memalign(&arg_array[i].buffer, 4096, common.opt_unit_size);
assert(ret == 0);
......@@ -90,10 +88,9 @@ int main(int argc, char **argv)
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
for(i=0; i<common.opt_num_units; i++)
{
for (i = 0; i < common.opt_num_units; i++) {
pthread_mutex_lock(&common.mutex);
while((i + 1 - common.completed) >= common.inflight_threads)
while ((i + 1 - common.completed) >= common.inflight_threads)
pthread_cond_wait(&common.cond, &common.mutex);
pthread_mutex_unlock(&common.mutex);
......@@ -103,55 +100,56 @@ int main(int argc, char **argv)
}
pthread_mutex_lock(&common.mutex);
while(common.completed < common.opt_num_units)
while (common.completed < common.opt_num_units)
pthread_cond_wait(&common.cond, &common.mutex);
pthread_mutex_unlock(&common.mutex);
end = wtime();
seconds = end-start;
seconds = end - start;
pthread_mutex_destroy(&common.mutex);
pthread_cond_destroy(&common.cond);
for(i=0; i<common.opt_num_units; i++)
free(arg_array[i].buffer);
for (i = 0; i < common.opt_num_units; i++) free(arg_array[i].buffer);
free(arg_array);
assert(common.opt_num_units == common.completed);
printf("#<opt_compute>\t<opt_io>\t<opt_unit_size>\t<opt_num_units>\t<time (s)>\t<bytes/s>\t<ops/s>\n");
printf("%d\t%d\t%d\t%d\t%f\t%f\t%f\n", common.opt_compute, common.opt_io,
common.opt_unit_size, common.opt_num_units, seconds, ((double)common.opt_unit_size* (double)common.opt_num_units)/seconds, (double)common.opt_num_units/seconds);
return(0);
printf(
"#<opt_compute>\t<opt_io>\t<opt_unit_size>\t<opt_num_units>\t<time "
"(s)>\t<bytes/s>\t<ops/s>\n");
printf("%d\t%d\t%d\t%d\t%f\t%f\t%f\n", common.opt_compute, common.opt_io,
common.opt_unit_size, common.opt_num_units, seconds,
((double)common.opt_unit_size * (double)common.opt_num_units)
/ seconds,
(double)common.opt_num_units / seconds);
return (0);
}
static void *worker_pthread(void *_arg)
static void* worker_pthread(void* _arg)
{
struct worker_pthread_arg* arg = _arg;
struct worker_pthread_common *common = arg->common;
void *buffer = arg->buffer;
size_t ret;
struct worker_pthread_arg* arg = _arg;
struct worker_pthread_common* common = arg->common;
void* buffer = arg->buffer;
size_t ret;
char template[256];
int fd;
if(common->opt_compute)
{
if (common->opt_compute) {
ret = RAND_bytes(buffer, common->opt_unit_size);
assert(ret == 1);
}
sprintf(template, "./data-XXXXXX");
if(common->opt_io)
{
if (common->opt_io) {
#ifdef HAVE_MKOSTEMP
fd = mkostemp(template, O_DIRECT|O_SYNC);
fd = mkostemp(template, O_DIRECT | O_SYNC);
#else
fd = mkstemp(template);
#endif
if(fd < 0)
{
if (fd < 0) {
perror("mkostemp");
fprintf(stderr, "errno: %d\n", errno);
}
......@@ -172,13 +170,13 @@ static void *worker_pthread(void *_arg)
pthread_cond_signal(&common->cond);
pthread_mutex_unlock(&common->mutex);
return(NULL);
return (NULL);
}
static double wtime(void)
{
struct timeval t;
gettimeofday(&t, NULL);
return((double)t.tv_sec + (double)t.tv_usec / 1000000.0);
return ((double)t.tv_sec + (double)t.tv_usec / 1000000.0);
}
......@@ -15,6 +15,8 @@ extern "C" {
#include <sys/types.h>
#include <stdlib.h>
#define DEPRECATED(msg) __attribute__((deprecated(msg)))
struct abt_io_instance;
typedef struct abt_io_instance* abt_io_instance_id;
......@@ -23,6 +25,18 @@ typedef struct abt_io_instance* abt_io_instance_id;
struct abt_io_op;
typedef struct abt_io_op abt_io_op_t;
/**
* The abt_io_init_info structure should be passed to abt_io_init_ext
* to finely configure abt-io. The structure can be memset to 0 to have
* abt-io use default values. For any field that is not NULL,
* abt_io_init_ext will first look for a configuration in the json_config
* string. If no configuration is found or of json_config is NULL, abt-io
* will fall back to default.
*/
struct abt_io_init_info {
const char* json_config; /* JSON-formatted string */
ABT_pool progress_pool; /* Progress pool */
};
/**
* Initializes abt_io library, using the specified number of backing threads. A
......@@ -34,14 +48,40 @@ typedef struct abt_io_op abt_io_op_t;
*/
abt_io_instance_id abt_io_init(int backing_thread_count);
/* ------- abt-io configuration examples ------
*
* optional input fields for convenience. This will cause abt-io to create
* an internal service pool with N execution streams in it.
* --------------
* {"backing_thread_count": 16}
*
* The user may also pass in an explicit pool. If so, the resulting json
* will look like this:
* --------------
* {"internal_pool_flag": 0}
*
* This is the fully resolved json description of an internal pool (may be
* passed in explicitly, or will be generated based on the
* backing_thread_count json parameter.
* --------------
* {"internal_pool_flag": 1,
* "internal_pool":{
* "kind":"fifo_wait",
* "access":"mpmc",
* "num_xstreams": 4
* }
* }
*/
/**
* Initializes abt_io library using configuration parameters specified in
* json_cfg_string
* Initializes an abt-io instance using an abt_io_init_info struct to provide
* arguments.
*
* @param [in] json_cfg_string configuration parameters
* @returns abt_io instance id on success, NULL upon error
* @param args Arguments
*
* @return an abt_io_instance_id or ABT_IO_INSTANCE_NULL in case of failure.
*/
abt_io_instance_id abt_io_init_json(const char* json_cfg_string);
abt_io_instance_id abt_io_init_ext(const struct abt_io_init_info* args);
/**
* Initializes abt_io library using the specified Argobots pool for operation
......@@ -49,15 +89,8 @@ abt_io_instance_id abt_io_init_json(const char* json_cfg_string);
* @param [in] progress_pool Argobots pool to drive I/O
* @returns abt_io instance id on success, NULL upon error
*/
abt_io_instance_id abt_io_init_pool(ABT_pool progress_pool);
/**
* Retrieves complete configuration of abt_io, encoded as json
*
* @param [in] aid abt-io instance
* @returns null terminated string that must be free'd by caller
*/
char* abt_io_get_config(abt_io_instance_id aid);
abt_io_instance_id abt_io_init_pool(ABT_pool progress_pool)
DEPRECATED("use abt_io_init_ext instead");
/**
* Shuts down abt_io library and its underlying resources. Waits for underlying
......@@ -67,131 +100,105 @@ char* abt_io_get_config(abt_io_instance_id aid);
*/
void abt_io_finalize(abt_io_instance_id aid);
/**
/**
* wrapper for open()
*/
int abt_io_open(
abt_io_instance_id aid,
const char* pathname,
int flags,
mode_t mode);
int abt_io_open(abt_io_instance_id aid,
const char* pathname,
int flags,
mode_t mode);
/**
/**
* non-blocking wrapper for open()
*/
abt_io_op_t* abt_io_open_nb(
abt_io_instance_id aid,
const char* pathname,
int flags,
mode_t mode,
int *ret);
abt_io_op_t* abt_io_open_nb(abt_io_instance_id aid,
const char* pathname,
int flags,
mode_t mode,
int* ret);
/**
* wrapper for pwrite()
*/
ssize_t abt_io_pwrite(
abt_io_instance_id aid,
int fd,
const void *buf,
size_t count,
off_t offset);
ssize_t abt_io_pwrite(abt_io_instance_id aid,
int fd,
const void* buf,
size_t count,
off_t offset);
/**
* non-blocking wrapper for pwrite()
*/
abt_io_op_t* abt_io_pwrite_nb(
abt_io_instance_id aid,
int fd,
const void *buf,
size_t count,
off_t offset,
ssize_t *ret);
abt_io_op_t* abt_io_pwrite_nb(abt_io_instance_id aid,
int fd,
const void* buf,
size_t count,
off_t offset,
ssize_t* ret);
/**
* wrapper for write()
*/
ssize_t abt_io_write(
abt_io_instance_id aid,
int fd,
const void *buf,
size_t count);
ssize_t
abt_io_write(abt_io_instance_id aid, int fd, const void* buf, size_t count);
/**
* non-blocking wrapper for write()
*/
abt_io_op_t* abt_io_write_nb(
abt_io_instance_id aid,
int fd,
const void *buf,
size_t count,
ssize_t *ret);
abt_io_op_t* abt_io_write_nb(abt_io_instance_id aid,
int fd,
const void* buf,
size_t count,
ssize_t* ret);
/**
* wrapper for pread()
*/
ssize_t abt_io_pread(
abt_io_instance_id aid,
int fd,
void *buf,
size_t count,
off_t offset);
abt_io_instance_id aid, int fd, void* buf, size_t count, off_t offset);
/**
* non-blocking wrapper for pread()
*/
abt_io_op_t* abt_io_pread_nb(
abt_io_instance_id aid,
int fd,
void *buf,
size_t count,
off_t offset,
ssize_t *ret);
abt_io_op_t* abt_io_pread_nb(abt_io_instance_id aid,
int fd,
void* buf,
size_t count,
off_t offset,
ssize_t* ret);
/**
* wrapper for read()
*/
ssize_t abt_io_read(
abt_io_instance_id aid,
int fd,
void *buf,
size_t count);
ssize_t abt_io_read(abt_io_instance_id aid, int fd, void* buf, size_t count);
/**
* non-blocking wrapper for read()
*/
abt_io_op_t* abt_io_read_nb(
abt_io_instance_id aid,
int fd,
void *buf,
size_t count,
ssize_t *ret);
abt_io_instance_id aid, int fd, void* buf, size_t count, ssize_t* ret);
/**
* wrapper for mkostemp()
*/
int abt_io_mkostemp(abt_io_instance_id aid, char *tpl, int flags);
int abt_io_mkostemp(abt_io_instance_id aid, char* tpl, int flags);
/**
* non-blocking wrapper for mkostemp()
*/
abt_io_op_t* abt_io_mkostemp_nb(
abt_io_instance_id aid,
char *tpl,
int flags,
int *ret);
abt_io_op_t*
abt_io_mkostemp_nb(abt_io_instance_id aid, char* tpl, int flags, int* ret);
/**
/**
* wrapper for unlink()
*/
int abt_io_unlink(abt_io_instance_id aid, const char *pathname);
int abt_io_unlink(abt_io_instance_id aid, const char* pathname);
/**
/**
* non-blocking wrapper for unlink()
*/
abt_io_op_t* abt_io_unlink_nb(
abt_io_instance_id aid,
const char *pathname,
int *ret);
abt_io_op_t*
abt_io_unlink_nb(abt_io_instance_id aid, const char* pathname, int* ret);
/**
* wrapper for fdatasync()
......@@ -201,7 +208,7 @@ int abt_io_fdatasync(abt_io_instance_id aid, int fd);
/**
* non-blocking wrapper for fdatasync()
*/
abt_io_op_t* abt_io_fdatasync_nb(abt_io_instance_id aid, int fd, int *ret);
abt_io_op_t* abt_io_fdatasync_nb(abt_io_instance_id aid, int fd, int* ret);
/**
* wrapper for close()
......@@ -211,17 +218,23 @@ int abt_io_close(abt_io_instance_id aid, int fd);
/**
* non-blocking wrapper for close()
*/
abt_io_op_t* abt_io_close_nb(abt_io_instance_id aid, int fd, int *ret);
abt_io_op_t* abt_io_close_nb(abt_io_instance_id aid, int fd, int* ret);
/**
* wrapper for fallocate() (if available on this platform)
*/
int abt_io_fallocate(abt_io_instance_id aid, int fd, int mode, off_t offset, off_t len);
int abt_io_fallocate(
abt_io_instance_id aid, int fd, int mode, off_t offset, off_t len);
/**
* non-blocking wrapper for fallocate() (if available on this platform)
*/
abt_io_op_t* abt_io_fallocate_nb(abt_io_instance_id aid, int fd, int mode, off_t offset, off_t len, int *ret);
abt_io_op_t* abt_io_fallocate_nb(abt_io_instance_id aid,
int fd,
int mode,
off_t offset,
off_t len,
int* ret);
/**
* wait on an abt-io operation
......@@ -240,6 +253,14 @@ void abt_io_op_free(abt_io_op_t* op);
*/
size_t abt_io_get_pending_op_count(abt_io_instance_id aid);
/**
* Retrieves complete configuration of abt-io instance, incoded as json
*
* @param [in] aid abt-io instance
* @returns null terminated string that must be free'd by caller
*/
char* abt_io_get_config(abt_io_instance_id aid);
#ifdef __cplusplus
}
#endif
......
......@@ -7,6 +7,6 @@ Name: abt-io
Description: Argobots bindings for common POSIX I/O functions
Version: 0.2
URL: https://xgitlab.cels.anl.gov/sds/abt-io
Requires: argobots
Requires: argobots json-c
Libs: -L${libdir} -labt-io
Cflags: -I${includedir}
#! /usr/bin/env bash
##
## Copyright (C) by Argonne National Laboratory
## See COPYRIGHT in top-level directory
##
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
# If we have a STDIN, use it, otherwise get one
if tty >/dev/null 2>&1; then
TTY=$(tty)
else
TTY=/dev/tty
fi
ask() {
while true; do
if [ "${2:-}" = "Y" ]; then
prompt="Y/n"
default=Y
elif [ "${2:-}" = "N" ]; then
prompt="y/N"
default=N
else
prompt="y/n"
default=
fi
# Ask the question (not using "read -p" as it uses stderr not stdout)
echo -n "$1 [$prompt] "
# Read the answer
read REPLY < "$TTY"