Home | History | Annotate | Line # | Download | only in isc
      1 /*	$NetBSD: util.h,v 1.2 2024/08/18 20:47:15 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 (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 extern void exit(int);
     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 (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 (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 (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 (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 (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 (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 (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 #endif /* ISC_UTIL_H */
    241