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