206 lines
5.8 KiB
C
206 lines
5.8 KiB
C
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
/*
|
|
* (C) 2008 by Argonne National Laboratory.
|
|
* See COPYRIGHT in top-level directory.
|
|
*/
|
|
|
|
#ifndef OPA_BY_LOCK_H_INCLUDED
|
|
#define OPA_BY_LOCK_H_INCLUDED
|
|
|
|
/* FIXME For now we rely on pthreads for our IPC locks. This is fairly
|
|
portable, although it is obviously not 100% portable. Some day when we
|
|
refactor the OPA_Process_locks code we should be able to use that again. */
|
|
#if defined(OPA_HAVE_PTHREAD_H)
|
|
#include <pthread.h>
|
|
|
|
/* defined in opa_primitives.c */
|
|
extern pthread_mutex_t *OPA_emulation_lock;
|
|
|
|
/* FIXME these make less sense now that OPA is not inside of MPICH. Is there a
|
|
simpler name/scheme that could be used here instead? [goodell@ 2009-02-19] */
|
|
#define OPA_IPC_SINGLE_CS_ENTER(msg) \
|
|
do { \
|
|
OPA_assert(OPA_emulation_lock); \
|
|
pthread_mutex_lock(OPA_emulation_lock); \
|
|
} while (0)
|
|
|
|
#define OPA_IPC_SINGLE_CS_EXIT(msg) \
|
|
do { \
|
|
OPA_assert(OPA_emulation_lock); \
|
|
pthread_mutex_unlock(OPA_emulation_lock); \
|
|
} while (0)
|
|
|
|
typedef struct { volatile int v; } OPA_int_t;
|
|
typedef struct { int * volatile v; } OPA_ptr_t;
|
|
|
|
#define OPA_INT_T_INITIALIZER(val_) { (val_) }
|
|
#define OPA_PTR_T_INITIALIZER(val_) { (val_) }
|
|
|
|
/*
|
|
Emulated atomic primitives
|
|
--------------------------
|
|
|
|
These are versions of the atomic primitives that emulate the proper behavior
|
|
via the use of an inter-process lock. For more information on their
|
|
individual behavior, please see the comment on the corresponding top level
|
|
function.
|
|
|
|
In general, these emulated primitives should _not_ be used. Most algorithms
|
|
can be more efficiently implemented by putting most or all of the algorithm
|
|
inside of a single critical section. These emulated primitives exist to
|
|
ensure that there is always a fallback if no machine-dependent version of a
|
|
particular operation has been defined. They also serve as a very readable
|
|
reference for the exact semantics of our OPA_* ops.
|
|
*/
|
|
|
|
static _opa_inline int OPA_load_int(_opa_const OPA_int_t *ptr)
|
|
{
|
|
int retval;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_add");
|
|
retval = ptr->v;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_add");
|
|
return retval;
|
|
}
|
|
|
|
static _opa_inline void OPA_store_int(OPA_int_t *ptr, int val)
|
|
{
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_add");
|
|
ptr->v = val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_add");
|
|
}
|
|
|
|
static _opa_inline void *OPA_load_ptr(_opa_const OPA_ptr_t *ptr)
|
|
{
|
|
int *retval;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_add");
|
|
retval = ptr->v;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_add");
|
|
return retval;
|
|
}
|
|
|
|
static _opa_inline void OPA_store_ptr(OPA_ptr_t *ptr, void *val)
|
|
{
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_add");
|
|
ptr->v = val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_add");
|
|
}
|
|
|
|
/* normal loads/stores are fully ordered, so just use them */
|
|
#define OPA_load_acquire_int(ptr_) OPA_load_int((ptr_))
|
|
#define OPA_store_release_int(ptr_,val_) OPA_store_int((ptr_),(val_))
|
|
#define OPA_load_acquire_ptr(ptr_) OPA_load_ptr((ptr_))
|
|
#define OPA_store_release_ptr(ptr_,val_) OPA_store_ptr((ptr_),(val_))
|
|
|
|
static _opa_inline void OPA_add_int(OPA_int_t *ptr, int val)
|
|
{
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_add");
|
|
ptr->v += val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_add");
|
|
}
|
|
|
|
static _opa_inline void *OPA_cas_ptr(OPA_ptr_t *ptr, int *oldv, int *newv)
|
|
{
|
|
int *prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_cas");
|
|
prev = ptr->v;
|
|
if (prev == oldv) {
|
|
ptr->v = newv;
|
|
}
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_cas");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline int OPA_cas_int(OPA_int_t *ptr, int oldv, int newv)
|
|
{
|
|
int prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_cas");
|
|
prev = ptr->v;
|
|
if (prev == oldv) {
|
|
ptr->v = newv;
|
|
}
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_cas");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline int OPA_decr_and_test_int(OPA_int_t *ptr)
|
|
{
|
|
int new_val;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_decr_and_test");
|
|
new_val = --(ptr->v);
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_decr_and_test");
|
|
return (0 == new_val);
|
|
}
|
|
|
|
static _opa_inline void OPA_decr_int(OPA_int_t *ptr)
|
|
{
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_decr");
|
|
--(ptr->v);
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_decr");
|
|
}
|
|
|
|
static _opa_inline int OPA_fetch_and_add_int(OPA_int_t *ptr, int val)
|
|
{
|
|
int prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_fetch_and_add");
|
|
prev = ptr->v;
|
|
ptr->v += val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_fetch_and_add");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline int OPA_fetch_and_decr_int(OPA_int_t *ptr)
|
|
{
|
|
int prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_fetch_and_decr");
|
|
prev = ptr->v;
|
|
--(ptr->v);
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_fetch_and_decr");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline int OPA_fetch_and_incr_int(OPA_int_t *ptr)
|
|
{
|
|
int prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_fetch_and_incr");
|
|
prev = ptr->v;
|
|
++(ptr->v);
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_fetch_and_incr");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline void OPA_incr_int(OPA_int_t *ptr)
|
|
{
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_incr");
|
|
++(ptr->v);
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_incr");
|
|
}
|
|
|
|
static _opa_inline void *OPA_swap_ptr(OPA_ptr_t *ptr, void *val)
|
|
{
|
|
int *prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_swap_ptr");
|
|
prev = ptr->v;
|
|
ptr->v = val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_swap_ptr");
|
|
return prev;
|
|
}
|
|
|
|
static _opa_inline int OPA_swap_int(OPA_int_t *ptr, int val)
|
|
{
|
|
int prev;
|
|
OPA_IPC_SINGLE_CS_ENTER("atomic_swap_int");
|
|
prev = ptr->v;
|
|
ptr->v = val;
|
|
OPA_IPC_SINGLE_CS_EXIT("atomic_swap_int");
|
|
return (int)prev;
|
|
}
|
|
|
|
/* lock/unlock provides barrier */
|
|
#define OPA_write_barrier() do {} while (0)
|
|
#define OPA_read_barrier() do {} while (0)
|
|
#define OPA_read_write_barrier() do {} while (0)
|
|
|
|
|
|
#endif /* defined(OPA_HAVE_PTHREAD_H) */
|
|
#endif /* !defined(OPA_BY_LOCK_H_INCLUDED) */
|