1/*
2 * Copyright (C) 1998-2001  Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: util.h,v 1.23 2001/11/30 01:59:38 gson Exp $ */
19
20#ifndef ISC_UTIL_H
21#define ISC_UTIL_H 1
22
23/*
24 * NOTE:
25 *
26 * This file is not to be included from any <isc/???.h> (or other) library
27 * files.
28 *
29 * Including this file puts several macros in your name space that are
30 * not protected (as all the other ISC functions/macros do) by prepending
31 * ISC_ or isc_ to the name.
32 */
33
34/***
35 *** General Macros.
36 ***/
37
38/*
39 * Use this to hide unused function arguments.
40 *
41 * int
42 * foo(char *bar)
43 * {
44 *	UNUSED(bar);
45 * }
46 */
47#define UNUSED(x)      (void)(x)
48
49#define ISC_MAX(a, b)  ((a) > (b) ? (a) : (b))
50#define ISC_MIN(a, b)  ((a) < (b) ? (a) : (b))
51
52/*
53 * Use this to remove the const qualifier of a variable to assign it to
54 * a non-const variable or pass it as a non-const function argument ...
55 * but only when you are sure it won't then be changed!
56 * This is necessary to sometimes shut up some compilers
57 * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
58 * situation.
59 */
60#define DE_CONST(konst, var) \
61	do { \
62		union { const void *k; void *v; } _u; \
63		_u.k = konst; \
64		var = _u.v; \
65	} while (0)
66
67/*
68 * Use this in translation units that would otherwise be empty, to
69 * suppress compiler warnings.
70 */
71#define EMPTY_TRANSLATION_UNIT static void isc__empty(void) { isc__empty(); }
72
73/*
74 * We use macros instead of calling the routines directly because
75 * the capital letters make the locking stand out.
76 *
77 * We RUNTIME_CHECK for success since in general there's no way
78 * for us to continue if they fail.
79 */
80
81#ifdef ISC_UTIL_TRACEON
82#define ISC_UTIL_TRACE(a) a
83#include <stdio.h>		/* Required for fprintf/stderr when tracing. */
84#include <isc/msgs.h>		/* Required for isc_msgcat when tracing. */
85#else
86#define ISC_UTIL_TRACE(a)
87#endif
88
89#include <isc/result.h>		/* Contractual promise. */
90
91#define LOCK(lp) do { \
92	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
93			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
94					      ISC_MSG_LOCKING, "LOCKING"), \
95			       (lp), __FILE__, __LINE__)); \
96	RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
97	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
98			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
99					      ISC_MSG_LOCKED, "LOCKED"), \
100			       (lp), __FILE__, __LINE__)); \
101	} while (0)
102#define UNLOCK(lp) do { \
103	RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
104	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
105			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
106					      ISC_MSG_UNLOCKED, "UNLOCKED"), \
107			       (lp), __FILE__, __LINE__)); \
108	} while (0)
109#define ISLOCKED(lp) (1)
110#define DESTROYLOCK(lp) \
111	RUNTIME_CHECK(isc_mutex_destroy((lp)) == ISC_R_SUCCESS)
112
113
114#define BROADCAST(cvp) do { \
115	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
116			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
117					      ISC_MSG_BROADCAST, "BROADCAST"),\
118			       (cvp), __FILE__, __LINE__)); \
119	RUNTIME_CHECK(isc_condition_broadcast((cvp)) == ISC_R_SUCCESS); \
120	} while (0)
121#define SIGNAL(cvp) do { \
122	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
123			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
124					      ISC_MSG_SIGNAL, "SIGNAL"), \
125			       (cvp), __FILE__, __LINE__)); \
126	RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
127	} while (0)
128#define WAIT(cvp, lp) do { \
129	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
130			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
131					      ISC_MSG_UTILWAIT, "WAIT"), \
132			       (cvp), \
133			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
134					      ISC_MSG_LOCK, "LOCK"), \
135			       (lp), __FILE__, __LINE__)); \
136	RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == ISC_R_SUCCESS); \
137	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
138			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
139					      ISC_MSG_WAITED, "WAITED"), \
140			       (cvp), \
141			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
142					      ISC_MSG_LOCKED, "LOCKED"), \
143			       (lp), __FILE__, __LINE__)); \
144	} while (0)
145
146/*
147 * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
148 * don't RUNTIME_CHECK the result.
149 *
150 *  XXX Also, can't really debug this then...
151 */
152
153#define WAITUNTIL(cvp, lp, tp) \
154	isc_condition_waituntil((cvp), (lp), (tp))
155
156#define RWLOCK(lp, t) do { \
157	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
158			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
159					      ISC_MSG_RWLOCK, "RWLOCK"), \
160			       (lp), (t), __FILE__, __LINE__)); \
161	RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
162	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
163			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
164					      ISC_MSG_RWLOCKED, "RWLOCKED"), \
165			       (lp), (t), __FILE__, __LINE__)); \
166	} while (0)
167#define RWUNLOCK(lp, t) do { \
168	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
169			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
170					      ISC_MSG_RWUNLOCK, "RWUNLOCK"), \
171			       (lp), (t), __FILE__, __LINE__)); \
172	RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
173	} while (0)
174
175#define DESTROYMUTEXBLOCK(bp, n) \
176	RUNTIME_CHECK(isc_mutexblock_destroy((bp), (n)) == ISC_R_SUCCESS)
177
178/*
179 * List Macros.
180 */
181#include <isc/list.h>		/* Contractual promise. */
182
183#define LIST(type)			ISC_LIST(type)
184#define INIT_LIST(type)			ISC_LIST_INIT(type)
185#define LINK(type)			ISC_LINK(type)
186#define INIT_LINK(elt, link)		ISC_LINK_INIT(elt, link)
187#define HEAD(list)			ISC_LIST_HEAD(list)
188#define TAIL(list)			ISC_LIST_TAIL(list)
189#define EMPTY(list)			ISC_LIST_EMPTY(list)
190#define PREV(elt, link)			ISC_LIST_PREV(elt, link)
191#define NEXT(elt, link)			ISC_LIST_NEXT(elt, link)
192#define APPEND(list, elt, link)		ISC_LIST_APPEND(list, elt, link)
193#define PREPEND(list, elt, link)	ISC_LIST_PREPEND(list, elt, link)
194#define UNLINK(list, elt, link)		ISC_LIST_UNLINK(list, elt, link)
195#define ENQUEUE(list, elt, link)	ISC_LIST_APPEND(list, elt, link)
196#define DEQUEUE(list, elt, link)	ISC_LIST_UNLINK(list, elt, link)
197#define INSERTBEFORE(li, b, e, ln)	ISC_LIST_INSERTBEFORE(li, b, e, ln)
198#define INSERTAFTER(li, a, e, ln)	ISC_LIST_INSERTAFTER(li, a, e, ln)
199#define APPENDLIST(list1, list2, link)	ISC_LIST_APPENDLIST(list1, list2, link)
200
201/*
202 * Assertions
203 */
204#include <isc/assertions.h>	/* Contractual promise. */
205
206#define REQUIRE(e)			ISC_REQUIRE(e)
207#define ENSURE(e)			ISC_ENSURE(e)
208#define INSIST(e)			ISC_INSIST(e)
209#define INVARIANT(e)			ISC_INVARIANT(e)
210
211/*
212 * Errors
213 */
214#include <isc/error.h>		/* Contractual promise. */
215
216#define UNEXPECTED_ERROR		isc_error_unexpected
217#define FATAL_ERROR			isc_error_fatal
218#define RUNTIME_CHECK(cond)		ISC_ERROR_RUNTIMECHECK(cond)
219
220/*
221 * Time
222 */
223#define TIME_NOW(tp) 	RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
224
225#endif /* ISC_UTIL_H */
226