Blame src/util/thread/mpiu_thread_posix.h

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 */