Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-08 10:33:34

0001 #ifndef __SSIATOMICS_HH__
0002 #define __SSIATOMICS_HH__
0003 /******************************************************************************/
0004 /*                                                                            */
0005 /*                      X r d S s i A t o m i c s . h h                       */
0006 /*                                                                            */
0007 /* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University  */
0008 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
0009 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
0010 /*                                                                            */
0011 /* This file is part of the XRootD software suite.                            */
0012 /*                                                                            */
0013 /* XRootD is free software: you can redistribute it and/or modify it under    */
0014 /* the terms of the GNU Lesser General Public License as published by the     */
0015 /* Free Software Foundation, either version 3 of the License, or (at your     */
0016 /* option) any later version.                                                 */
0017 /*                                                                            */
0018 /* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
0019 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
0020 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
0021 /* License for more details.                                                  */
0022 /*                                                                            */
0023 /* You should have received a copy of the GNU Lesser General Public License   */
0024 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
0025 /* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
0026 /*                                                                            */
0027 /* The copyright holder's institutional names and contributor's names may not */
0028 /* be used to endorse or promote products derived from this software without  */
0029 /* specific prior written permission of the institution or contributor.       */
0030 /******************************************************************************/
0031 
0032 #include <cstring>
0033 
0034 #undef NEED_ATOMIC_MUTEX
0035 
0036 //-----------------------------------------------------------------------------
0037 //! Use native atomics at the c11 or higher level (-std=c++0x -lstdc++)
0038 //-----------------------------------------------------------------------------
0039 #if __cplusplus >= 201103L
0040 #include <atomic>
0041 #define Atomic(type)    std::atomic<type>
0042 #define Atomic_IMP "C++11"
0043 #define Atomic_BEG(x)
0044 #define Atomic_DEC(x)          x.fetch_sub(1,std::memory_order_relaxed)
0045 #define Atomic_GET(x)          x.load(std::memory_order_relaxed)
0046 #define Atomic_GET_STRICT(x)   x.load(std::memory_order_acquire)
0047 #define Atomic_INC(x)          x.fetch_add(1,std::memory_order_relaxed)
0048 #define Atomic_SET(x,y)        x.store(y,std::memory_order_relaxed)
0049 #define Atomic_SET_STRICT(x,y) x.store(y,std::memory_order_release)
0050 #define Atomic_ZAP(x)          x.store(0,std::memory_order_relaxed)
0051 #define Atomic_END(x)
0052 
0053 //-----------------------------------------------------------------------------
0054 //! Use new gcc builtins at 4.7 or above
0055 //-----------------------------------------------------------------------------
0056 #elif __GNUC__ == 4 && __GNUC_MINOR__ > 6
0057 #define Atomic(type)    type
0058 #define Atomic_IMP "gnu-atomic"
0059 #define Atomic_BEG(x)
0060 #define Atomic_DEC(x)          __atomic_fetch_sub(&x,1,__ATOMIC_RELAXED)
0061 #define Atomic_GET(x)          __atomic_load_n   (&x,  __ATOMIC_RELAXED)
0062 #define Atomic_GET_STRICT(x)   __atomic_load_n   (&x,  __ATOMIC_ACQUIRE)
0063 #define Atomic_INC(x)          __atomic_fetch_add(&x,1,__ATOMIC_RELAXED)
0064 #define Atomic_SET(x,y)        __atomic_store_n  (&x,y,__ATOMIC_RELAXED)
0065 #define Atomic_SET_STRICT(x,y) __atomic_store_n  (&x,y,__ATOMIC_RELEASE)
0066 #define Atomic_ZAP(x)          __atomic_store_n  (&x,0,__ATOMIC_RELAXED)
0067 #define Atomic_END(x)
0068 
0069 //-----------------------------------------------------------------------------
0070 //! Use old-style gcc builtins if they area available. The STRICT variants
0071 //! are only effective on strict memory compliant machines (e.g. x86, SPARC).
0072 //! This doesn't get resolved until gcc 4.7, sigh.
0073 //-----------------------------------------------------------------------------
0074 #elif HAVE_ATOMICS
0075 #define Atomic(type)    type
0076 #define Atomic_IMP "gnu-sync"
0077 #define Atomic_BEG(x)
0078 #define Atomic_DEC(x)              __sync_fetch_and_sub(&x, 1)
0079 #define Atomic_GET(x)              __sync_fetch_and_or (&x, 0)
0080 #define Atomic_GET_STRICT(x)       __sync_fetch_and_or (&x, 0)
0081 #define Atomic_INC(x)              __sync_fetch_and_add(&x, 1)
0082 #define Atomic_SET(x,y)        x=y,__sync_synchronize()
0083 #define Atomic_SET_STRICT(x,y)     __sync_synchronize(),x=y,__sync_synchronize()
0084 #define Atomic_ZAP(x)              __sync_fetch_and_and(&x, 0)
0085 #define Atomic_END(x)
0086 
0087 //-----------------------------------------------------------------------------
0088 //! Use ordinary operators since the program needs to use mutexes
0089 //-----------------------------------------------------------------------------
0090 #else
0091 #define NEED_ATOMIC_MUTEX 1
0092 #define Atomic_IMP "missing"
0093 #define Atomic(type)    type
0094 #define Atomic_BEG(x)   pthread_mutex_lock(x)
0095 #define Atomic_DEC(x)   x--
0096 #define Atomic_GET(x)   x
0097 #define Atomic_INC(x)   x++
0098 #define Atomic_SET(x,y) x = y
0099 #define Atomic_ZAP(x)   x = 0
0100 #define Atomic_END(x)   pthread_mutex_unlock(x)
0101 #endif
0102 
0103 /******************************************************************************/
0104 /*                           X r d S s i M u t e x                            */
0105 /******************************************************************************/
0106 
0107 #include <pthread.h>
0108 
0109 class XrdSsiMutex
0110 {
0111 public:
0112 
0113 inline bool TryLock() {return pthread_mutex_trylock( &cs ) == 0;}
0114 
0115 inline void    Lock() {pthread_mutex_lock(&cs);}
0116 
0117 inline void  UnLock() {pthread_mutex_unlock(&cs);}
0118 
0119 enum MutexType {Simple = 0, Recursive = 1};
0120 
0121        XrdSsiMutex(MutexType mt=Simple)
0122                   {int rc;
0123                    if (mt == Simple) rc = pthread_mutex_init(&cs, NULL);
0124                       else {pthread_mutexattr_t attr;
0125                             if (!(rc = pthread_mutexattr_init(&attr)))
0126                                {pthread_mutexattr_settype(&attr,
0127                                                      PTHREAD_MUTEX_RECURSIVE);
0128                                 rc = pthread_mutex_init(&cs, &attr);
0129                                }
0130                            }
0131                    if (rc) throw Errno2Text(rc);
0132                   }
0133 
0134       ~XrdSsiMutex() {pthread_mutex_destroy(&cs);}
0135 
0136 protected:
0137 
0138 pthread_mutex_t cs;
0139 
0140 private:
0141 const char* Errno2Text(int ecode);
0142 };
0143   
0144 /******************************************************************************/
0145 /*                        X r d S s i M u t e x M o n                         */
0146 /******************************************************************************/
0147   
0148 class XrdSsiMutexMon
0149 {
0150 public:
0151 
0152 inline void   Lock(XrdSsiMutex *mutex)
0153                   {if (mtx) {if (mtx != mutex) mtx->UnLock();
0154                                 else return;
0155                             }
0156                    mutex->Lock();
0157                    mtx = mutex;
0158                   };
0159 
0160 inline void   Lock(XrdSsiMutex &mutex) {Lock(&mutex);}
0161 
0162 inline void   Reset() {mtx = 0;}
0163 
0164 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
0165 
0166             XrdSsiMutexMon(XrdSsiMutex *mutex=0)
0167                           {if (mutex) mutex->Lock();
0168                            mtx =  mutex;
0169                           }
0170             XrdSsiMutexMon(XrdSsiMutex &mutex)
0171                           {mutex.Lock();
0172                            mtx = &mutex;
0173                           }
0174 
0175            ~XrdSsiMutexMon() {if (mtx) UnLock();}
0176 private:
0177 XrdSsiMutex *mtx;
0178 };
0179 #endif