|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifndef MPIR_REFCOUNT_POBJ_H_INCLUDED
|
|
Packit Service |
c5cf8c |
#define MPIR_REFCOUNT_POBJ_H_INCLUDED
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* define a type for the completion counter */
|
|
Packit Service |
c5cf8c |
#include "opa_primitives.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef OPA_int_t MPIR_cc_t;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* implies no barrier, since this routine should only be used for request
|
|
Packit Service |
c5cf8c |
* initialization */
|
|
Packit Service |
c5cf8c |
static inline void MPIR_cc_set(MPIR_cc_t * cc_ptr, int val)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (val == 0) {
|
|
Packit Service |
c5cf8c |
/* values other than 0 do not enforce any ordering, and therefore do not
|
|
Packit Service |
c5cf8c |
* start a HB arc */
|
|
Packit Service |
c5cf8c |
/* MT FIXME using cc_set in this way is sloppy. Sometimes the caller
|
|
Packit Service |
c5cf8c |
* really does know that the cc value may cleared, but more likely this
|
|
Packit Service |
c5cf8c |
* is just a hack to avoid the work of figuring out what the cc value
|
|
Packit Service |
c5cf8c |
* currently is and decrementing it instead. */
|
|
Packit Service |
c5cf8c |
/* barrier ensures that any state written before indicating completion is
|
|
Packit Service |
c5cf8c |
* seen by the thread polling on the cc. If OPA adds store-release
|
|
Packit Service |
c5cf8c |
* semantics, we can convert to that instead. */
|
|
Packit Service |
c5cf8c |
OPA_write_barrier();
|
|
Packit Service |
c5cf8c |
MPL_VG_ANNOTATE_HAPPENS_BEFORE(cc_ptr);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#if defined(MPL_VG_AVAILABLE)
|
|
Packit Service |
c5cf8c |
/* MT subtle: store_int is actually safe to use, but Helgrind/DRD/TSan all
|
|
Packit Service |
c5cf8c |
* view the store/load pair as a race. Using an atomic operation for the
|
|
Packit Service |
c5cf8c |
* store side makes all three happy. DRD & TSan also support
|
|
Packit Service |
c5cf8c |
* ANNOTATE_BENIGN_RACE, but Helgrind does not. */
|
|
Packit Service |
c5cf8c |
OPA_swap_int(cc_ptr, val);
|
|
Packit Service |
c5cf8c |
#else
|
|
Packit Service |
c5cf8c |
OPA_store_int(cc_ptr, val);
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ATTRIBUTE((unused))
|
|
Packit Service |
c5cf8c |
static inline int MPIR_cc_is_complete(MPIR_cc_t * cc_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int complete;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
complete = (0 == OPA_load_int(cc_ptr));
|
|
Packit Service |
c5cf8c |
if (complete) {
|
|
Packit Service |
c5cf8c |
MPL_VG_ANNOTATE_HAPPENS_AFTER(cc_ptr);
|
|
Packit Service |
c5cf8c |
OPA_read_barrier();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return complete;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* incomplete_==TRUE iff the cc > 0 after the decr */
|
|
Packit Service |
c5cf8c |
#define MPIR_cc_decr(cc_ptr_, incomplete_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int ctr_; \
|
|
Packit Service |
c5cf8c |
OPA_write_barrier(); \
|
|
Packit Service |
c5cf8c |
MPL_VG_ANNOTATE_HAPPENS_BEFORE(cc_ptr_); \
|
|
Packit Service |
c5cf8c |
ctr_ = OPA_fetch_and_decr_int(cc_ptr_); \
|
|
Packit Service |
c5cf8c |
MPIR_Assert(ctr_ >= 1); \
|
|
Packit Service |
c5cf8c |
*(incomplete_) = (ctr_ != 1); \
|
|
Packit Service |
c5cf8c |
/* TODO check if this HA is actually necessary */ \
|
|
Packit Service |
c5cf8c |
if (!*(incomplete_)) { \
|
|
Packit Service |
c5cf8c |
MPL_VG_ANNOTATE_HAPPENS_AFTER(cc_ptr_); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* MT FIXME does this need a HB/HA annotation? This macro is only used for
|
|
Packit Service |
c5cf8c |
* cancel_send right now. */
|
|
Packit Service |
c5cf8c |
/* was_incomplete_==TRUE iff the cc==0 before the decr */
|
|
Packit Service |
c5cf8c |
#define MPIR_cc_incr(cc_ptr_, was_incomplete_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
*(was_incomplete_) = OPA_fetch_and_incr_int(cc_ptr_); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPIR_cc_get(cc_) OPA_load_int(&(cc_))
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* "publishes" the obj with handle value (handle_) via the handle pointer
|
|
Packit Service |
c5cf8c |
* (hnd_lval_). That is, it is a version of the following statement that fixes
|
|
Packit Service |
c5cf8c |
* memory consistency issues:
|
|
Packit Service |
c5cf8c |
* (hnd_lval_) = (handle_);
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* assumes that the following is always true: typeof(*hnd_lval_ptr_)==int
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
/* This could potentially be generalized beyond MPI-handle objects, but we
|
|
Packit Service |
c5cf8c |
* should only take that step after seeing good evidence of its use. A general
|
|
Packit Service |
c5cf8c |
* macro (that is portable to non-gcc compilers) will need type information to
|
|
Packit Service |
c5cf8c |
* make the appropriate volatile cast. */
|
|
Packit Service |
c5cf8c |
/* Ideally _GLOBAL would use this too, but we don't want to count on OPA
|
|
Packit Service |
c5cf8c |
* availability in _GLOBAL mode. Instead the GLOBAL critical section should be
|
|
Packit Service |
c5cf8c |
* used. */
|
|
Packit Service |
c5cf8c |
#define MPIR_OBJ_PUBLISH_HANDLE(hnd_lval_, handle_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
if (MPIR_ThreadInfo.isThreaded) { \
|
|
Packit Service |
c5cf8c |
/* wmb ensures all read-only object field values are seen before the */ \
|
|
Packit Service |
c5cf8c |
/* handle value is seen at the application level */ \
|
|
Packit Service |
c5cf8c |
OPA_write_barrier(); \
|
|
Packit Service |
c5cf8c |
/* volatile ensures lval is not speculatively read or written */ \
|
|
Packit Service |
c5cf8c |
*(volatile int *)&(hnd_lval_) = (handle_); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
else { \
|
|
Packit Service |
c5cf8c |
(hnd_lval_) = (handle_); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif /* MPIR_REFCOUNT_POBJ_H_INCLUDED */
|