Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Thread synchronization routines. Mutexes & Spinlocks.
0003  *
0004  * @file thlock.h
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #ifndef THLOCK_H
0035 #define THLOCK_H
0036 
0037 #ifdef  __cplusplus
0038 extern "C" {
0039 #endif
0040 
0041 /*---------------------------Includes-----------------------------------*/
0042 #include <pthread.h>
0043 #include <userlog.h>
0044 
0045 #include "ndrstandard.h"
0046 /*---------------------------Externs------------------------------------*/
0047 /*---------------------------Macros-------------------------------------*/
0048 
0049 
0050 /* *** PTHREAD MUTEX *** */
0051     
0052 #define MUTEX_VAR(X)        pthread_mutex_t X
0053     
0054 /**
0055  * Standard type mutex
0056  */
0057 #define MUTEX_VAR_INIT(X)   do {\
0058                     if ( EXSUCCEED!=pthread_mutex_init ( &(X), NULL ) ) \
0059                     {\
0060                         userlog("Mutex init fail: %s", #X);\
0061                         exit ( 1 );\
0062                     }\
0063                 } while (0)
0064     
0065 /* support for debugging if any */
0066 #if NDRX_MUTEX_DEBUG
0067 #define NDRX_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
0068 #else
0069 #define NDRX_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE
0070 #endif
0071 
0072 /**
0073  * Recursive mutex
0074  */
0075 #define MUTEX_VAR_INIT_RECURS(X)   do {\
0076                     pthread_mutexattr_t attr;\
0077                     pthread_mutexattr_init(&attr);\
0078                     pthread_mutexattr_settype(&attr, NDRX_PTHREAD_MUTEX_RECURSIVE);\
0079                     if ( EXSUCCEED!=pthread_mutex_init ( &(X), &attr ) ) \
0080                     {\
0081                         userlog("Mutex init fail: %s", #X);\
0082                         exit ( 1 );\
0083                     }\
0084                 } while (0)
0085 /*
0086  Have custom error checks...
0087  */
0088 #if NDRX_MUTEX_DEBUG
0089 
0090 /**
0091  * Declare mutex with debug mode on
0092  * @param X mutex var name
0093  */
0094 #define MUTEX_LOCKDECL(X) pthread_mutex_t X = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
0095 
0096 /**
0097  * Mutex init with out init
0098  */
0099 #define MUTEX_LOCKDECLN(X) pthread_mutex_t X
0100     
0101 /**
0102  * Lock the mutex
0103  * @param X mutex var name
0104  */
0105 #define MUTEX_LOCK_V(X) do {int ndrx_mut_ret; if (0!=(ndrx_mut_ret=pthread_mutex_lock(&X)))\
0106      {userlog("Mutex lock failed: %d/%s at %s:%u %s() - aborting", \
0107         ndrx_mut_ret, strerror(ndrx_mut_ret), __FILE__, __LINE__, __func__); abort();} } while (0)
0108 
0109 /**
0110  * Unlock the mutex
0111  * @param X mutex var name
0112  */
0113 #define MUTEX_UNLOCK_V(X) do {int ndrx_mut_ret; if (0!=(ndrx_mut_ret=pthread_mutex_unlock(&X)))\
0114      {userlog("Mutex unlock failed: %d/%s at %s:%u %s() - aborting", \
0115         ndrx_mut_ret, strerror(ndrx_mut_ret), __FILE__, __LINE__, __func__); abort();} } while (0)
0116 
0117 #else 
0118 
0119 /**
0120  * Declare static initalized mutex
0121  * @param X mutex variable name
0122  */
0123 #define MUTEX_LOCKDECL(X) pthread_mutex_t X = PTHREAD_MUTEX_INITIALIZER
0124     
0125     
0126 /**
0127  * Mutex init with out init
0128  */
0129 #define MUTEX_LOCKDECLN(X) pthread_mutex_t X
0130     
0131 /**
0132  * Lock the mutex
0133  * @param X mutex var name
0134  */
0135 #define MUTEX_LOCK_V(X) pthread_mutex_lock(&X)
0136     
0137 /**
0138  * Unlock the mutex
0139  * @param X mutex var name
0140  */
0141 #define MUTEX_UNLOCK_V(X) pthread_mutex_unlock(&X)
0142 
0143 #endif
0144 
0145     
0146 #define MUTEX_TRYLOCK_V(X) pthread_mutex_trylock(&X)
0147     
0148 /**
0149  * Destroy mutex var
0150  */
0151 #define MUTEX_DESTROY_V(X) pthread_mutex_destroy(&X)
0152 
0153 /**
0154  * Define static mutex and do lock / for scope
0155  */
0156 #define MUTEX_LOCK \
0157         static MUTEX_LOCKDECL(__mutexlock);\
0158         MUTEX_LOCK_V(__mutexlock);
0159 
0160 /**
0161  * Unlock the static mutex / for scope
0162  */
0163 #define MUTEX_UNLOCK MUTEX_UNLOCK_V(__mutexlock);
0164 
0165 /* *** NDRX LOCKS *** */
0166     
0167 /**
0168  * Spinlock init
0169  */
0170 #define NDRX_SPIN_INIT_V(X)   \
0171                 do {\
0172                     if ( EXSUCCEED!=pthread_spin_init ( &(X), PTHREAD_PROCESS_PRIVATE ) ) \
0173                     {\
0174                         userlog("Spinlock init fail: %s", #X);\
0175                         exit ( 1 );\
0176                     }\
0177                 }while(0)
0178 /**
0179  * Spinlock declare variable
0180  * @param X name of declare. If needs static, just add before
0181  */
0182 #define NDRX_SPIN_LOCKDECL(X) pthread_spinlock_t X
0183     
0184 /**
0185  * Spinlock lock
0186  * This will ensure that scheduler yield would run
0187  * @param X name of variable of spinlock
0188  */
0189 #define NDRX_SPIN_LOCK_V(X) \
0190     while (1)\
0191     {\
0192         int ndrx_try_counter; int ndrx_try_done=EXFALSE;\
0193         for (ndrx_try_counter=0; ndrx_try_counter < 1000; ndrx_try_counter++)\
0194         {\
0195             if (EXSUCCEED==pthread_spin_trylock(&X)) {ndrx_try_done=EXTRUE; break;}\
0196         }\
0197         if (ndrx_try_done) {break;}\
0198         sched_yield();\
0199     }
0200 
0201 /**
0202  * Try lock
0203  * @param X lock var name
0204  * @return 0 - if locked, else error
0205  */
0206 #define NDRX_SPIN_TRYLOCK_V(X) pthread_spin_trylock(&X)
0207     
0208 /**
0209  * Spinlock unlock
0210  * @param X name of variable of spinlock
0211  */
0212 #define NDRX_SPIN_UNLOCK_V(X) pthread_spin_unlock(&X)
0213 
0214 /**
0215  * Destroy spinlock 
0216  * @param X spinlock var
0217  */
0218 #define NDRX_SPIN_DESTROY_V(X) pthread_spin_destroy(&X)
0219     
0220 /**
0221  * Delcare RW mutex with init
0222  * @param X rw lock variable name
0223  */ 
0224 #define NDRX_RWLOCK_DECL(X) pthread_rwlock_t X = PTHREAD_RWLOCK_INITIALIZER;
0225     
0226 /**
0227  * Read lock
0228  * @param X name of the lock variable
0229  */
0230 #define NDRX_RWLOCK_RLOCK_V(X) \
0231     do {int ndrx_mut_ret; if (0!=(ndrx_mut_ret=pthread_rwlock_rdlock(&X)))\
0232      {userlog("pthread_rwlock_rdlock failed %d/%s at %s:%u %s() - aborting", \
0233         ndrx_mut_ret, strerror(ndrx_mut_ret), __FILE__, __LINE__, __func__); abort();} } while (0)
0234         
0235     
0236 /**
0237  * Write lock
0238  * @param X name of the lock variable
0239  */
0240 #define NDRX_RWLOCK_WLOCK_V(X) \
0241     do {int ndrx_mut_ret; if (0!=(ndrx_mut_ret=pthread_rwlock_wrlock(&X)))\
0242      {userlog("pthread_rwlock_wrlock failed %d/%s at %s:%u %s() - aborting", \
0243         ndrx_mut_ret, strerror(ndrx_mut_ret), __FILE__, __LINE__, __func__); abort();} } while (0)
0244 
0245 /**
0246  * RW unlock
0247  * @param X name of rw lock variable
0248  */
0249 #define NDRX_RWLOCK_UNLOCK_V(X) \
0250     do {int ndrx_mut_ret; if (0!=(ndrx_mut_ret=pthread_rwlock_unlock(&X)))\
0251      {userlog("pthread_rwlock_unlock failed %d/%s at %s:%u %s() - aborting", \
0252         ndrx_mut_ret, strerror(ndrx_mut_ret), __FILE__, __LINE__, __func__); abort();} } while (0)
0253 
0254 /*---------------------------Enums--------------------------------------*/
0255 /*---------------------------Typedefs-----------------------------------*/
0256 /*---------------------------Globals------------------------------------*/
0257 /*---------------------------Statics------------------------------------*/
0258 /*---------------------------Prototypes---------------------------------*/
0259 
0260 #ifdef  __cplusplus
0261 }
0262 #endif
0263 
0264 #endif  /* THLOCK_H */
0265 
0266 /* vim: set ts=4 sw=4 et smartindent: */