Blame src/include/mpir_refcount_pobj.h

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 */