|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
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 |
/*
|
|
Packit Service |
c5cf8c |
* Threads
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#ifndef MPL_THREAD_POSIX_H_INCLUDED
|
|
Packit Service |
c5cf8c |
#define MPL_THREAD_POSIX_H_INCLUDED
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpl.h" /* for MPL_sched_yield */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include <errno.h>
|
|
Packit Service |
c5cf8c |
#include <pthread.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef pthread_mutex_t MPL_thread_mutex_t;
|
|
Packit Service |
c5cf8c |
typedef pthread_cond_t MPL_thread_cond_t;
|
|
Packit Service |
c5cf8c |
typedef pthread_t MPL_thread_id_t;
|
|
Packit Service |
c5cf8c |
typedef pthread_key_t MPL_thread_tls_t;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#if defined(MPL_NEEDS_PTHREAD_MUTEXATTR_SETTYPE_DECL)
|
|
Packit Service |
c5cf8c |
int pthread_mutexattr_settype(pthread_mutexattr_t * attr, int kind);
|
|
Packit Service |
c5cf8c |
#endif /* MPL_NEEDS_PTHREAD_MUTEXATTR_SETTYPE_DECL */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
typedef void (*MPL_thread_func_t) (void *data);
|
|
Packit Service |
c5cf8c |
void MPL_thread_create(MPL_thread_func_t func, void *data, MPL_thread_id_t * id, int *err);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_exit() \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
pthread_exit(NULL); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_self(id_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
*(id_) = pthread_self(); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_same(id1_, id2_, same_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
*(same_) = pthread_equal(*(id1_), *(id2_)) ? TRUE : FALSE; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_yield MPL_sched_yield
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Mutexes
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* FIXME: mutex creation and destruction should be implemented as routines
|
|
Packit Service |
c5cf8c |
because there is no reason to use macros (these are not on the performance
|
|
Packit Service |
c5cf8c |
critical path). Making these macros requires that any code that might use
|
|
Packit Service |
c5cf8c |
these must load all of the pthread.h (or other thread library) support.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* FIXME: using constant initializer if available */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* FIXME: convert errors to an MPL_THREAD_ERR value */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#if !defined(MPL_PTHREAD_MUTEX_ERRORCHECK_VALUE)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_create(mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_init(mutex_ptr_, NULL); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_init", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#else /* defined(MPL_PTHREAD_MUTEX_ERRORCHECK_VALUE) */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_create(mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
pthread_mutexattr_t attr__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
pthread_mutexattr_init(&attr__); \
|
|
Packit Service |
c5cf8c |
pthread_mutexattr_settype(&attr__, MPL_PTHREAD_MUTEX_ERRORCHECK_VALUE); \
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_init(mutex_ptr_, &attr__); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_init", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif /* defined(MPL_PTHREAD_MUTEX_ERRORCHECK_VALUE) */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_destroy(mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_destroy(mutex_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_destroy", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_lock(mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_lock(mutex_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) { \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_lock", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_trylock(mutex_ptr_, err_ptr_, cs_acq_ptr) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
*(int*)cs_acq_ptr = 1; \
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_trylock(mutex_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__ != 0 && err__ != EBUSY)) { \
|
|
Packit Service |
c5cf8c |
*(int*)cs_acq_ptr = 0; \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_trylock", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
else { \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__ != 0)) \
|
|
Packit Service |
c5cf8c |
*(int*)cs_acq_ptr = 0; \
|
|
Packit Service |
c5cf8c |
err__ = 0; \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_mutex_unlock(mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_mutex_unlock(mutex_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) { \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_mutex_unlock", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
} \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Condition Variables
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_cond_create(cond_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_cond_init((cond_ptr_), NULL); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_cond_init", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_cond_destroy(cond_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_cond_destroy(cond_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_cond_destroy", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_cond_wait(cond_ptr_, mutex_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
/* The latest pthread specification says that cond_wait \
|
|
Packit Service |
c5cf8c |
* routines aren't allowed to return EINTR, but some of the \
|
|
Packit Service |
c5cf8c |
* older implementations still do. */ \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
err__ = pthread_cond_wait((cond_ptr_), mutex_ptr_); \
|
|
Packit Service |
c5cf8c |
} while (err__ == EINTR); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_cond_wait", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_cond_broadcast(cond_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_cond_broadcast(cond_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_cond_broadcast", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_cond_signal(cond_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_cond_signal(cond_ptr_); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_cond_signal", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Thread Local Storage
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_tls_create(exit_func_ptr_, tls_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_key_create((tls_ptr_), (exit_func_ptr_)); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_key_create", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_tls_destroy(tls_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_key_delete(*(tls_ptr_)); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_key_delete", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_tls_set(tls_ptr_, value_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
int err__; \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
err__ = pthread_setspecific(*(tls_ptr_), (value_)); \
|
|
Packit Service |
c5cf8c |
if (unlikely(err__)) \
|
|
Packit Service |
c5cf8c |
MPL_internal_sys_error_printf("pthread_setspecific", err__, \
|
|
Packit Service |
c5cf8c |
" %s:%d\n", __FILE__, __LINE__); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = err__; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define MPL_thread_tls_get(tls_ptr_, value_ptr_, err_ptr_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
*(value_ptr_) = pthread_getspecific(*(tls_ptr_)); \
|
|
Packit Service |
c5cf8c |
\
|
|
Packit Service |
c5cf8c |
*(int *)(err_ptr_) = MPL_THREAD_SUCCESS; \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif /* MPL_THREAD_POSIX_H_INCLUDED */
|