/usr/include/mpich/opa_primitives.h is in libmpich-dev 3.2-6build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2008 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#ifndef OPA_PRIMITIVES_H_INCLUDED
#define OPA_PRIMITIVES_H_INCLUDED
#include "opa_config.h"
#include "opa_util.h"
/* Clean up some of the opa_config.h definitions. This is a consequence
of using the AX_PREFIX_CONFIG_H macro. Autoconf won't define inline
or _opa_inline when a real "inline" works. Since we are
unconditionally using _opa_inline we must define it ourselves in this
case. */
#ifndef _opa_inline
#define _opa_inline inline
#endif
#ifndef _opa_restrict
#define _opa_restrict restrict
#endif
#ifndef _opa_const
#define _opa_const const
#endif
/*
Primitive atomic functions
--------------------------
The included file is responsible for defining the types of OPA_int_t and
OPA_ptr_t as well as a set of functions for operating on these
types. If you have the following declaration:
OPA_int_t atomic_var;
Then in order for the emulation functions to compile, the underlying value of
atomic_var should be accessible via:
atomic_var.v;
The same goes for OPA_ptr_t.
The atomic functions that must be ported for each architecture:
static _opa_inline int OPA_load_int(_opa_const OPA_int_t *ptr);
static _opa_inline void OPA_store_int(OPA_int_t *ptr, int val);
static _opa_inline void *OPA_load_ptr(_opa_const OPA_ptr_t *ptr);
static _opa_inline void OPA_store_ptr(OPA_ptr_t *ptr, void *val);
static _opa_inline void OPA_add_int(OPA_int_t *ptr, int val);
static _opa_inline void OPA_incr_int(OPA_int_t *ptr);
static _opa_inline void OPA_decr_int(OPA_int_t *ptr);
static _opa_inline int OPA_decr_and_test_int(OPA_int_t *ptr);
static _opa_inline int OPA_fetch_and_add_int(OPA_int_t *ptr, int val);
static _opa_inline int OPA_fetch_and_incr_int(OPA_int_t *ptr);
static _opa_inline int OPA_fetch_and_decr_int(OPA_int_t *ptr);
static _opa_inline void *OPA_cas_ptr(OPA_ptr_t *ptr, void *oldv, void *newv);
static _opa_inline int OPA_cas_int(OPA_int_t *ptr, int oldv, int newv);
static _opa_inline void *OPA_swap_ptr(OPA_ptr_t *ptr, void *val);
static _opa_inline int OPA_swap_int(OPA_int_t *ptr, int val);
// (the memory barriers may be macros instead of inline functions)
static _opa_inline void OPA_write_barrier();
static _opa_inline void OPA_read_barrier();
static _opa_inline void OPA_read_write_barrier();
// Loads and stores with memory ordering guarantees (also may be macros):
static _opa_inline int OPA_load_acquire_int(_opa_const OPA_int_t *ptr);
static _opa_inline void OPA_store_release_int(OPA_int_t *ptr, int val);
static _opa_inline void *OPA_load_acquire_ptr(_opa_const OPA_ptr_t *ptr);
static _opa_inline void OPA_store_release_ptr(OPA_ptr_t *ptr, void *val);
// Compiler barrier, only preventing compiler reordering, *not* CPU
// reordering (may be a macro):
static _opa_inline void OPA_compiler_barrier();
// The following need to be ported only for architectures supporting LL/SC:
static _opa_inline int OPA_LL_int(OPA_int_t *ptr);
static _opa_inline int OPA_SC_int(OPA_int_t *ptr, int val);
static _opa_inline void *OPA_LL_ptr(OPA_ptr_t *ptr);
static _opa_inline int OPA_SC_ptr(OPA_ptr_t *ptr, void *val);
// Additionally, the following initializer macros must be defined:
#define OPA_INT_T_INITIALIZER(val_) ...
#define OPA_PTR_T_INITIALIZER(val_) ...
// They should be useable as C89 static initializers like so:
struct { int x; OPA_int_t y; OPA_ptr_t z; } foo = { 35, OPA_INT_T_INITIALIZER(1), OPA_PTR_T_INITIALIZER(NULL) };
*/
/* Include the appropriate header for the architecture */
#if defined(OPA_USE_UNSAFE_PRIMITIVES)
/* comes first to permit user overrides in the style of NDEBUG */
#include "primitives/opa_unsafe.h"
#elif defined(OPA_HAVE_GCC_AND_POWERPC_ASM)
#include "primitives/opa_gcc_ppc.h"
#elif defined(OPA_HAVE_GCC_AND_ARM_ASM)
#include "primitives/opa_gcc_arm.h"
#elif defined(OPA_HAVE_GCC_X86_32_64)
#include "primitives/opa_gcc_intel_32_64.h"
#elif defined(OPA_HAVE_GCC_X86_32_64_P3)
#include "primitives/opa_gcc_intel_32_64_p3.h"
#elif defined(OPA_HAVE_GCC_AND_IA64_ASM)
#include "primitives/opa_gcc_ia64.h"
#elif defined(OPA_HAVE_GCC_AND_SICORTEX_ASM)
#include "primitives/opa_gcc_sicortex.h"
#elif defined(OPA_HAVE_GCC_INTRINSIC_ATOMICS)
#include "primitives/opa_gcc_intrinsics.h"
#elif defined(OPA_HAVE_SUN_ATOMIC_OPS)
#include "primitives/opa_sun_atomic_ops.h"
#elif defined(OPA_HAVE_NT_INTRINSICS)
#include "primitives/opa_nt_intrinsics.h"
#elif defined(OPA_USE_LOCK_BASED_PRIMITIVES)
#include "primitives/opa_by_lock.h"
#else
#error no primitives implementation specified
#endif
/*
This routine is needed because the MPIU_THREAD_XXX_CS_{ENTER,EXIT} macros do
not provide synchronization across multiple processes, only across multiple
threads within a process. In order to safely emulate atomic operations on a
shared memory region, we need a shared memory backed lock mechanism.
This routine must be called by any subsystem that intends to use the atomic
abstractions if the cpp directive OPA_USE_LOCK_BASED_PRIMITIVES is defined. It must
be called exactly once by _all_ processes, not just a single leader. This
function will initialize the contents of the lock variable if the caller
specifies (isLeader==true). Note that multiple initialization is forbidden
by several lock implementations, especially pthreads.
Inputs:
shm_lock - A pointer to an allocated piece of shared memory that can hold
a mutex (e.g., pthread_mutex_t). This is not portable to
non-pthreads systems at this time.
isLeader - This boolean value should be set to true for exactly one
thread/process of the group that calls this function.
*/
#if defined(OPA_HAVE_PTHREAD_H)
# include <pthread.h>
typedef pthread_mutex_t OPA_emulation_ipl_t;
int OPA_Interprocess_lock_init(OPA_emulation_ipl_t *shm_lock, int isLeader);
#endif
/* FIXME This should probably be pushed down into the platform-specific headers. */
#if defined(OPA_HAVE_SCHED_YIELD)
# include <sched.h>
# define OPA_busy_wait() sched_yield()
#else
# define OPA_busy_wait() do { } while (0)
#endif
#endif /* defined(OPA_PRIMITIVES_H_INCLUDED) */
|