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
31ISC_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)
39extern 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
58typedef struct isc_mutexstats isc_mutexstats_t;
59
60typedef struct {
61	pthread_mutex_t		mutex;	/*%< The actual mutex. */
62	isc_mutexstats_t *	stats;	/*%< Mutex statistics. */
63} isc_mutex_t;
64#else
65typedef 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__)
79isc_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
129isc_result_t
130isc_mutex_init_profile(isc_mutex_t *mp, const char * _file, int _line);
131isc_result_t
132isc_mutex_lock_profile(isc_mutex_t *mp, const char * _file, int _line);
133isc_result_t
134isc_mutex_unlock_profile(isc_mutex_t *mp, const char * _file, int _line);
135
136void
137isc_mutex_statsprofile(FILE *fp);
138
139isc_result_t
140isc_mutex_init_errcheck(isc_mutex_t *mp);
141
142#endif /* ISC_MUTEX_PROFILE */
143
144ISC_LANG_ENDDECLS
145#endif /* ISC_MUTEX_H */
146