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