|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Threads
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#ifndef MPIU_THREAD_POSIX_H_INCLUDED
|
|
Packit |
0848f5 |
#define MPIU_THREAD_POSIX_H_INCLUDED
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include "mpiu_process_wrappers.h" /* for MPIU_PW_Sched_yield */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include <errno.h>
|
|
Packit |
0848f5 |
#include <pthread.h>
|
|
Packit |
0848f5 |
#include "opa_primitives.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
typedef struct {
|
|
Packit |
0848f5 |
pthread_mutex_t mutex;
|
|
Packit |
0848f5 |
OPA_int_t num_queued_threads;
|
|
Packit |
0848f5 |
} MPIU_Thread_mutex_t;
|
|
Packit |
0848f5 |
typedef pthread_cond_t MPIU_Thread_cond_t;
|
|
Packit |
0848f5 |
typedef pthread_t MPIU_Thread_id_t;
|
|
Packit |
0848f5 |
typedef pthread_key_t MPIU_Thread_tls_t;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if defined(NEEDS_PTHREAD_MUTEXATTR_SETTYPE_DECL)
|
|
Packit |
0848f5 |
int pthread_mutexattr_settype(pthread_mutexattr_t * attr, int kind);
|
|
Packit |
0848f5 |
#endif /* NEEDS_PTHREAD_MUTEXATTR_SETTYPE_DECL */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
typedef void (*MPIU_Thread_func_t) (void *data);
|
|
Packit |
0848f5 |
void MPIU_Thread_create(MPIU_Thread_func_t func, void *data, MPIU_Thread_id_t * id, int *err);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_exit() \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
pthread_exit(NULL); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_self(id_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
*(id_) = pthread_self(); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_same(id1_, id2_, same_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
*(same_) = pthread_equal(*(id1_), *(id2_)) ? TRUE : FALSE; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_yield(mutex_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG(THREAD,VERBOSE,"enter MPIU_Thread_yield"); \
|
|
Packit |
0848f5 |
if (OPA_load_int(&(mutex_ptr_)->num_queued_threads) == 0) \
|
|
Packit |
0848f5 |
break; \
|
|
Packit |
0848f5 |
MPIU_Thread_mutex_unlock(mutex_ptr_, &err;; \
|
|
Packit |
0848f5 |
MPIU_PW_Sched_yield(); \
|
|
Packit |
0848f5 |
MPIU_Thread_mutex_lock(mutex_ptr_, &err;; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG(THREAD,VERBOSE,"exit MPIU_Thread_yield"); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Mutexes
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* FIXME: mutex creation and destruction should be implemented as routines
|
|
Packit |
0848f5 |
because there is no reason to use macros (these are not on the performance
|
|
Packit |
0848f5 |
critical path). Making these macros requires that any code that might use
|
|
Packit |
0848f5 |
these must load all of the pthread.h (or other thread library) support.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* FIXME: using constant initializer if available */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* FIXME: convert errors to an MPIU_THREAD_ERR value */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if !defined(MPICH_PTHREAD_MUTEX_ERRORCHECK_VALUE)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_mutex_create(mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
OPA_store_int(&(mutex_ptr_)->num_queued_threads, 0); \
|
|
Packit |
0848f5 |
err__ = pthread_mutex_init(&(mutex_ptr_)->mutex, NULL); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_mutex_init", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"Created MPIU_Thread_mutex %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#else /* defined(MPICH_PTHREAD_MUTEX_ERRORCHECK_VALUE) */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_mutex_create(mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
pthread_mutexattr_t attr__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
OPA_store_int(&(mutex_ptr_)->num_queued_threads, 0); \
|
|
Packit |
0848f5 |
pthread_mutexattr_init(&attr__); \
|
|
Packit |
0848f5 |
pthread_mutexattr_settype(&attr__, MPICH_PTHREAD_MUTEX_ERRORCHECK_VALUE); \
|
|
Packit |
0848f5 |
err__ = pthread_mutex_init(&(mutex_ptr_)->mutex, &attr__); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_mutex_init", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"Created MPIU_Thread_mutex %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* defined(MPICH_PTHREAD_MUTEX_ERRORCHECK_VALUE) */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_mutex_destroy(mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"About to destroy MPIU_Thread_mutex %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
err__ = pthread_mutex_destroy(&(mutex_ptr_)->mutex); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_mutex_destroy", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_mutex_lock(mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,VERBOSE,"enter MPIU_Thread_mutex_lock %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
OPA_incr_int(&(mutex_ptr_)->num_queued_threads); \
|
|
Packit |
0848f5 |
err__ = pthread_mutex_lock(&(mutex_ptr_)->mutex); \
|
|
Packit |
0848f5 |
OPA_decr_int(&(mutex_ptr_)->num_queued_threads); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) { \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_S(THREAD,TERSE," mutex lock error: %s", MPIU_Strerror(err__)); \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_mutex_lock", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,VERBOSE,"exit MPIU_Thread_mutex_lock %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_mutex_unlock(mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,VERBOSE,"MPIU_Thread_mutex_unlock %p", (mutex_ptr_)); \
|
|
Packit |
0848f5 |
err__ = pthread_mutex_unlock(&(mutex_ptr_)->mutex); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) { \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_S(THREAD,TERSE," mutex unlock error: %s", MPIU_Strerror(err__)); \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_mutex_unlock", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
} \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Condition Variables
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_cond_create(cond_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
err__ = pthread_cond_init((cond_ptr_), NULL); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_cond_init", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"Created MPIU_Thread_cond %p", (cond_ptr_)); \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_cond_destroy(cond_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"About to destroy MPIU_Thread_cond %p", (cond_ptr_)); \
|
|
Packit |
0848f5 |
err__ = pthread_cond_destroy(cond_ptr_); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_cond_destroy", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_cond_wait(cond_ptr_, mutex_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
/* The latest pthread specification says that cond_wait \
|
|
Packit |
0848f5 |
* routines aren't allowed to return EINTR, but some of the \
|
|
Packit |
0848f5 |
* older implementations still do. */ \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_FMT(THREAD,TYPICAL,(MPIU_DBG_FDEST,"Enter cond_wait on cond=%p mutex=%p",(cond_ptr_),(mutex_ptr_))) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
OPA_incr_int(&(mutex_ptr_)->num_queued_threads); \
|
|
Packit |
0848f5 |
err__ = pthread_cond_wait((cond_ptr_), &(mutex_ptr_)->mutex); \
|
|
Packit |
0848f5 |
OPA_decr_int(&(mutex_ptr_)->num_queued_threads); \
|
|
Packit |
0848f5 |
} while (err__ == EINTR); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_cond_wait", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_Assert_fmt_msg(err__ == 0, \
|
|
Packit |
0848f5 |
("cond_wait failed, err=%d (%s)",err__,strerror(err__))); \
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_FMT(THREAD,TYPICAL,(MPIU_DBG_FDEST,"Exit cond_wait on cond=%p mutex=%p",(cond_ptr_),(mutex_ptr_))); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_cond_broadcast(cond_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"About to cond_broadcast on MPIU_Thread_cond %p", (cond_ptr_)); \
|
|
Packit |
0848f5 |
err__ = pthread_cond_broadcast(cond_ptr_); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_cond_broadcast", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_Assert_fmt_msg(err__ == 0, \
|
|
Packit |
0848f5 |
("cond_broadcast failed, err__=%d (%s)",err__,strerror(err__))); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_cond_signal(cond_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_P(THREAD,TYPICAL,"About to cond_signal on MPIU_Thread_cond %p", (cond_ptr_)); \
|
|
Packit |
0848f5 |
err__ = pthread_cond_signal(cond_ptr_); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_cond_signal", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_Assert_fmt_msg(err__ == 0, \
|
|
Packit |
0848f5 |
("cond_signal failed, err__=%d (%s)",err__,strerror(err__))); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Thread Local Storage
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_tls_create(exit_func_ptr_, tls_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
err__ = pthread_key_create((tls_ptr_), (exit_func_ptr_)); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_key_create", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_tls_destroy(tls_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
err__ = pthread_key_delete(*(tls_ptr_)); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_key_delete", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_tls_set(tls_ptr_, value_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
int err__; \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
err__ = pthread_setspecific(*(tls_ptr_), (value_)); \
|
|
Packit |
0848f5 |
if (unlikely(err__)) \
|
|
Packit |
0848f5 |
MPL_internal_sys_error_printf("pthread_setspecific", err__, \
|
|
Packit |
0848f5 |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = err__; \
|
|
Packit |
0848f5 |
MPIU_Assert_fmt_msg(err__ == 0, \
|
|
Packit |
0848f5 |
("tls_set failed, err__=%d (%s)",err__,strerror(err__))); \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MPIU_Thread_tls_get(tls_ptr_, value_ptr_, err_ptr_) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
*(value_ptr_) = pthread_getspecific(*(tls_ptr_)); \
|
|
Packit |
0848f5 |
\
|
|
Packit |
0848f5 |
*(int *)(err_ptr_) = MPIU_THREAD_SUCCESS; \
|
|
Packit |
0848f5 |
} while (0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* MPIU_THREAD_POSIX_H_INCLUDED */
|