1290001Sglebius/*
2290001Sglebius * Copyright (C) 2004-2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
3290001Sglebius * Copyright (C) 1998-2001  Internet Software Consortium.
4290001Sglebius *
5290001Sglebius * Permission to use, copy, modify, and/or distribute this software for any
6290001Sglebius * purpose with or without fee is hereby granted, provided that the above
7290001Sglebius * copyright notice and this permission notice appear in all copies.
8290001Sglebius *
9290001Sglebius * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10290001Sglebius * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11290001Sglebius * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12290001Sglebius * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13290001Sglebius * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14290001Sglebius * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15290001Sglebius * PERFORMANCE OF THIS SOFTWARE.
16290001Sglebius */
17290001Sglebius
18290001Sglebius/* $Id$ */
19290001Sglebius
20290001Sglebius#ifndef ISC_UTIL_H
21290001Sglebius#define ISC_UTIL_H 1
22290001Sglebius
23290001Sglebius/*! \file isc/util.h
24290001Sglebius * NOTE:
25290001Sglebius *
26290001Sglebius * This file is not to be included from any <isc/???.h> (or other) library
27290001Sglebius * files.
28290001Sglebius *
29290001Sglebius * \brief
30290001Sglebius * Including this file puts several macros in your name space that are
31290001Sglebius * not protected (as all the other ISC functions/macros do) by prepending
32290001Sglebius * ISC_ or isc_ to the name.
33290001Sglebius */
34290001Sglebius
35290001Sglebius/***
36290001Sglebius *** General Macros.
37290001Sglebius ***/
38290001Sglebius
39290001Sglebius/*%
40290001Sglebius * Use this to hide unused function arguments.
41290001Sglebius * \code
42290001Sglebius * int
43290001Sglebius * foo(char *bar)
44290001Sglebius * {
45290001Sglebius *	UNUSED(bar);
46290001Sglebius * }
47290001Sglebius * \endcode
48290001Sglebius */
49290001Sglebius#define UNUSED(x)      (void)(x)
50290001Sglebius
51290001Sglebius/*%
52290001Sglebius * The opposite: silent warnings about stored values which are never read.
53290001Sglebius */
54290001Sglebius#define POST(x)        (void)(x)
55290001Sglebius
56290001Sglebius#define ISC_MAX(a, b)  ((a) > (b) ? (a) : (b))
57290001Sglebius#define ISC_MIN(a, b)  ((a) < (b) ? (a) : (b))
58290001Sglebius
59290001Sglebius/*%
60290001Sglebius * Use this to remove the const qualifier of a variable to assign it to
61290001Sglebius * a non-const variable or pass it as a non-const function argument ...
62290001Sglebius * but only when you are sure it won't then be changed!
63290001Sglebius * This is necessary to sometimes shut up some compilers
64290001Sglebius * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
65290001Sglebius * situation.
66290001Sglebius */
67290001Sglebius#define DE_CONST(konst, var) \
68290001Sglebius	do { \
69290001Sglebius		union { const void *k; void *v; } _u; \
70290001Sglebius		_u.k = konst; \
71290001Sglebius		var = _u.v; \
72290001Sglebius	} while (0)
73290001Sglebius
74290001Sglebius/*%
75290001Sglebius * Use this in translation units that would otherwise be empty, to
76290001Sglebius * suppress compiler warnings.
77290001Sglebius */
78290001Sglebius#define EMPTY_TRANSLATION_UNIT extern void exit(int);
79290001Sglebius
80290001Sglebius/*%
81290001Sglebius * We use macros instead of calling the routines directly because
82290001Sglebius * the capital letters make the locking stand out.
83290001Sglebius * We RUNTIME_CHECK for success since in general there's no way
84290001Sglebius * for us to continue if they fail.
85290001Sglebius */
86290001Sglebius
87290001Sglebius#ifdef ISC_UTIL_TRACEON
88290001Sglebius#define ISC_UTIL_TRACE(a) a
89290001Sglebius#include <stdio.h>		/* Required for fprintf/stderr when tracing. */
90290001Sglebius#include <isc/msgs.h>		/* Required for isc_msgcat when tracing. */
91290001Sglebius#else
92290001Sglebius#define ISC_UTIL_TRACE(a)
93290001Sglebius#endif
94290001Sglebius
95290001Sglebius#include <isc/result.h>		/* Contractual promise. */
96290001Sglebius
97290001Sglebius#define LOCK(lp) do { \
98290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
99290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
100290001Sglebius					      ISC_MSG_LOCKING, "LOCKING"), \
101290001Sglebius			       (lp), __FILE__, __LINE__)); \
102290001Sglebius	RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
103290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
104290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
105290001Sglebius					      ISC_MSG_LOCKED, "LOCKED"), \
106290001Sglebius			       (lp), __FILE__, __LINE__)); \
107290001Sglebius	} while (0)
108290001Sglebius#define UNLOCK(lp) do { \
109290001Sglebius	RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
110290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
111290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
112290001Sglebius					      ISC_MSG_UNLOCKED, "UNLOCKED"), \
113290001Sglebius			       (lp), __FILE__, __LINE__)); \
114290001Sglebius	} while (0)
115290001Sglebius#define ISLOCKED(lp) (1)
116290001Sglebius#define DESTROYLOCK(lp) \
117290001Sglebius	RUNTIME_CHECK(isc_mutex_destroy((lp)) == ISC_R_SUCCESS)
118290001Sglebius
119290001Sglebius
120290001Sglebius#define BROADCAST(cvp) do { \
121290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
122290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
123290001Sglebius					      ISC_MSG_BROADCAST, "BROADCAST"),\
124290001Sglebius			       (cvp), __FILE__, __LINE__)); \
125290001Sglebius	RUNTIME_CHECK(isc_condition_broadcast((cvp)) == ISC_R_SUCCESS); \
126290001Sglebius	} while (0)
127290001Sglebius#define SIGNAL(cvp) do { \
128290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
129290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
130290001Sglebius					      ISC_MSG_SIGNAL, "SIGNAL"), \
131290001Sglebius			       (cvp), __FILE__, __LINE__)); \
132290001Sglebius	RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
133290001Sglebius	} while (0)
134290001Sglebius#define WAIT(cvp, lp) do { \
135290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
136290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
137290001Sglebius					      ISC_MSG_UTILWAIT, "WAIT"), \
138290001Sglebius			       (cvp), \
139290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
140290001Sglebius					      ISC_MSG_LOCK, "LOCK"), \
141290001Sglebius			       (lp), __FILE__, __LINE__)); \
142290001Sglebius	RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == ISC_R_SUCCESS); \
143290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
144290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
145290001Sglebius					      ISC_MSG_WAITED, "WAITED"), \
146290001Sglebius			       (cvp), \
147290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
148290001Sglebius					      ISC_MSG_LOCKED, "LOCKED"), \
149290001Sglebius			       (lp), __FILE__, __LINE__)); \
150290001Sglebius	} while (0)
151290001Sglebius
152290001Sglebius/*
153290001Sglebius * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
154290001Sglebius * don't RUNTIME_CHECK the result.
155290001Sglebius *
156290001Sglebius *  XXX Also, can't really debug this then...
157290001Sglebius */
158290001Sglebius
159290001Sglebius#define WAITUNTIL(cvp, lp, tp) \
160290001Sglebius	isc_condition_waituntil((cvp), (lp), (tp))
161290001Sglebius
162290001Sglebius#define RWLOCK(lp, t) do { \
163290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
164290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
165290001Sglebius					      ISC_MSG_RWLOCK, "RWLOCK"), \
166290001Sglebius			       (lp), (t), __FILE__, __LINE__)); \
167290001Sglebius	RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
168290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
169290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
170290001Sglebius					      ISC_MSG_RWLOCKED, "RWLOCKED"), \
171290001Sglebius			       (lp), (t), __FILE__, __LINE__)); \
172290001Sglebius	} while (0)
173290001Sglebius#define RWUNLOCK(lp, t) do { \
174290001Sglebius	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
175290001Sglebius			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
176290001Sglebius					      ISC_MSG_RWUNLOCK, "RWUNLOCK"), \
177290001Sglebius			       (lp), (t), __FILE__, __LINE__)); \
178290001Sglebius	RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
179290001Sglebius	} while (0)
180290001Sglebius
181290001Sglebius#define DESTROYMUTEXBLOCK(bp, n) \
182290001Sglebius	RUNTIME_CHECK(isc_mutexblock_destroy((bp), (n)) == ISC_R_SUCCESS)
183290001Sglebius
184290001Sglebius/*
185290001Sglebius * List Macros.
186290001Sglebius */
187290001Sglebius#include <isc/list.h>		/* Contractual promise. */
188290001Sglebius
189290001Sglebius#define LIST(type)			ISC_LIST(type)
190290001Sglebius#define INIT_LIST(type)			ISC_LIST_INIT(type)
191290001Sglebius#define LINK(type)			ISC_LINK(type)
192290001Sglebius#define INIT_LINK(elt, link)		ISC_LINK_INIT(elt, link)
193290001Sglebius#define HEAD(list)			ISC_LIST_HEAD(list)
194290001Sglebius#define TAIL(list)			ISC_LIST_TAIL(list)
195290001Sglebius#define EMPTY(list)			ISC_LIST_EMPTY(list)
196290001Sglebius#define PREV(elt, link)			ISC_LIST_PREV(elt, link)
197290001Sglebius#define NEXT(elt, link)			ISC_LIST_NEXT(elt, link)
198290001Sglebius#define APPEND(list, elt, link)		ISC_LIST_APPEND(list, elt, link)
199290001Sglebius#define PREPEND(list, elt, link)	ISC_LIST_PREPEND(list, elt, link)
200290001Sglebius#define UNLINK(list, elt, link)		ISC_LIST_UNLINK(list, elt, link)
201290001Sglebius#define ENQUEUE(list, elt, link)	ISC_LIST_APPEND(list, elt, link)
202290001Sglebius#define DEQUEUE(list, elt, link)	ISC_LIST_UNLINK(list, elt, link)
203290001Sglebius#define INSERTBEFORE(li, b, e, ln)	ISC_LIST_INSERTBEFORE(li, b, e, ln)
204290001Sglebius#define INSERTAFTER(li, a, e, ln)	ISC_LIST_INSERTAFTER(li, a, e, ln)
205290001Sglebius#define APPENDLIST(list1, list2, link)	ISC_LIST_APPENDLIST(list1, list2, link)
206290001Sglebius
207290001Sglebius/*
208290001Sglebius * Assertions
209290001Sglebius */
210290001Sglebius#include <isc/assertions.h>	/* Contractual promise. */
211290001Sglebius
212290001Sglebius/*% Require Assertion */
213290001Sglebius#define REQUIRE(e)			ISC_REQUIRE(e)
214290001Sglebius/*% Ensure Assertion */
215290001Sglebius#define ENSURE(e)			ISC_ENSURE(e)
216290001Sglebius/*% Insist Assertion */
217290001Sglebius#define INSIST(e)			ISC_INSIST(e)
218290001Sglebius/*% Invariant Assertion */
219290001Sglebius#define INVARIANT(e)			ISC_INVARIANT(e)
220290001Sglebius
221290001Sglebius/*
222290001Sglebius * Errors
223290001Sglebius */
224290001Sglebius#include <isc/error.h>		/* Contractual promise. */
225290001Sglebius
226290001Sglebius/*% Unexpected Error */
227290001Sglebius#define UNEXPECTED_ERROR		isc_error_unexpected
228290001Sglebius/*% Fatal Error */
229290001Sglebius#define FATAL_ERROR			isc_error_fatal
230290001Sglebius/*% Runtime Check */
231290001Sglebius#define RUNTIME_CHECK(cond)		ISC_ERROR_RUNTIMECHECK(cond)
232290001Sglebius
233290001Sglebius/*%
234290001Sglebius * Time
235290001Sglebius */
236290001Sglebius#define TIME_NOW(tp) 	RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
237290001Sglebius
238290001Sglebius#endif /* ISC_UTIL_H */
239