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