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