1 /*
2  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2002  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id: mutex.h,v 1.30 2007/06/19 23:47:18 tbox Exp $ */
19 
20 #ifndef ISC_MUTEX_H
21 #define ISC_MUTEX_H 1
22 
23 /*! \file */
24 
25 #include <pthread.h>
26 #include <stdio.h>
27 
28 #include <isc/lang.h>
29 #include <isc/result.h>		/* for ISC_R_ codes */
30 
31 ISC_LANG_BEGINDECLS
32 
33 /*!
34  * Supply mutex attributes that enable deadlock detection
35  * (helpful when debugging).  This is system dependent and
36  * currently only supported on NetBSD.
37  */
38 #if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
39 extern pthread_mutexattr_t isc__mutex_attrs;
40 #define ISC__MUTEX_ATTRS &isc__mutex_attrs
41 #else
42 #define ISC__MUTEX_ATTRS NULL
43 #endif
44 
45 /* XXX We could do fancier error handling... */
46 
47 /*!
48  * Define ISC_MUTEX_PROFILE to turn on profiling of mutexes by line.  When
49  * enabled, isc_mutex_stats() can be used to print a table showing the
50  * number of times each type of mutex was locked and the amount of time
51  * waiting to obtain the lock.
52  */
53 #ifndef ISC_MUTEX_PROFILE
54 #define ISC_MUTEX_PROFILE 0
55 #endif
56 
57 #if ISC_MUTEX_PROFILE
58 typedef struct isc_mutexstats isc_mutexstats_t;
59 
60 typedef struct {
61 	pthread_mutex_t		mutex;	/*%< The actual mutex. */
62 	isc_mutexstats_t *	stats;	/*%< Mutex statistics. */
63 } isc_mutex_t;
64 #else
65 typedef pthread_mutex_t	isc_mutex_t;
66 #endif
67 
68 
69 #if ISC_MUTEX_PROFILE
70 #define isc_mutex_init(mp) \
71 	isc_mutex_init_profile((mp), __FILE__, __LINE__)
72 #else
73 #if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
74 #define isc_mutex_init(mp) \
75         isc_mutex_init_errcheck((mp))
76 #else
77 #define isc_mutex_init(mp) \
78 	isc__mutex_init((mp), __FILE__, __LINE__)
79 isc_result_t isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
80 #endif
81 #endif
82 
83 #if ISC_MUTEX_PROFILE
84 #define isc_mutex_lock(mp) \
85 	isc_mutex_lock_profile((mp), __FILE__, __LINE__)
86 #else
87 #define isc_mutex_lock(mp) \
88 	((pthread_mutex_lock((mp)) == 0) ? \
89 	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
90 #endif
91 
92 #if ISC_MUTEX_PROFILE
93 #define isc_mutex_unlock(mp) \
94 	isc_mutex_unlock_profile((mp), __FILE__, __LINE__)
95 #else
96 #define isc_mutex_unlock(mp) \
97 	((pthread_mutex_unlock((mp)) == 0) ? \
98 	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
99 #endif
100 
101 #if ISC_MUTEX_PROFILE
102 #define isc_mutex_trylock(mp) \
103 	((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? \
104 	 ISC_R_SUCCESS : ISC_R_LOCKBUSY)
105 #else
106 #define isc_mutex_trylock(mp) \
107 	((pthread_mutex_trylock((mp)) == 0) ? \
108 	 ISC_R_SUCCESS : ISC_R_LOCKBUSY)
109 #endif
110 
111 #if ISC_MUTEX_PROFILE
112 #define isc_mutex_destroy(mp) \
113 	((pthread_mutex_destroy((&(mp)->mutex)) == 0) ? \
114 	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
115 #else
116 #define isc_mutex_destroy(mp) \
117 	((pthread_mutex_destroy((mp)) == 0) ? \
118 	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
119 #endif
120 
121 #if ISC_MUTEX_PROFILE
122 #define isc_mutex_stats(fp) isc_mutex_statsprofile(fp);
123 #else
124 #define isc_mutex_stats(fp)
125 #endif
126 
127 #if ISC_MUTEX_PROFILE
128 
129 isc_result_t
130 isc_mutex_init_profile(isc_mutex_t *mp, const char * _file, int _line);
131 isc_result_t
132 isc_mutex_lock_profile(isc_mutex_t *mp, const char * _file, int _line);
133 isc_result_t
134 isc_mutex_unlock_profile(isc_mutex_t *mp, const char * _file, int _line);
135 
136 void
137 isc_mutex_statsprofile(FILE *fp);
138 
139 isc_result_t
140 isc_mutex_init_errcheck(isc_mutex_t *mp);
141 
142 #endif /* ISC_MUTEX_PROFILE */
143 
144 ISC_LANG_ENDDECLS
145 #endif /* ISC_MUTEX_H */
146