|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if !defined(MPIU_THREAD_PRIV_H_INCLUDED)
|
|
Packit |
0848f5 |
#define MPIU_THREAD_PRIV_H_INCLUDED
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* The following three macros define a way to portably access thread-private
|
|
Packit |
0848f5 |
storage in MPICH, and avoid extra overhead when MPICH is single
|
|
Packit |
0848f5 |
threaded
|
|
Packit |
0848f5 |
INITKEY - Create the key. Must happen *before* the other threads
|
|
Packit |
0848f5 |
are created
|
|
Packit |
0848f5 |
INIT - Create the thread-private storage. Must happen once per thread
|
|
Packit |
0848f5 |
DECL - Declare local variables
|
|
Packit |
0848f5 |
GET - Access the thread-private storage
|
|
Packit |
0848f5 |
FIELD - Access the thread-private field (by name)
|
|
Packit |
0848f5 |
FINALIZE - to be invoked when all threads no longer need access to the thread
|
|
Packit |
0848f5 |
local storage, such as at MPI_Finalize time
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
The "DECL" is the extern so that there is always a statement for
|
|
Packit |
0848f5 |
the declaration.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if !defined(MPICH_TLS_SPECIFIER)
|
|
Packit |
0848f5 |
/* We need to provide a function that will cleanup the storage attached
|
|
Packit |
0848f5 |
* to the key. */
|
|
Packit |
0848f5 |
void MPIUI_Cleanup_tls(void *a);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* In the case where the thread level is set in MPI_Init_thread, we
|
|
Packit |
0848f5 |
need a blended version of the non-threaded and the thread-multiple
|
|
Packit |
0848f5 |
definitions.
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
The approach is to have TWO MPIUI_Per_thread_t pointers. One is local
|
|
Packit |
0848f5 |
(The MPIU_THREADPRIV_DECL is used in the routines local definitions),
|
|
Packit |
0848f5 |
as in the threaded version of these macros. This is set by using a routine
|
|
Packit |
0848f5 |
to get thread-private storage. The second is a preallocated, extern
|
|
Packit |
0848f5 |
MPIUI_Per_thread_t struct, as in the single threaded case. Based on
|
|
Packit |
0848f5 |
MPIR_Process.isThreaded, one or the other is used.
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
/* For the single threaded case, we use a preallocated structure
|
|
Packit |
0848f5 |
This structure is allocated in src/mpi/init/initthread.c */
|
|
Packit |
0848f5 |
extern MPIUI_Per_thread_t MPIUI_ThreadSingle;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_INITKEY \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
if (MPIR_ThreadInfo.isThreaded) { \
|
|
Packit |
0848f5 |
int initkey_err_; \
|
|
Packit |
0848f5 |
MPIU_Thread_tls_create(MPIUI_Cleanup_tls,&MPIR_ThreadInfo.thread_storage,&initkey_err_); \
|
|
Packit |
0848f5 |
MPIU_Assert(initkey_err_ == 0); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_INIT \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
if (MPIR_ThreadInfo.isThreaded) { \
|
|
Packit |
0848f5 |
int init_err_; \
|
|
Packit |
0848f5 |
MPIUI_Thread_ptr = (MPIUI_Per_thread_t *) MPIU_Calloc(1, sizeof(MPIUI_Per_thread_t)); \
|
|
Packit |
0848f5 |
MPIU_Assert(MPIUI_Thread_ptr); \
|
|
Packit |
0848f5 |
MPIU_Thread_tls_set(&MPIR_ThreadInfo.thread_storage, (void *)MPIUI_Thread_ptr, &init_err_); \
|
|
Packit |
0848f5 |
MPIU_Assert(init_err_ == 0); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_GET \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
if (!MPIUI_Thread_ptr) { \
|
|
Packit |
0848f5 |
if (MPIR_ThreadInfo.isThreaded) { \
|
|
Packit |
0848f5 |
int get_err_; \
|
|
Packit |
0848f5 |
MPIU_Thread_tls_get(&MPIR_ThreadInfo.thread_storage, (void **) &MPIUI_Thread_ptr, &get_err_); \
|
|
Packit |
0848f5 |
MPIU_Assert(get_err_ == 0); \
|
|
Packit |
0848f5 |
if (!MPIUI_Thread_ptr) { \
|
|
Packit |
0848f5 |
MPIU_THREADPRIV_INIT; /* subtle, sets MPIUI_Thread_ptr */ \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
else { \
|
|
Packit |
0848f5 |
MPIUI_Thread_ptr = &MPIUI_ThreadSingle; \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
MPIU_Assert(MPIUI_Thread_ptr); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* common definitions when using MPIU_Thread-based TLS */
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_DECL MPIUI_Per_thread_t *MPIUI_Thread_ptr = NULL
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_FIELD(a_) (MPIUI_Thread_ptr->a_)
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_FINALIZE \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
MPIU_THREADPRIV_DECL; \
|
|
Packit |
0848f5 |
if (MPIR_ThreadInfo.isThreaded) { \
|
|
Packit |
0848f5 |
int tpf_err_; /* unique name to not conflict with vars in called macros */ \
|
|
Packit |
0848f5 |
MPIU_THREADPRIV_GET; \
|
|
Packit |
0848f5 |
MPIU_Free(MPIUI_Thread_ptr); \
|
|
Packit |
0848f5 |
MPIU_Thread_tls_set(&MPIR_ThreadInfo.thread_storage,NULL, &tpf_err_); \
|
|
Packit |
0848f5 |
MPIU_Assert(tpf_err_ == 0); \
|
|
Packit |
0848f5 |
MPIU_Thread_tls_destroy(&MPIR_ThreadInfo.thread_storage,&tpf_err_); \
|
|
Packit |
0848f5 |
MPIU_Assert(tpf_err_ == 0); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#else /* defined(MPICH_TLS_SPECIFIER) */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* We have proper thread-local storage (TLS) support from the compiler, which
|
|
Packit |
0848f5 |
* should yield the best performance and simplest code, so we'll use that. */
|
|
Packit |
0848f5 |
extern MPICH_TLS_SPECIFIER MPIUI_Per_thread_t MPIUI_Thread;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_INITKEY
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_INIT
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_DECL
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_GET
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_FIELD(a_) (MPIUI_Thread.a_)
|
|
Packit |
0848f5 |
#define MPIU_THREADPRIV_FINALIZE do {} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* defined(MPICH_TLS_SPECIFIER) */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* !defined(MPIU_THREAD_PRIV_H_INCLUDED) */
|