#ifndef UU_UMTX_H
#define UU_UMTX_H

#ifndef HAVE_SETPSHARED
#define pthread_mutexattr_setpshared(m,n) 0
#endif

#define OUR_PTHREAD_MUTEX_INIT(m)                                                       \
    STMT_START {                                                                         \
        int _eC_;                                                                         \
        pthread_mutexattr_t attr;                                                          \
        if ((_eC_ = pthread_mutexattr_init(&attr)))                                         \
            Perl_croak_nocontext("panic: UMTX_ATTR (%d) [%s:%d]", _eC_, __FILE__, __LINE__); \
        if ((_eC_ = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)))             \
            Perl_croak_nocontext("panic: UMTX_SETP (%d) [%s:%d]", _eC_, __FILE__, __LINE__);   \
        if ((_eC_ = pthread_mutex_init((m), &attr)))                                            \
            Perl_croak_nocontext("panic: UMTX_INIT (%d) [%s:%d]", _eC_, __FILE__, __LINE__);     \
    } STMT_END

/*  We need a sharable mutex. */
#ifdef HAVE_PTHREAD_H
#  if defined(USE_WIN32_ALIEN)
#    define uu_mutex    CRITICAL_SECTION
#    define UMTX_init   InitializeCriticalSection(&SMEM->LOCK)
#    define UMTX_lock   EnterCriticalSection(&SMEM->LOCK)
#    define UMTX_unlock LeaveCriticalSection(&SMEM->LOCK)
#  else
#    define uu_mutex     pthread_mutex_t
#    define UMTX_init    OUR_PTHREAD_MUTEX_INIT(&SMEM->LOCK)
#    define UMTX_lock    pthread_mutex_lock(&SMEM->LOCK)
#    define UMTX_unlock  pthread_mutex_unlock(&SMEM->LOCK)
#  endif
#else
#  if defined(USE_WIN32_ALIEN) || defined(USE_WIN32_NATIVE)
#    define uu_mutex    CRITICAL_SECTION
#    define UMTX_init   InitializeCriticalSection(&SMEM->LOCK)
#    define UMTX_lock   EnterCriticalSection(&SMEM->LOCK)
#    define UMTX_unlock LeaveCriticalSection(&SMEM->LOCK)
#  else
#    error "No mutex available"
#  endif
#endif

/* This is try/catch from XSUB.h, copied here for reference. */
#ifdef NO_XSLOCKSxxx
#  define dXCPT             dJMPENV; int rEtV = 0
#  define XCPT_TRY_START    JMPENV_PUSH(rEtV); if (rEtV == 0)
#  define XCPT_TRY_END      JMPENV_POP;
#  define XCPT_CATCH        if (rEtV != 0)
#  define XCPT_RETHROW      JMPENV_JUMP(rEtV)
#endif

#define UMTX_INIT   UMTX_init
#define UMTX_LOCK   dJMPENV; int rEtV = 0; UMTX_lock; JMPENV_PUSH(rEtV); if (rEtV == 0)
#define UMTX_UNLOCK JMPENV_POP; UMTX_unlock; if (rEtV != 0) { JMPENV_JUMP(rEtV); }

#endif
/* ex:set ts=2 sw=2 itab=spaces: */
