#ifndef SH_PTHREAD_H
#define SH_PTHREAD_H

#ifdef HAVE_PTHREAD

#include <pthread.h>
#define SH_MUTEX(M)				pthread_mutex_t M
#define SH_MUTEX_INIT(M,I)			pthread_mutex_t M = I
#define SH_MUTEX_STATIC(M,I)			static pthread_mutex_t M = I
#define SH_MUTEX_EXTERN(M)			extern pthread_mutex_t M

#define SH_MUTEX_LOCK(M)						   \
	do {                                                               \
                int oldtype;                                               \
		pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);  \
                pthread_cleanup_push(pthread_mutex_unlock, (void *) &(M)); \
                pthread_mutex_lock(&(M))


#define SH_MUTEX_UNLOCK(M,C)						   \
		pthread_cleanup_pop(1);                                    \
                pthread_setcanceltype(oldtype, NULL);                      \
	} while (0)

#define SH_MUTEX_LOCK_UNSAFE(M) pthread_mutex_lock(&(M))
#define SH_MUTEX_UNLOCK_UNSAFE(M) pthread_mutex_unlock(&(M))

/* 
 * ----   Global mutexes   ----
 */
SH_MUTEX_EXTERN(mutex_skey);
SH_MUTEX_EXTERN(mutex_resolv);
SH_MUTEX_EXTERN(mutex_pwent);

/*
 * ----   Initialize thread-specific conversion area   ----
 */
extern int sh_g_thread();

#else

#define SH_MUTEX(M)				void *SH_MUTEX_DUMMY_ ## M
#define SH_MUTEX_INIT(M,I)			extern void *SH_MUTEX_DUMMY_ ## M
#define SH_MUTEX_STATIC(M,I)			extern void *SH_MUTEX_DUMMY_ ## M
#define SH_MUTEX_EXTERN(M)			extern void *SH_MUTEX_DUMMY_ ## M
#define SH_MUTEX_LOCK(M)			((void)0)
#define SH_MUTEX_UNLOCK(M)			((void)0)
#define SH_MUTEX_LOCK_UNSAFE(M)			((void)0)
#define SH_MUTEX_UNLOCK_UNSAFE(M)		((void)0)

/* #ifdef HAVE_PTHREAD */
#endif

/* #ifndef SH_PTHREAD_H */
#endif
