|
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 MPL_THREAD_PRIV_H_INCLUDED
|
|
Packit Service |
c5cf8c |
#define MPL_THREAD_PRIV_H_INCLUDED
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#if MPL_THREAD_PACKAGE_NAME != MPL_THREAD_PACKAGE_NONE && !defined(MPL_TLS)
|
|
Packit Service |
c5cf8c |
/* We need to provide a function that will cleanup the storage attached
|
|
Packit Service |
c5cf8c |
* to the key. */
|
|
Packit Service |
c5cf8c |
void MPLI_cleanup_tls(void *a);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* In the case where the thread level is set in MPI_Init_thread, we
|
|
Packit Service |
c5cf8c |
need a blended version of the non-threaded and the thread-multiple
|
|
Packit Service |
c5cf8c |
definitions.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
The approach is to have TWO MPLI_per_thread_t pointers. One is local
|
|
Packit Service |
c5cf8c |
(The MPL_THREADPRIV_DECL is used in the routines local definitions),
|
|
Packit Service |
c5cf8c |
as in the threaded version of these macros. This is set by using a routine
|
|
Packit Service |
c5cf8c |
to get thread-private storage. The second is a preallocated, extern
|
|
Packit Service |
c5cf8c |
MPLI_per_thread_t struct, as in the single threaded case. Based on
|
|
Packit Service |
c5cf8c |
whether MPL is initialized with thread safety, one or the other is used.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_CREATE(key, var, err_ptr_, class_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
void *thread_ptr; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_create(MPLI_cleanup_tls, &(key) , err_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(*((int *) err_ptr_))) \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
thread_ptr = MPL_calloc(1, sizeof(var), class_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(!thread_ptr)) { \
|
|
Packit Service |
c5cf8c |
*((int *) err_ptr_) = MPL_THREAD_ERROR; \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_set(&(key), thread_ptr, err_ptr_); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_GET_ADDR(is_threaded, key, var, addr, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
if (is_threaded) { \
|
|
Packit Service |
c5cf8c |
void *thread_ptr; \
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_get(&(key), &thread_ptr, err_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(*((int *) err_ptr_))) \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
if (!thread_ptr) { \
|
|
Packit Service |
c5cf8c |
thread_ptr = MPL_calloc(1, sizeof(var), MPL_MEM_OTHER); \
|
|
Packit Service |
c5cf8c |
if (unlikely(!thread_ptr)) { \
|
|
Packit Service |
c5cf8c |
*((int *) err_ptr_) = MPL_THREAD_ERROR; \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_set(&(key), thread_ptr, err_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(*((int *) err_ptr_))) \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
addr = thread_ptr; \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
else { \
|
|
Packit Service |
c5cf8c |
addr = &(var); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_DESTROY(key, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
void *thread_ptr; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_get(&(key), &thread_ptr, err_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(*((int *) err_ptr_))) \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
if (thread_ptr) \
|
|
Packit Service |
c5cf8c |
MPL_free(thread_ptr); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_set(&(key), NULL, err_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(*((int *) err_ptr_))) \
|
|
Packit Service |
c5cf8c |
break; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
MPL_thread_tls_destroy(&(key), err_ptr_); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#else /* MPL_THREAD_PACKAGE_NAME != MPL_THREAD_PACKAGE_NONE || defined(MPL_TLS) */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We have proper thread-local storage (TLS) support from the compiler, which
|
|
Packit Service |
c5cf8c |
* should yield the best performance and simplest code, so we'll use that. */
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_CREATE(...)
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_GET_ADDR(is_threaded, key, var, addr, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
addr = &(var); \
|
|
Packit Service |
c5cf8c |
*((int *) err_ptr_) = MPL_THREAD_SUCCESS; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
#define MPL_THREADPRIV_KEY_DESTROY(...)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif /* MPL_THREAD_PRIV_H_INCLUDED */
|