1258945Sroberto/*
2280849Scy * Copyright (C) 2004-2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 1998-2001  Internet Software Consortium.
4258945Sroberto *
5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
6258945Sroberto * purpose with or without fee is hereby granted, provided that the above
7258945Sroberto * copyright notice and this permission notice appear in all copies.
8258945Sroberto *
9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
16258945Sroberto */
17258945Sroberto
18280849Scy/* $Id$ */
19258945Sroberto
20258945Sroberto#ifndef ISC_UTIL_H
21258945Sroberto#define ISC_UTIL_H 1
22258945Sroberto
23258945Sroberto/*! \file isc/util.h
24258945Sroberto * NOTE:
25258945Sroberto *
26258945Sroberto * This file is not to be included from any <isc/???.h> (or other) library
27258945Sroberto * files.
28258945Sroberto *
29258945Sroberto * \brief
30258945Sroberto * Including this file puts several macros in your name space that are
31258945Sroberto * not protected (as all the other ISC functions/macros do) by prepending
32258945Sroberto * ISC_ or isc_ to the name.
33258945Sroberto */
34258945Sroberto
35258945Sroberto/***
36258945Sroberto *** General Macros.
37258945Sroberto ***/
38258945Sroberto
39258945Sroberto/*%
40258945Sroberto * Use this to hide unused function arguments.
41258945Sroberto * \code
42258945Sroberto * int
43258945Sroberto * foo(char *bar)
44258945Sroberto * {
45258945Sroberto *	UNUSED(bar);
46258945Sroberto * }
47258945Sroberto * \endcode
48258945Sroberto */
49258945Sroberto#define UNUSED(x)      (void)(x)
50258945Sroberto
51280849Scy/*%
52280849Scy * The opposite: silent warnings about stored values which are never read.
53280849Scy */
54280849Scy#define POST(x)        (void)(x)
55280849Scy
56258945Sroberto#define ISC_MAX(a, b)  ((a) > (b) ? (a) : (b))
57258945Sroberto#define ISC_MIN(a, b)  ((a) < (b) ? (a) : (b))
58258945Sroberto
59258945Sroberto/*%
60258945Sroberto * Use this to remove the const qualifier of a variable to assign it to
61258945Sroberto * a non-const variable or pass it as a non-const function argument ...
62258945Sroberto * but only when you are sure it won't then be changed!
63258945Sroberto * This is necessary to sometimes shut up some compilers
64258945Sroberto * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
65258945Sroberto * situation.
66258945Sroberto */
67258945Sroberto#define DE_CONST(konst, var) \
68258945Sroberto	do { \
69258945Sroberto		union { const void *k; void *v; } _u; \
70258945Sroberto		_u.k = konst; \
71258945Sroberto		var = _u.v; \
72258945Sroberto	} while (0)
73258945Sroberto
74258945Sroberto/*%
75258945Sroberto * Use this in translation units that would otherwise be empty, to
76258945Sroberto * suppress compiler warnings.
77258945Sroberto */
78280849Scy#define EMPTY_TRANSLATION_UNIT extern void exit(int);
79258945Sroberto
80258945Sroberto/*%
81258945Sroberto * We use macros instead of calling the routines directly because
82258945Sroberto * the capital letters make the locking stand out.
83258945Sroberto * We RUNTIME_CHECK for success since in general there's no way
84258945Sroberto * for us to continue if they fail.
85258945Sroberto */
86258945Sroberto
87258945Sroberto#ifdef ISC_UTIL_TRACEON
88258945Sroberto#define ISC_UTIL_TRACE(a) a
89258945Sroberto#include <stdio.h>		/* Required for fprintf/stderr when tracing. */
90258945Sroberto#include <isc/msgs.h>		/* Required for isc_msgcat when tracing. */
91258945Sroberto#else
92258945Sroberto#define ISC_UTIL_TRACE(a)
93258945Sroberto#endif
94258945Sroberto
95258945Sroberto#include <isc/result.h>		/* Contractual promise. */
96258945Sroberto
97258945Sroberto#define LOCK(lp) do { \
98258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
99258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
100258945Sroberto					      ISC_MSG_LOCKING, "LOCKING"), \
101258945Sroberto			       (lp), __FILE__, __LINE__)); \
102258945Sroberto	RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
103258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
104258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
105258945Sroberto					      ISC_MSG_LOCKED, "LOCKED"), \
106258945Sroberto			       (lp), __FILE__, __LINE__)); \
107258945Sroberto	} while (0)
108258945Sroberto#define UNLOCK(lp) do { \
109258945Sroberto	RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
110258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
111258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
112258945Sroberto					      ISC_MSG_UNLOCKED, "UNLOCKED"), \
113258945Sroberto			       (lp), __FILE__, __LINE__)); \
114258945Sroberto	} while (0)
115258945Sroberto#define ISLOCKED(lp) (1)
116258945Sroberto#define DESTROYLOCK(lp) \
117258945Sroberto	RUNTIME_CHECK(isc_mutex_destroy((lp)) == ISC_R_SUCCESS)
118258945Sroberto
119258945Sroberto
120258945Sroberto#define BROADCAST(cvp) do { \
121258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
122258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
123258945Sroberto					      ISC_MSG_BROADCAST, "BROADCAST"),\
124258945Sroberto			       (cvp), __FILE__, __LINE__)); \
125258945Sroberto	RUNTIME_CHECK(isc_condition_broadcast((cvp)) == ISC_R_SUCCESS); \
126258945Sroberto	} while (0)
127258945Sroberto#define SIGNAL(cvp) do { \
128258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
129258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
130258945Sroberto					      ISC_MSG_SIGNAL, "SIGNAL"), \
131258945Sroberto			       (cvp), __FILE__, __LINE__)); \
132258945Sroberto	RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
133258945Sroberto	} while (0)
134258945Sroberto#define WAIT(cvp, lp) do { \
135258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
136258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
137258945Sroberto					      ISC_MSG_UTILWAIT, "WAIT"), \
138258945Sroberto			       (cvp), \
139258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
140258945Sroberto					      ISC_MSG_LOCK, "LOCK"), \
141258945Sroberto			       (lp), __FILE__, __LINE__)); \
142258945Sroberto	RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == ISC_R_SUCCESS); \
143258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
144258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
145258945Sroberto					      ISC_MSG_WAITED, "WAITED"), \
146258945Sroberto			       (cvp), \
147258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
148258945Sroberto					      ISC_MSG_LOCKED, "LOCKED"), \
149258945Sroberto			       (lp), __FILE__, __LINE__)); \
150258945Sroberto	} while (0)
151258945Sroberto
152258945Sroberto/*
153258945Sroberto * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
154258945Sroberto * don't RUNTIME_CHECK the result.
155258945Sroberto *
156258945Sroberto *  XXX Also, can't really debug this then...
157258945Sroberto */
158258945Sroberto
159258945Sroberto#define WAITUNTIL(cvp, lp, tp) \
160258945Sroberto	isc_condition_waituntil((cvp), (lp), (tp))
161258945Sroberto
162258945Sroberto#define RWLOCK(lp, t) do { \
163258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
164258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
165258945Sroberto					      ISC_MSG_RWLOCK, "RWLOCK"), \
166258945Sroberto			       (lp), (t), __FILE__, __LINE__)); \
167258945Sroberto	RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
168258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
169258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
170258945Sroberto					      ISC_MSG_RWLOCKED, "RWLOCKED"), \
171258945Sroberto			       (lp), (t), __FILE__, __LINE__)); \
172258945Sroberto	} while (0)
173258945Sroberto#define RWUNLOCK(lp, t) do { \
174258945Sroberto	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
175258945Sroberto			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
176258945Sroberto					      ISC_MSG_RWUNLOCK, "RWUNLOCK"), \
177258945Sroberto			       (lp), (t), __FILE__, __LINE__)); \
178258945Sroberto	RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
179258945Sroberto	} while (0)
180258945Sroberto
181258945Sroberto#define DESTROYMUTEXBLOCK(bp, n) \
182258945Sroberto	RUNTIME_CHECK(isc_mutexblock_destroy((bp), (n)) == ISC_R_SUCCESS)
183258945Sroberto
184258945Sroberto/*
185258945Sroberto * List Macros.
186258945Sroberto */
187258945Sroberto#include <isc/list.h>		/* Contractual promise. */
188258945Sroberto
189258945Sroberto#define LIST(type)			ISC_LIST(type)
190258945Sroberto#define INIT_LIST(type)			ISC_LIST_INIT(type)
191258945Sroberto#define LINK(type)			ISC_LINK(type)
192258945Sroberto#define INIT_LINK(elt, link)		ISC_LINK_INIT(elt, link)
193258945Sroberto#define HEAD(list)			ISC_LIST_HEAD(list)
194258945Sroberto#define TAIL(list)			ISC_LIST_TAIL(list)
195258945Sroberto#define EMPTY(list)			ISC_LIST_EMPTY(list)
196258945Sroberto#define PREV(elt, link)			ISC_LIST_PREV(elt, link)
197258945Sroberto#define NEXT(elt, link)			ISC_LIST_NEXT(elt, link)
198258945Sroberto#define APPEND(list, elt, link)		ISC_LIST_APPEND(list, elt, link)
199258945Sroberto#define PREPEND(list, elt, link)	ISC_LIST_PREPEND(list, elt, link)
200258945Sroberto#define UNLINK(list, elt, link)		ISC_LIST_UNLINK(list, elt, link)
201258945Sroberto#define ENQUEUE(list, elt, link)	ISC_LIST_APPEND(list, elt, link)
202258945Sroberto#define DEQUEUE(list, elt, link)	ISC_LIST_UNLINK(list, elt, link)
203258945Sroberto#define INSERTBEFORE(li, b, e, ln)	ISC_LIST_INSERTBEFORE(li, b, e, ln)
204258945Sroberto#define INSERTAFTER(li, a, e, ln)	ISC_LIST_INSERTAFTER(li, a, e, ln)
205258945Sroberto#define APPENDLIST(list1, list2, link)	ISC_LIST_APPENDLIST(list1, list2, link)
206258945Sroberto
207258945Sroberto/*
208258945Sroberto * Assertions
209258945Sroberto */
210258945Sroberto#include <isc/assertions.h>	/* Contractual promise. */
211258945Sroberto
212258945Sroberto/*% Require Assertion */
213258945Sroberto#define REQUIRE(e)			ISC_REQUIRE(e)
214258945Sroberto/*% Ensure Assertion */
215258945Sroberto#define ENSURE(e)			ISC_ENSURE(e)
216258945Sroberto/*% Insist Assertion */
217258945Sroberto#define INSIST(e)			ISC_INSIST(e)
218258945Sroberto/*% Invariant Assertion */
219258945Sroberto#define INVARIANT(e)			ISC_INVARIANT(e)
220258945Sroberto
221258945Sroberto/*
222258945Sroberto * Errors
223258945Sroberto */
224258945Sroberto#include <isc/error.h>		/* Contractual promise. */
225258945Sroberto
226258945Sroberto/*% Unexpected Error */
227258945Sroberto#define UNEXPECTED_ERROR		isc_error_unexpected
228258945Sroberto/*% Fatal Error */
229258945Sroberto#define FATAL_ERROR			isc_error_fatal
230258945Sroberto/*% Runtime Check */
231258945Sroberto#define RUNTIME_CHECK(cond)		ISC_ERROR_RUNTIMECHECK(cond)
232258945Sroberto
233258945Sroberto/*%
234258945Sroberto * Time
235258945Sroberto */
236258945Sroberto#define TIME_NOW(tp) 	RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
237258945Sroberto
238258945Sroberto#endif /* ISC_UTIL_H */
239