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