1 /* Copyright (C) 2007-2013 Open Information Security Foundation 2 * 3 * You can copy, redistribute or modify this Program under the terms of 4 * the GNU General Public License version 2 as published by the Free 5 * Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * version 2 along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 * 02110-1301, USA. 16 */ 17 18 /** 19 * \file 20 * 21 * \author Victor Julien <victor@inliniac.net> 22 * 23 * Lock profiling wrappers 24 */ 25 26 #ifndef __THREADS_PROFILE_H__ 27 #define __THREADS_PROFILE_H__ 28 29 /* profiling */ 30 31 typedef struct ProfilingLock_ { 32 char *file; 33 char *func; 34 int line; 35 int type; 36 uint32_t cont; 37 uint64_t ticks; 38 } ProfilingLock; 39 40 extern thread_local ProfilingLock locks[PROFILING_MAX_LOCKS]; 41 extern thread_local int locks_idx; 42 extern thread_local int record_locks; 43 44 extern thread_local uint64_t mutex_lock_contention; 45 extern thread_local uint64_t mutex_lock_wait_ticks; 46 extern thread_local uint64_t mutex_lock_cnt; 47 48 /* mutex */ 49 50 //printf("%16s(%s:%d): (thread:%"PRIuMAX") locked mutex %p ret %" PRId32 "\n", __FUNCTION__, __FILE__, __LINE__, (uintmax_t)pthread_self(), mut, retl); 51 #define SCMutexLock_profile(mut) ({ \ 52 mutex_lock_cnt++; \ 53 int retl = 0; \ 54 int cont = 0; \ 55 uint64_t mutex_lock_start = UtilCpuGetTicks(); \ 56 if (pthread_mutex_trylock((mut)) != 0) { \ 57 mutex_lock_contention++; \ 58 cont = 1; \ 59 retl = pthread_mutex_lock(mut); \ 60 } \ 61 uint64_t mutex_lock_end = UtilCpuGetTicks(); \ 62 mutex_lock_wait_ticks += (uint64_t)(mutex_lock_end - mutex_lock_start); \ 63 \ 64 if (locks_idx < PROFILING_MAX_LOCKS && record_locks) { \ 65 locks[locks_idx].file = (char *)__FILE__; \ 66 locks[locks_idx].func = (char *)__func__; \ 67 locks[locks_idx].line = (int)__LINE__; \ 68 locks[locks_idx].type = LOCK_MUTEX; \ 69 locks[locks_idx].cont = cont; \ 70 locks[locks_idx].ticks = (uint64_t)(mutex_lock_end - mutex_lock_start); \ 71 locks_idx++; \ 72 } \ 73 retl; \ 74 }) 75 76 #define SCMutex pthread_mutex_t 77 #define SCMutexAttr pthread_mutexattr_t 78 #define SCMutexInit(mut, mutattr ) pthread_mutex_init(mut, mutattr) 79 #define SCMutexLock(mut) SCMutexLock_profile(mut) 80 #define SCMutexTrylock(mut) pthread_mutex_trylock(mut) 81 #define SCMutexUnlock(mut) pthread_mutex_unlock(mut) 82 #define SCMutexDestroy pthread_mutex_destroy 83 #define SCMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 84 85 /* conditions */ 86 87 #define SCCondT pthread_cond_t 88 #define SCCondInit pthread_cond_init 89 #define SCCondSignal pthread_cond_signal 90 #define SCCondDestroy pthread_cond_destroy 91 #define SCCondWait(cond, mut) pthread_cond_wait(cond, mut) 92 93 /* spinlocks */ 94 95 extern thread_local uint64_t spin_lock_contention; 96 extern thread_local uint64_t spin_lock_wait_ticks; 97 extern thread_local uint64_t spin_lock_cnt; 98 99 //printf("%16s(%s:%d): (thread:%"PRIuMAX") locked mutex %p ret %" PRId32 "\n", __FUNCTION__, __FILE__, __LINE__, (uintmax_t)pthread_self(), mut, retl); 100 #define SCSpinLock_profile(spin) ({ \ 101 spin_lock_cnt++; \ 102 int retl = 0; \ 103 int cont = 0; \ 104 uint64_t spin_lock_start = UtilCpuGetTicks(); \ 105 if (pthread_spin_trylock((spin)) != 0) { \ 106 spin_lock_contention++; \ 107 cont = 1; \ 108 retl = pthread_spin_lock((spin)); \ 109 } \ 110 uint64_t spin_lock_end = UtilCpuGetTicks(); \ 111 spin_lock_wait_ticks += (uint64_t)(spin_lock_end - spin_lock_start); \ 112 \ 113 if (locks_idx < PROFILING_MAX_LOCKS && record_locks) { \ 114 locks[locks_idx].file = (char *)__FILE__; \ 115 locks[locks_idx].func = (char *)__func__; \ 116 locks[locks_idx].line = (int)__LINE__; \ 117 locks[locks_idx].type = LOCK_SPIN; \ 118 locks[locks_idx].cont = cont; \ 119 locks[locks_idx].ticks = (uint64_t)(spin_lock_end - spin_lock_start); \ 120 locks_idx++; \ 121 } \ 122 retl; \ 123 }) 124 125 #define SCSpinlock pthread_spinlock_t 126 #define SCSpinLock(mut) SCSpinLock_profile(mut) 127 #define SCSpinTrylock(spin) pthread_spin_trylock(spin) 128 #define SCSpinUnlock(spin) pthread_spin_unlock(spin) 129 #define SCSpinInit(spin, spin_attr) pthread_spin_init(spin, spin_attr) 130 #define SCSpinDestroy(spin) pthread_spin_destroy(spin) 131 132 /* rwlocks */ 133 134 extern thread_local uint64_t rww_lock_contention; 135 extern thread_local uint64_t rww_lock_wait_ticks; 136 extern thread_local uint64_t rww_lock_cnt; 137 138 #define SCRWLockWRLock_profile(mut) ({ \ 139 rww_lock_cnt++; \ 140 int retl = 0; \ 141 int cont = 0; \ 142 uint64_t rww_lock_start = UtilCpuGetTicks(); \ 143 if (pthread_rwlock_trywrlock((mut)) != 0) { \ 144 rww_lock_contention++; \ 145 cont = 1; \ 146 retl = pthread_rwlock_wrlock(mut); \ 147 } \ 148 uint64_t rww_lock_end = UtilCpuGetTicks(); \ 149 rww_lock_wait_ticks += (uint64_t)(rww_lock_end - rww_lock_start); \ 150 \ 151 if (locks_idx < PROFILING_MAX_LOCKS && record_locks) { \ 152 locks[locks_idx].file = (char *)__FILE__; \ 153 locks[locks_idx].func = (char *)__func__; \ 154 locks[locks_idx].line = (int)__LINE__; \ 155 locks[locks_idx].type = LOCK_RWW; \ 156 locks[locks_idx].cont = cont; \ 157 locks[locks_idx].ticks = (uint64_t)(rww_lock_end - rww_lock_start); \ 158 locks_idx++; \ 159 } \ 160 retl; \ 161 }) 162 163 extern thread_local uint64_t rwr_lock_contention; 164 extern thread_local uint64_t rwr_lock_wait_ticks; 165 extern thread_local uint64_t rwr_lock_cnt; 166 167 #define SCRWLockRDLock_profile(mut) ({ \ 168 rwr_lock_cnt++; \ 169 int retl = 0; \ 170 int cont = 0; \ 171 uint64_t rwr_lock_start = UtilCpuGetTicks(); \ 172 if (pthread_rwlock_tryrdlock((mut)) != 0) { \ 173 rwr_lock_contention++; \ 174 cont = 1; \ 175 retl = pthread_rwlock_rdlock(mut); \ 176 } \ 177 uint64_t rwr_lock_end = UtilCpuGetTicks(); \ 178 rwr_lock_wait_ticks += (uint64_t)(rwr_lock_end - rwr_lock_start); \ 179 \ 180 if (locks_idx < PROFILING_MAX_LOCKS && record_locks) { \ 181 locks[locks_idx].file = (char *)__FILE__; \ 182 locks[locks_idx].func = (char *)__func__; \ 183 locks[locks_idx].line = (int)__LINE__; \ 184 locks[locks_idx].type = LOCK_RWR; \ 185 locks[locks_idx].cont = cont; \ 186 locks[locks_idx].ticks = (uint64_t)(rwr_lock_end - rwr_lock_start); \ 187 locks_idx++; \ 188 } \ 189 retl; \ 190 }) 191 192 #define SCRWLock pthread_rwlock_t 193 #define SCRWLockInit(rwl, rwlattr ) pthread_rwlock_init(rwl, rwlattr) 194 #define SCRWLockWRLock(mut) SCRWLockWRLock_profile(mut) 195 #define SCRWLockRDLock(mut) SCRWLockRDLock_profile(mut) 196 #define SCRWLockTryWRLock(rwl) pthread_rwlock_trywrlock(rwl) 197 #define SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl) 198 #define SCRWLockUnlock(rwl) pthread_rwlock_unlock(rwl) 199 #define SCRWLockDestroy pthread_rwlock_destroy 200 201 /* ctrl mutex */ 202 #define SCCtrlMutex pthread_mutex_t 203 #define SCCtrlMutexAttr pthread_mutexattr_t 204 #define SCCtrlMutexInit(mut, mutattr ) pthread_mutex_init(mut, mutattr) 205 #define SCCtrlMutexLock(mut) pthread_mutex_lock(mut) 206 #define SCCtrlMutexTrylock(mut) pthread_mutex_trylock(mut) 207 #define SCCtrlMutexUnlock(mut) pthread_mutex_unlock(mut) 208 #define SCCtrlMutexDestroy pthread_mutex_destroy 209 210 /* ctrl conditions */ 211 #define SCCtrlCondT pthread_cond_t 212 #define SCCtrlCondInit pthread_cond_init 213 #define SCCtrlCondSignal pthread_cond_signal 214 #define SCCtrlCondTimedwait pthread_cond_timedwait 215 #define SCCtrlCondWait pthread_cond_wait 216 #define SCCtrlCondDestroy pthread_cond_destroy 217 218 #endif 219