1 /* $NetBSD: mutex.h,v 1.1 2024/02/18 20:57:56 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef ISC_MUTEX_H 17 #define ISC_MUTEX_H 1 18 19 /*! \file */ 20 21 #include <pthread.h> 22 #include <stdio.h> 23 24 #include <isc/lang.h> 25 #include <isc/result.h> /* for ISC_R_ codes */ 26 27 ISC_LANG_BEGINDECLS 28 29 /*! 30 * Supply mutex attributes that enable deadlock detection 31 * (helpful when debugging). This is system dependent and 32 * currently only supported on NetBSD. 33 */ 34 #if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK) 35 extern pthread_mutexattr_t isc__mutex_attrs; 36 #define ISC__MUTEX_ATTRS &isc__mutex_attrs 37 #else /* if ISC_MUTEX_DEBUG && defined(__NetBSD__) && \ 38 * defined(PTHREAD_MUTEX_ERRORCHECK) */ 39 #define ISC__MUTEX_ATTRS NULL 40 #endif /* if ISC_MUTEX_DEBUG && defined(__NetBSD__) && \ 41 * defined(PTHREAD_MUTEX_ERRORCHECK) */ 42 43 /* XXX We could do fancier error handling... */ 44 45 /*! 46 * Define ISC_MUTEX_PROFILE to turn on profiling of mutexes by line. When 47 * enabled, isc_mutex_stats() can be used to print a table showing the 48 * number of times each type of mutex was locked and the amount of time 49 * waiting to obtain the lock. 50 */ 51 #ifndef ISC_MUTEX_PROFILE 52 #define ISC_MUTEX_PROFILE 0 53 #endif /* ifndef ISC_MUTEX_PROFILE */ 54 55 #if ISC_MUTEX_PROFILE 56 typedef struct isc_mutexstats isc_mutexstats_t; 57 58 typedef struct { 59 pthread_mutex_t mutex; /*%< The actual mutex. */ 60 isc_mutexstats_t *stats; /*%< Mutex statistics. */ 61 } isc_mutex_t; 62 #else /* if ISC_MUTEX_PROFILE */ 63 typedef pthread_mutex_t isc_mutex_t; 64 #endif /* if ISC_MUTEX_PROFILE */ 65 66 #if ISC_MUTEX_PROFILE 67 #define isc_mutex_init(mp) isc_mutex_init_profile((mp), __FILE__, __LINE__) 68 #else /* if ISC_MUTEX_PROFILE */ 69 #if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) 70 #define isc_mutex_init(mp) isc_mutex_init_errcheck((mp)) 71 #else /* if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) */ 72 #define isc_mutex_init(mp) isc__mutex_init((mp), __FILE__, __LINE__) 73 void 74 isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line); 75 #endif /* if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) */ 76 #endif /* if ISC_MUTEX_PROFILE */ 77 78 #if ISC_MUTEX_PROFILE 79 #define isc_mutex_lock(mp) isc_mutex_lock_profile((mp), __FILE__, __LINE__) 80 #else /* if ISC_MUTEX_PROFILE */ 81 #define isc_mutex_lock(mp) \ 82 ((pthread_mutex_lock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED) 83 #endif /* if ISC_MUTEX_PROFILE */ 84 85 #if ISC_MUTEX_PROFILE 86 #define isc_mutex_unlock(mp) isc_mutex_unlock_profile((mp), __FILE__, __LINE__) 87 #else /* if ISC_MUTEX_PROFILE */ 88 #define isc_mutex_unlock(mp) \ 89 ((pthread_mutex_unlock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED) 90 #endif /* if ISC_MUTEX_PROFILE */ 91 92 #if ISC_MUTEX_PROFILE 93 #define isc_mutex_trylock(mp) \ 94 ((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? ISC_R_SUCCESS \ 95 : ISC_R_LOCKBUSY) 96 #else /* if ISC_MUTEX_PROFILE */ 97 #define isc_mutex_trylock(mp) \ 98 ((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY) 99 #endif /* if ISC_MUTEX_PROFILE */ 100 101 #if ISC_MUTEX_PROFILE 102 #define isc_mutex_destroy(mp) \ 103 RUNTIME_CHECK(pthread_mutex_destroy((&(mp)->mutex)) == 0) 104 #else /* if ISC_MUTEX_PROFILE */ 105 #define isc_mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0) 106 #endif /* if ISC_MUTEX_PROFILE */ 107 108 #if ISC_MUTEX_PROFILE 109 #define isc_mutex_stats(fp) isc_mutex_statsprofile(fp); 110 #else /* if ISC_MUTEX_PROFILE */ 111 #define isc_mutex_stats(fp) 112 #endif /* if ISC_MUTEX_PROFILE */ 113 114 #if ISC_MUTEX_PROFILE 115 116 void 117 isc_mutex_init_profile(isc_mutex_t *mp, const char *_file, int _line); 118 isc_result_t 119 isc_mutex_lock_profile(isc_mutex_t *mp, const char *_file, int _line); 120 isc_result_t 121 isc_mutex_unlock_profile(isc_mutex_t *mp, const char *_file, int _line); 122 123 void 124 isc_mutex_statsprofile(FILE *fp); 125 #endif /* ISC_MUTEX_PROFILE */ 126 127 void 128 isc_mutex_init_errcheck(isc_mutex_t *mp); 129 130 ISC_LANG_ENDDECLS 131 #endif /* ISC_MUTEX_H */ 132