Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Copyright (c) 2010 Oak Ridge National Labs. All rights reserved.
Copyright (c) 2011 University of Houston. All rights reserved.
Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
Copyright (c) 2015 NVIDIA Corporation. All rights reserved.
Copyright (c) 2017 Los Alamos National Security, LLC. All rights
Copyright (c) 2017-2018 Los Alamos National Security, LLC. All rights
reserved.
Copyright (c) 2017 Research Organization for Information Science
and Technology (RIST). All rights reserved.
Expand Down Expand Up @@ -143,10 +143,7 @@ General notes
Platform Notes
--------------

- ARM and POWER users may experience intermittent hangs when Open MPI
is compiled with low optimization settings, due to an issue with our
atomic list implementation. We recommend compiling with -O3
optimization, both for performance reasons and to avoid this hang.
- N/A


Compiler Notes
Expand Down
40 changes: 26 additions & 14 deletions opal/class/opal_fifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* All rights reserved.
* Copyright (c) 2007 Voltaire All rights reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* Copyright (c) 2014-2016 Los Alamos National Security, LLC. All rights
* Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
* reseved.
* $COPYRIGHT$
*
Expand Down Expand Up @@ -186,9 +186,10 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
opal_list_item_t *item)
{
const opal_list_item_t * const ghost = &fifo->opal_fifo_ghost;
opal_list_item_t *tail_item;

item->opal_list_next = &fifo->opal_fifo_ghost;
item->opal_list_next = (opal_list_item_t *) ghost;

opal_atomic_wmb ();

Expand All @@ -197,7 +198,7 @@ static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,

opal_atomic_wmb ();

if (&fifo->opal_fifo_ghost == tail_item) {
if (ghost == tail_item) {
/* update the head */
fifo->opal_fifo_head.data.item = item;
} else {
Expand All @@ -215,14 +216,24 @@ static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
*/
static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
{
opal_list_item_t *item, *next;
const opal_list_item_t * const ghost = &fifo->opal_fifo_ghost;

#if OPAL_HAVE_ATOMIC_LLSC_PTR
register opal_list_item_t *item, *next;
int attempt = 0, ret = 0;

/* use load-linked store-conditional to avoid ABA issues */
do {
item = opal_atomic_ll_ptr (&fifo->opal_fifo_head.data.item);
if (&fifo->opal_fifo_ghost == item) {
if (&fifo->opal_fifo_ghost == fifo->opal_fifo_tail.data.item) {
if (++attempt == 5) {
/* deliberatly suspend this thread to allow other threads to run. this should
* only occur during periods of contention on the lifo. */
_opal_lifo_release_cpu ();
attempt = 0;
}

opal_atomic_ll_ptr(&fifo->opal_fifo_head.data.item, item);
if (ghost == item) {
if (ghost == fifo->opal_fifo_tail.data.item) {
return NULL;
}

Expand All @@ -232,11 +243,12 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
}

next = (opal_list_item_t *) item->opal_list_next;
if (opal_atomic_sc_ptr (&fifo->opal_fifo_head.data.item, next)) {
break;
}
} while (1);
opal_atomic_sc_ptr(&fifo->opal_fifo_head.data.item, next, ret);
} while (!ret);

#else
opal_list_item_t *item, *next;

/* protect against ABA issues by "locking" the head */
do {
if (opal_atomic_cmpset_32 ((int32_t *) &fifo->opal_fifo_head.data.counter, 0, 1)) {
Expand All @@ -258,9 +270,9 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
fifo->opal_fifo_head.data.item = next;
#endif

if (&fifo->opal_fifo_ghost == next) {
if (!opal_atomic_cmpset_ptr (&fifo->opal_fifo_tail.data.item, item, &fifo->opal_fifo_ghost)) {
while (&fifo->opal_fifo_ghost == item->opal_list_next) {
if (ghost == next) {
if (!opal_atomic_cmpset_ptr (&fifo->opal_fifo_tail.data.item, item, (void *) ghost)) {
while (ghost == item->opal_list_next) {
opal_atomic_rmb ();
}

Expand Down
11 changes: 6 additions & 5 deletions opal/class/opal_lifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* All rights reserved.
* Copyright (c) 2007 Voltaire All rights reserved.
* Copyright (c) 2010 IBM Corporation. All rights reserved.
* Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
* Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
* reseved.
* Copyright (c) 2016 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
Expand Down Expand Up @@ -204,8 +204,8 @@ static inline void _opal_lifo_release_cpu (void)
*/
static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
{
opal_list_item_t *item, *next;
int attempt = 0;
register opal_list_item_t *item, *next;
int attempt = 0, ret;

do {
if (++attempt == 5) {
Expand All @@ -215,13 +215,14 @@ static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
attempt = 0;
}

item = (opal_list_item_t *) opal_atomic_ll_ptr (&lifo->opal_lifo_head.data.item);
opal_atomic_ll_ptr(&lifo->opal_lifo_head.data.item, item);
if (&lifo->opal_lifo_ghost == item) {
return NULL;
}

next = (opal_list_item_t *) item->opal_list_next;
} while (!opal_atomic_sc_ptr (&lifo->opal_lifo_head.data.item, next));
opal_atomic_sc_ptr(&lifo->opal_lifo_head.data.item, next, ret);
} while (!ret);

opal_atomic_wmb ();

Expand Down
94 changes: 50 additions & 44 deletions opal/include/opal/sys/arm64/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,28 +150,31 @@ static inline int opal_atomic_cmpset_rel_32(volatile int32_t *addr,
return (ret == oldval);
}

static inline int32_t opal_atomic_ll_32 (volatile int32_t *addr)
{
int32_t ret;

__asm__ __volatile__ ("ldaxr %w0, [%1] \n"
: "=&r" (ret)
: "r" (addr));

return ret;
}

static inline int opal_atomic_sc_32 (volatile int32_t *addr, int32_t newval)
{
int ret;

__asm__ __volatile__ ("stlxr %w0, %w2, [%1] \n"
: "=&r" (ret)
: "r" (addr), "r" (newval)
: "cc", "memory");

return ret == 0;
}
#define opal_atomic_ll_32(addr, ret) \
do { \
volatile int32_t *_addr = (addr); \
int32_t _ret; \
\
__asm__ __volatile__ ("ldaxr %w0, [%1] \n" \
: "=&r" (_ret) \
: "r" (_addr)); \
\
ret = (typeof(ret)) _ret; \
} while (0)

#define opal_atomic_sc_32(addr, newval, ret) \
do { \
volatile int32_t *_addr = (addr); \
int32_t _newval = (int32_t) newval; \
int _ret; \
\
__asm__ __volatile__ ("stlxr %w0, %w2, [%1] \n" \
: "=&r" (_ret) \
: "r" (_addr), "r" (_newval) \
: "cc", "memory"); \
\
ret = (_ret == 0); \
} while (0)

static inline int opal_atomic_cmpset_64(volatile int64_t *addr,
int64_t oldval, int64_t newval)
Expand Down Expand Up @@ -251,28 +254,31 @@ static inline int opal_atomic_cmpset_rel_64(volatile int64_t *addr,
return (ret == oldval);
}

static inline int64_t opal_atomic_ll_64 (volatile int64_t *addr)
{
int64_t ret;

__asm__ __volatile__ ("ldaxr %0, [%1] \n"
: "=&r" (ret)
: "r" (addr));

return ret;
}

static inline int opal_atomic_sc_64 (volatile int64_t *addr, int64_t newval)
{
int ret;

__asm__ __volatile__ ("stlxr %w0, %2, [%1] \n"
: "=&r" (ret)
: "r" (addr), "r" (newval)
: "cc", "memory");

return ret == 0;
}
#define opal_atomic_ll_64(addr, ret) \
do { \
volatile int64_t *_addr = (addr); \
int64_t _ret; \
\
__asm__ __volatile__ ("ldaxr %0, [%1] \n" \
: "=&r" (_ret) \
: "r" (_addr)); \
\
ret = (typeof(ret)) _ret; \
} while (0)

#define opal_atomic_sc_64(addr, newval, ret) \
do { \
volatile int64_t *_addr = (addr); \
int64_t _newval = (int64_t) newval; \
int _ret; \
\
__asm__ __volatile__ ("stlxr %w0, %2, [%1] \n" \
: "=&r" (_ret) \
: "r" (_addr), "r" (_newval) \
: "cc", "memory"); \
\
ret = (_ret == 0); \
} while (0)

#define OPAL_ASM_MAKE_ATOMIC(type, bits, name, inst, reg) \
static inline type opal_atomic_ ## name ## _ ## bits (volatile type *addr, type value) \
Expand Down
8 changes: 4 additions & 4 deletions opal/include/opal/sys/atomic_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,15 @@ static inline int opal_atomic_cmpset_rel_ptr(volatile void* addr,

#if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_LLSC_32

#define opal_atomic_ll_ptr(addr) (void *) opal_atomic_ll_32((int32_t *) addr)
#define opal_atomic_sc_ptr(addr, newval) opal_atomic_sc_32((int32_t *) addr, (int32_t) newval)
#define opal_atomic_ll_ptr(addr, ret) opal_atomic_ll_32((volatile int32_t *) (addr), ret)
#define opal_atomic_sc_ptr(addr, value, ret) opal_atomic_sc_32((volatile int32_t *) (addr), (intptr_t) (value), ret)

#define OPAL_HAVE_ATOMIC_LLSC_PTR 1

#elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_LLSC_64

#define opal_atomic_ll_ptr(addr) (void *) opal_atomic_ll_64((int64_t *) addr)
#define opal_atomic_sc_ptr(addr, newval) opal_atomic_sc_64((int64_t *) addr, (int64_t) newval)
#define opal_atomic_ll_ptr(addr, ret) opal_atomic_ll_64((volatile int64_t *) (addr), ret)
#define opal_atomic_sc_ptr(addr, value, ret) opal_atomic_sc_64((volatile int64_t *) (addr), (intptr_t) (value), ret)

#define OPAL_HAVE_ATOMIC_LLSC_PTR 1

Expand Down
Loading