xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/isc/pthreads/include/isc/mutex.h (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
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