1
1
openmpi/ompi/mca/osc/sm/osc_sm_passive_target.c
Nathan Hjelm 7aece0a7fd osc/sm: fix bugs in both the passive and active target paths
While testing one-sided on LANL systems I found a couple more OSC
bugs that were not caught during the initial testing:

 - In the passive target code we read the read lock count as a
   char instead of the intended uint32_t. This causes lock to
   lockup when using shared locks after 127 iterations.

 - The post code used the wrong group when trying to increment post
   counters. This causes a segmentation fault.

 - Both the post and wait code used the wrong check in the inner
   loop leading to an infinite loop.

cmr=v1.8.1:reviewer=jsquyres

This commit was SVN r31354.
2014-04-08 21:55:00 +00:00

249 строки
5.5 KiB
C

/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "ompi/mca/osc/osc.h"
#include "ompi/mca/osc/base/base.h"
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
#include "osc_sm.h"
static inline uint32_t
lk_fetch_add32(ompi_osc_sm_module_t *module,
int target,
size_t offset,
uint32_t delta)
{
/* opal_atomic_add_32 is an add then fetch so delta needs to be subtracted out to get the
* old value */
return opal_atomic_add_32((int32_t*) ((char*) &module->node_states[target].lock + offset),
delta) - delta;
}
static inline void
lk_add32(ompi_osc_sm_module_t *module,
int target,
size_t offset,
uint32_t delta)
{
opal_atomic_add_32((int32_t*) ((char*) &module->node_states[target].lock + offset),
delta);
}
static inline uint32_t
lk_fetch32(ompi_osc_sm_module_t *module,
int target,
size_t offset)
{
opal_atomic_mb ();
return *((uint32_t *)((char*) &module->node_states[target].lock + offset));
}
static inline int
start_exclusive(ompi_osc_sm_module_t *module,
int target)
{
uint32_t me = lk_fetch_add32(module, target,
offsetof(ompi_osc_sm_lock_t, counter), 1);
while (me != lk_fetch32(module, target,
offsetof(ompi_osc_sm_lock_t, write))) {
opal_progress();
}
return OMPI_SUCCESS;
}
static inline int
end_exclusive(ompi_osc_sm_module_t *module,
int target)
{
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, write), 1);
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, read), 1);
return OMPI_SUCCESS;
}
static inline int
start_shared(ompi_osc_sm_module_t *module,
int target)
{
uint32_t me = lk_fetch_add32(module, target,
offsetof(ompi_osc_sm_lock_t, counter), 1);
while (me != lk_fetch32(module, target,
offsetof(ompi_osc_sm_lock_t, read))) {
opal_progress();
}
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, read), 1);
return OMPI_SUCCESS;
}
static inline int
end_shared(ompi_osc_sm_module_t *module,
int target)
{
lk_add32(module, target, offsetof(ompi_osc_sm_lock_t, write), 1);
return OMPI_SUCCESS;
}
int
ompi_osc_sm_lock(int lock_type,
int target,
int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret;
if (lock_none != module->outstanding_locks[target]) {
return OMPI_ERR_RMA_SYNC;
}
if (0 == (assert & MPI_MODE_NOCHECK)) {
if (MPI_LOCK_EXCLUSIVE == lock_type) {
module->outstanding_locks[target] = lock_exclusive;
ret = start_exclusive(module, target);
} else {
module->outstanding_locks[target] = lock_shared;
ret = start_shared(module, target);
}
} else {
module->outstanding_locks[target] = lock_nocheck;
ret = OMPI_SUCCESS;
}
return ret;
}
int
ompi_osc_sm_unlock(int target,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret;
/* ensure all memory operations have completed */
opal_atomic_mb();
if (module->outstanding_locks[target] == lock_nocheck) {
ret = OMPI_SUCCESS;
} else if (module->outstanding_locks[target] == lock_exclusive) {
ret = end_exclusive(module, target);
module->outstanding_locks[target] = lock_none;
} else if (module->outstanding_locks[target] == lock_shared) {
ret = end_shared(module, target);
module->outstanding_locks[target] = lock_none;
} else {
ret = OMPI_ERR_RMA_SYNC;
}
return ret;
}
int
ompi_osc_sm_lock_all(int assert,
struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret, i, comm_size;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret = ompi_osc_sm_lock(MPI_LOCK_SHARED, i, assert, win);
if (OMPI_SUCCESS != ret) return ret;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_unlock_all(struct ompi_win_t *win)
{
ompi_osc_sm_module_t *module =
(ompi_osc_sm_module_t*) win->w_osc_module;
int ret, i, comm_size;
comm_size = ompi_comm_size(module->comm);
for (i = 0 ; i < comm_size ; ++i) {
ret = ompi_osc_sm_unlock(i, win);
if (OMPI_SUCCESS != ret) return ret;
}
return OMPI_SUCCESS;
}
int
ompi_osc_sm_sync(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush(int target,
struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_all(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_local(int target,
struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}
int
ompi_osc_sm_flush_local_all(struct ompi_win_t *win)
{
opal_atomic_mb();
return OMPI_SUCCESS;
}