diff options
| author | Xin LI <delphij@FreeBSD.org> | 2016-09-28 03:45:43 +0000 |
|---|---|---|
| committer | Xin LI <delphij@FreeBSD.org> | 2016-09-28 03:45:43 +0000 |
| commit | c2a8859aa5c96190c179c911d3841c4de17b9c34 (patch) | |
| tree | d692d2581f8989d075abe40c9f3f55f2fa650949 /lib/isc | |
| parent | 5ef882476736cbe802bb4e6437c520162c4f44ce (diff) | |
Diffstat (limited to 'lib/isc')
45 files changed, 635 insertions, 175 deletions
diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 3176a267988d..8b2c0608aced 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -17,7 +17,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ @LIBISC_API@ diff --git a/lib/isc/alpha/include/isc/Makefile.in b/lib/isc/alpha/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/alpha/include/isc/Makefile.in +++ b/lib/isc/alpha/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/api b/lib/isc/api index 9a572b2d2e74..7de96ec52e86 100644 --- a/lib/isc/api +++ b/lib/isc/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 106 -LIBREVISION = 0 -LIBAGE = 0 +LIBINTERFACE = 107 +LIBREVISION = 1 +LIBAGE = 1 diff --git a/lib/isc/base32.c b/lib/isc/base32.c index 2ee99b182426..e472439eba5e 100644 --- a/lib/isc/base32.c +++ b/lib/isc/base32.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008, 2009, 2013-2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -170,7 +170,7 @@ base32_decode_init(base32_decode_ctx_t *ctx, int length, const char base[], static inline isc_result_t base32_decode_char(base32_decode_ctx_t *ctx, int c) { - char *s; + const char *s; unsigned int last; if (ctx->seen_end) diff --git a/lib/isc/base64.c b/lib/isc/base64.c index 6b4cb1bf7c63..554097c47eb5 100644 --- a/lib/isc/base64.c +++ b/lib/isc/base64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2013-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -118,7 +118,7 @@ base64_decode_init(base64_decode_ctx_t *ctx, int length, isc_buffer_t *target) static inline isc_result_t base64_decode_char(base64_decode_ctx_t *ctx, int c) { - char *s; + const char *s; if (ctx->seen_end) return (ISC_R_BADBASE64); diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c index 2d15e248575c..d0f08d767113 100644 --- a/lib/isc/buffer.c +++ b/lib/isc/buffer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -462,6 +462,8 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, length); dbuf->mctx = mctx; + ENSURE(ISC_BUFFER_VALID(dbuf)); + *dynbuffer = dbuf; return (ISC_R_SUCCESS); diff --git a/lib/isc/commandline.c b/lib/isc/commandline.c index 416fba1927a6..e58b1b8ceddc 100644 --- a/lib/isc/commandline.c +++ b/lib/isc/commandline.c @@ -95,7 +95,7 @@ static char endopt = '\0'; int isc_commandline_parse(int argc, char * const *argv, const char *options) { static char *place = ENDOPT; - char *option; /* Index into *options of option. */ + const char *option; /* Index into *options of option. */ REQUIRE(argc >= 0 && argv != NULL && options != NULL); diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 6ee8dcf5a1f7..8fd58532838d 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2013-2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2013-2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -399,3 +399,152 @@ isc_hash_calc(const unsigned char *key, unsigned int keylen, return (hash_calc(hash, key, keylen, case_sensitive)); } + +static isc_uint32_t fnv_offset_basis; +static isc_once_t fnv_once = ISC_ONCE_INIT; + +static void +fnv_initialize(void) { + /* + * This function should not leave fnv_offset_basis set to + * 0. Also, after this function has been called, if it is called + * again, it should not change fnv_offset_basis. + */ + while (fnv_offset_basis == 0) { + isc_random_get(&fnv_offset_basis); + } +} + +isc_uint32_t +isc_hash_function(const void *data, size_t length, + isc_boolean_t case_sensitive, + const isc_uint32_t *previous_hashp) +{ + isc_uint32_t hval; + const unsigned char *bp; + const unsigned char *be; + + INSIST(data == NULL || length > 0); + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + + hval = ISC_UNLIKELY(previous_hashp != NULL) ? + *previous_hashp : fnv_offset_basis; + + if (length == 0) + return (hval); + + bp = (const unsigned char *) data; + be = bp + length; + + /* + * Fowler-Noll-Vo FNV-1a hash function. + * + * NOTE: A random fnv_offset_basis is used by default to avoid + * collision attacks as the hash function is reversible. This + * makes the mapping non-deterministic, but the distribution in + * the domain is still uniform. + */ + + if (case_sensitive) { + while (bp < be - 4) { + hval ^= (isc_uint32_t) bp[0]; + hval *= 16777619; + hval ^= (isc_uint32_t) bp[1]; + hval *= 16777619; + hval ^= (isc_uint32_t) bp[2]; + hval *= 16777619; + hval ^= (isc_uint32_t) bp[3]; + hval *= 16777619; + bp += 4; + } + while (bp < be) { + hval ^= (isc_uint32_t) *bp++; + hval *= 16777619; + } + } else { + while (bp < be - 4) { + hval ^= (isc_uint32_t) maptolower[bp[0]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[bp[1]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[bp[2]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[bp[3]]; + hval *= 16777619; + bp += 4; + } + while (bp < be) { + hval ^= (isc_uint32_t) maptolower[*bp++]; + hval *= 16777619; + } + } + + return (hval); +} + +isc_uint32_t +isc_hash_function_reverse(const void *data, size_t length, + isc_boolean_t case_sensitive, + const isc_uint32_t *previous_hashp) +{ + isc_uint32_t hval; + const unsigned char *bp; + const unsigned char *be; + + INSIST(data == NULL || length > 0); + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + + hval = ISC_UNLIKELY(previous_hashp != NULL) ? + *previous_hashp : fnv_offset_basis; + + if (length == 0) + return (hval); + + bp = (const unsigned char *) data; + be = bp + length; + + /* + * Fowler-Noll-Vo FNV-1a hash function. + * + * NOTE: A random fnv_offset_basis is used by default to avoid + * collision attacks as the hash function is reversible. This + * makes the mapping non-deterministic, but the distribution in + * the domain is still uniform. + */ + + if (case_sensitive) { + while (be >= bp + 4) { + be -= 4; + hval ^= (isc_uint32_t) be[3]; + hval *= 16777619; + hval ^= (isc_uint32_t) be[2]; + hval *= 16777619; + hval ^= (isc_uint32_t) be[1]; + hval *= 16777619; + hval ^= (isc_uint32_t) be[0]; + hval *= 16777619; + } + while (--be >= bp) { + hval ^= (isc_uint32_t) *be; + hval *= 16777619; + } + } else { + while (be >= bp + 4) { + be -= 4; + hval ^= (isc_uint32_t) maptolower[be[3]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[be[2]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[be[1]]; + hval *= 16777619; + hval ^= (isc_uint32_t) maptolower[be[0]]; + hval *= 16777619; + } + while (--be >= bp) { + hval ^= (isc_uint32_t) maptolower[*be]; + hval *= 16777619; + } + } + + return (hval); +} diff --git a/lib/isc/hex.c b/lib/isc/hex.c index 00903c7374cf..9e565c8a1c24 100644 --- a/lib/isc/hex.c +++ b/lib/isc/hex.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2013-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -95,7 +95,7 @@ hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target) static inline isc_result_t hex_decode_char(hex_decode_ctx_t *ctx, int c) { - char *s; + const char *s; if ((s = strchr(hex, toupper(c))) == NULL) return (ISC_R_BADHEX); diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c index 241c1d53a8d5..b33f3577f994 100644 --- a/lib/isc/httpd.c +++ b/lib/isc/httpd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008, 2010-2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006-2008, 2010-2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -360,6 +360,73 @@ httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) { #define LENGTHOK(s) (httpd->recvbuf - (s) < (int)httpd->recvlen) #define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN) +/* + * Look for the given header in headers. + * If value is specified look for it terminated with a character in eov. + */ +static isc_boolean_t +have_header(isc_httpd_t *httpd, const char *header, const char *value, + const char *eov) +{ + char *cr, *nl, *h; + size_t hlen, vlen = 0; + + h = httpd->headers; + hlen = strlen(header); + if (value != NULL) { + INSIST(eov != NULL); + vlen = strlen(value); + } + + for (;;) { + if (strncasecmp(h, header, hlen) != 0) { + /* + * Skip to next line; + */ + cr = strchr(h, '\r'); + if (cr != NULL && cr[1] == '\n') + cr++; + nl = strchr(h, '\n'); + + /* last header? */ + h = cr; + if (h == NULL || (nl != NULL && nl < h)) + h = nl; + if (h == NULL) + return (ISC_FALSE); + h++; + continue; + } + + if (value == NULL) + return (ISC_TRUE); + + /* + * Skip optional leading white space. + */ + h += hlen; + while (*h == ' ' || *h == '\t') + h++; + /* + * Terminate token search on NULL or EOL. + */ + while (*h != 0 && *h != '\r' && *h != '\n') { + if (strncasecmp(h, value, vlen) == 0) + if (strchr(eov, h[vlen]) != NULL) + return (ISC_TRUE); + /* + * Skip to next token. + */ + h += strcspn(h, eov); + if (h[0] == '\r' && h[1] == '\n') + h++; + if (h[0] != 0) + h++; + } + return (ISC_FALSE); + } +} + static isc_result_t process_request(isc_httpd_t *httpd, int length) { char *s; @@ -378,15 +445,20 @@ process_request(isc_httpd_t *httpd, int length) { * more data. */ s = strstr(httpd->recvbuf, "\r\n\r\n"); - delim = 1; + delim = 2; if (s == NULL) { s = strstr(httpd->recvbuf, "\n\n"); - delim = 2; + delim = 1; } if (s == NULL) return (ISC_R_NOTFOUND); /* + * NUL terminate request at the blank line. + */ + s[delim] = 0; + + /* * Determine if this is a POST or GET method. Any other values will * cause an error to be returned. */ @@ -444,7 +516,7 @@ process_request(isc_httpd_t *httpd, int length) { } httpd->url = p; - p = s + delim; + p = s + 1; s = p; /* @@ -459,7 +531,7 @@ process_request(isc_httpd_t *httpd, int length) { /* * Extract the HTTP/1.X protocol. We will bounce on anything but - * HTTP/1.1 for now. + * HTTP/1.0 or HTTP/1.1 for now. */ while (LENGTHOK(s) && BUFLENOK(s) && (*s != '\n' && *s != '\r' && *s != '\0')) @@ -468,24 +540,30 @@ process_request(isc_httpd_t *httpd, int length) { return (ISC_R_NOTFOUND); if (!BUFLENOK(s)) return (ISC_R_NOMEMORY); + /* + * Check that we have the expected eol delimiter. + */ + if (strncmp(s, delim == 1 ? "\n" : "\r\n", delim) != 0) + return (ISC_R_RANGE); *s = 0; if ((strncmp(p, "HTTP/1.0", 8) != 0) && (strncmp(p, "HTTP/1.1", 8) != 0)) return (ISC_R_RANGE); httpd->protocol = p; - p = s + 1; + p = s + delim; /* skip past eol */ s = p; httpd->headers = s; - if (strstr(s, "Connection: close") != NULL) + if (have_header(httpd, "Connection:", "close", ", \t\r\n")) httpd->flags |= HTTPD_CLOSE; - if (strstr(s, "Host: ") != NULL) + if (have_header(httpd, "Host:", NULL, NULL)) httpd->flags |= HTTPD_FOUNDHOST; if (strncmp(httpd->protocol, "HTTP/1.0", 8) == 0) { - if (strcasestr(s, "Connection: Keep-Alive") != NULL) + if (have_header(httpd, "Connection:", "Keep-Alive", + ", \t\r\n")) httpd->flags |= HTTPD_KEEPALIVE; else httpd->flags |= HTTPD_CLOSE; @@ -838,7 +916,7 @@ isc_httpd_response(isc_httpd_t *httpd) { return (result); } - sprintf(isc_buffer_used(&httpd->headerbuffer), "%s %03d %s\r\n", + sprintf(isc_buffer_used(&httpd->headerbuffer), "%s %03u %s\r\n", httpd->protocol, httpd->retcode, httpd->retmsg); isc_buffer_add(&httpd->headerbuffer, needlen); diff --git a/lib/isc/ia64/include/isc/Makefile.in b/lib/isc/ia64/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/ia64/include/isc/Makefile.in +++ b/lib/isc/ia64/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in index 572bb3e1046b..15b55069b13b 100644 --- a/lib/isc/include/isc/Makefile.in +++ b/lib/isc/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2009, 2012-2015 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001, 2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -17,7 +17,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ # # Only list headers that are to be installed and are not diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h index 2c81b1ae9880..ebe96922dcbe 100644 --- a/lib/isc/include/isc/assertions.h +++ b/lib/isc/include/isc/assertions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -83,7 +83,7 @@ isc_assertion_typetotext(isc_assertiontype_t type); #if ISC_CHECK_REQUIRE != 0 #define ISC_REQUIRE(cond) \ - ((void) ((cond) || \ + ((void) (ISC_LIKELY(cond) || \ ((isc_assertion_failed)(__FILE__, __LINE__, \ isc_assertiontype_require, \ #cond), 0))) @@ -93,7 +93,7 @@ isc_assertion_typetotext(isc_assertiontype_t type); #if ISC_CHECK_ENSURE != 0 #define ISC_ENSURE(cond) \ - ((void) ((cond) || \ + ((void) (ISC_LIKELY(cond) || \ ((isc_assertion_failed)(__FILE__, __LINE__, \ isc_assertiontype_ensure, \ #cond), 0))) @@ -103,7 +103,7 @@ isc_assertion_typetotext(isc_assertiontype_t type); #if ISC_CHECK_INSIST != 0 #define ISC_INSIST(cond) \ - ((void) ((cond) || \ + ((void) (ISC_LIKELY(cond) || \ ((isc_assertion_failed)(__FILE__, __LINE__, \ isc_assertiontype_insist, \ #cond), 0))) @@ -113,7 +113,7 @@ isc_assertion_typetotext(isc_assertiontype_t type); #if ISC_CHECK_INVARIANT != 0 #define ISC_INVARIANT(cond) \ - ((void) ((cond) || \ + ((void) (ISC_LIKELY(cond) || \ ((isc_assertion_failed)(__FILE__, __LINE__, \ isc_assertiontype_invariant, \ #cond), 0))) diff --git a/lib/isc/include/isc/error.h b/lib/isc/include/isc/error.h index e0cdfa83e7cb..b6cac178e3d0 100644 --- a/lib/isc/include/isc/error.h +++ b/lib/isc/include/isc/error.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -55,7 +55,7 @@ void isc_error_runtimecheck(const char *, int, const char *); #define ISC_ERROR_RUNTIMECHECK(cond) \ - ((void) ((cond) || \ + ((void) (ISC_LIKELY(cond) || \ ((isc_error_runtimecheck)(__FILE__, __LINE__, #cond), 0))) ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h index 7137410b613d..97e4fd323e02 100644 --- a/lib/isc/include/isc/file.h +++ b/lib/isc/include/isc/file.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -312,8 +312,8 @@ isc_file_safecreate(const char *filename, FILE **fp); */ isc_result_t -isc_file_splitpath(isc_mem_t *mctx, char *path, - char **dirname, char **basename); +isc_file_splitpath(isc_mem_t *mctx, const char *path, + char **dirname, char const **basename); /*%< * Split a path into dirname and basename. If 'path' contains no slash * (or, on windows, backslash), then '*dirname' is set to ".". diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h index 0bfe936d7f95..46cdf78b4923 100644 --- a/lib/isc/include/isc/hash.h +++ b/lib/isc/include/isc/hash.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -180,6 +180,45 @@ isc_hash_calc(const unsigned char *key, unsigned int keylen, */ /*@}*/ +isc_uint32_t +isc_hash_function(const void *data, size_t length, + isc_boolean_t case_sensitive, + const isc_uint32_t *previous_hashp); +isc_uint32_t +isc_hash_function_reverse(const void *data, size_t length, + isc_boolean_t case_sensitive, + const isc_uint32_t *previous_hashp); +/*!< + * \brief Calculate a hash over data. + * + * This hash function is useful for hashtables. The hash function is + * opaque and not important to the caller. The returned hash values are + * non-deterministic and will have different mapping every time a + * process using this library is run, but will have uniform + * distribution. + * + * isc_hash_function() calculates the hash from start to end over the + * input data. isc_hash_function_reverse() calculates the hash from the + * end to the start over the input data. The difference in order is + * useful in incremental hashing; for example, a previously hashed + * value for 'com' can be used as input when hashing 'example.com'. + * + * This is a new variant of isc_hash_calc() and will supercede + * isc_hash_calc() eventually. + * + * 'data' is the data to be hashed. + * + * 'length' is the size of the data to be hashed. + * + * 'case_sensitive' specifies whether the hash key should be treated as + * case_sensitive values. It should typically be ISC_FALSE if the hash key + * is a DNS name. + * + * 'previous_hashp' is a pointer to a previous hash value returned by + * this function. It can be used to perform incremental hashing. NULL + * must be passed during first calls. + */ + ISC_LANG_ENDDECLS #endif /* ISC_HASH_H */ diff --git a/lib/isc/include/isc/magic.h b/lib/isc/include/isc/magic.h index 073de90dcc92..679d9d9233fb 100644 --- a/lib/isc/include/isc/magic.h +++ b/lib/isc/include/isc/magic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -20,6 +20,8 @@ #ifndef ISC_MAGIC_H #define ISC_MAGIC_H 1 +#include <isc/util.h> + /*! \file isc/magic.h */ typedef struct { @@ -33,8 +35,8 @@ typedef struct { * The intent of this is to allow magic numbers to be checked even though * the object is otherwise opaque. */ -#define ISC_MAGIC_VALID(a,b) (((a) != NULL) && \ - (((const isc__magic_t *)(a))->magic == (b))) +#define ISC_MAGIC_VALID(a,b) (ISC_LIKELY((a) != NULL) && \ + ISC_LIKELY(((const isc__magic_t *)(a))->magic == (b))) #define ISC_MAGIC(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 954d77019b69..140d11826dd9 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -155,6 +155,12 @@ isc_netaddr_issitelocal(isc_netaddr_t *na); * Returns #ISC_TRUE if the address is a site local address. */ +isc_boolean_t +isc_netaddr_isnetzero(isc_netaddr_t *na); +/*%< + * Returns #ISC_TRUE if the address is in net zero. + */ + void isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s); /*%< diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index 667a1454a4cd..ae2af287c338 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -288,12 +288,18 @@ @ISC_PLATFORM_HAVEXADDQ@ /* - * If the "atomic swap" operation is available on this architecture, - * ISC_PLATFORM_HAVEATOMICSTORE" will be defined. + * If the 32-bit "atomic swap" operation is available on this + * architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined. */ @ISC_PLATFORM_HAVEATOMICSTORE@ /* + * If the 64-bit "atomic swap" operation is available on this + * architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined. + */ +@ISC_PLATFORM_HAVEATOMICSTOREQ@ + +/* * If the "compare-and-exchange" operation is available on this architecture, * ISC_PLATFORM_HAVECMPXCHG will be defined. */ diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h index ed1bc63e7364..ce881e1a2388 100644 --- a/lib/isc/include/isc/result.h +++ b/lib/isc/include/isc/result.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -89,9 +89,10 @@ #define ISC_R_BADBASE32 60 /*%< bad base32 encoding */ #define ISC_R_UNSET 61 /*%< unset */ #define ISC_R_MULTIPLE 62 /*%< multiple */ +#define ISC_R_WOULDBLOCK 63 /*%< would block */ /*% Not a result code: the number of results. */ -#define ISC_R_NRESULTS 63 +#define ISC_R_NRESULTS 64 ISC_LANG_BEGINDECLS diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h index 4d811dd64971..5dfc3d23f512 100644 --- a/lib/isc/include/isc/sockaddr.h +++ b/lib/isc/include/isc/sockaddr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -220,6 +220,12 @@ isc_sockaddr_issitelocal(const isc_sockaddr_t *sa); * Returns ISC_TRUE if the address is a sitelocal address. */ +isc_boolean_t +isc_sockaddr_isnetzero(const isc_sockaddr_t *sa); +/*%< + * Returns ISC_TRUE if the address is in net zero. + */ + isc_result_t isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path); /* diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 97e2f7605b9c..0ee305c894b4 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2014, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -370,7 +370,8 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, * * Note: * - *\li 'fd' is the already-opened file descriptor. + *\li 'fd' is the already-opened file descriptor (must be less + * than maxsockets). *\li This function is not available on Windows. *\li The callback function is called "in-line" - this means the function * needs to return as fast as possible, as all other I/O will be suspended @@ -394,6 +395,7 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, *\li #ISC_R_NOMEMORY *\li #ISC_R_NORESOURCES *\li #ISC_R_UNEXPECTED + *\li #ISC_R_RANGE */ isc_result_t diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h index 6baf786bdeab..fc2e1882641a 100644 --- a/lib/isc/include/isc/util.h +++ b/lib/isc/include/isc/util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2010-2012, 2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010-2012, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -206,6 +206,17 @@ #define INSERTAFTER(li, a, e, ln) ISC_LIST_INSERTAFTER(li, a, e, ln) #define APPENDLIST(list1, list2, link) ISC_LIST_APPENDLIST(list1, list2, link) +/*% + * Performance + */ +#ifdef HAVE_BUILTIN_EXPECT +#define ISC_LIKELY(x) __builtin_expect(!!(x), 1) +#define ISC_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define ISC_LIKELY(x) (x) +#define ISC_UNLIKELY(x) (x) +#endif + /* * Assertions */ diff --git a/lib/isc/md5.c b/lib/isc/md5.c index 579d61c20b2a..55d56195f48e 100644 --- a/lib/isc/md5.c +++ b/lib/isc/md5.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -57,6 +57,8 @@ isc_md5_invalidate(isc_md5_t *ctx) { void isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) { + if (len == 0U) + return; RUNTIME_CHECK(EVP_DigestUpdate(ctx, (const void *) buf, (size_t) len) == 1); diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 854425750bcd..dfa5e572770b 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2012-2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010, 2012-2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -1987,53 +1987,43 @@ isc___mempool_get(isc_mempool_t *mpctx0 FLARG) { /* * Don't let the caller go over quota */ - if (mpctx->allocated >= mpctx->maxalloc) { + if (ISC_UNLIKELY(mpctx->allocated >= mpctx->maxalloc)) { item = NULL; goto out; } - /* - * if we have a free list item, return the first here - */ - item = mpctx->items; - if (item != NULL) { - mpctx->items = item->next; - INSIST(mpctx->freecount > 0); - mpctx->freecount--; - mpctx->gets++; - mpctx->allocated++; - goto out; - } - - /* - * We need to dip into the well. Lock the memory context here and - * fill up our free list. - */ - MCTXLOCK(mctx, &mctx->lock); - for (i = 0; i < mpctx->fillcount; i++) { - if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { - item = mem_getunlocked(mctx, mpctx->size); - } else { - item = mem_get(mctx, mpctx->size); - if (item != NULL) - mem_getstats(mctx, mpctx->size); + if (ISC_UNLIKELY(mpctx->items == NULL)) { + /* + * We need to dip into the well. Lock the memory context + * here and fill up our free list. + */ + MCTXLOCK(mctx, &mctx->lock); + for (i = 0; i < mpctx->fillcount; i++) { + if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + item = mem_getunlocked(mctx, mpctx->size); + } else { + item = mem_get(mctx, mpctx->size); + if (item != NULL) + mem_getstats(mctx, mpctx->size); + } + if (ISC_UNLIKELY(item == NULL)) + break; + item->next = mpctx->items; + mpctx->items = item; + mpctx->freecount++; } - if (item == NULL) - break; - item->next = mpctx->items; - mpctx->items = item; - mpctx->freecount++; + MCTXUNLOCK(mctx, &mctx->lock); } - MCTXUNLOCK(mctx, &mctx->lock); /* * If we didn't get any items, return NULL. */ item = mpctx->items; - if (item == NULL) + if (ISC_UNLIKELY(item == NULL)) goto out; mpctx->items = item->next; + INSIST(mpctx->freecount > 0); mpctx->freecount--; mpctx->gets++; mpctx->allocated++; diff --git a/lib/isc/mips/include/isc/Makefile.in b/lib/isc/mips/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/mips/include/isc/Makefile.in +++ b/lib/isc/mips/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index dcbfba42eae8..2178c7a2a7b5 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2010-2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2010-2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -419,6 +419,22 @@ isc_netaddr_issitelocal(isc_netaddr_t *na) { } } +#ifndef IN_ZERONET +#define IN_ZERONET(x) (((x) & htonl(0xff000000U)) == 0) +#endif + +isc_boolean_t +isc_netaddr_isnetzero(isc_netaddr_t *na) { + switch (na->family) { + case AF_INET: + return (ISC_TF(IN_ZERONET(na->type.in.s_addr))); + case AF_INET6: + return (ISC_FALSE); + default: + return (ISC_FALSE); + } +} + void isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) { isc_netaddr_t *src; diff --git a/lib/isc/noatomic/include/isc/Makefile.in b/lib/isc/noatomic/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/noatomic/include/isc/Makefile.in +++ b/lib/isc/noatomic/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/nothreads/include/isc/Makefile.in b/lib/isc/nothreads/include/isc/Makefile.in index a2c347eaa253..f32180f3a783 100644 --- a/lib/isc/nothreads/include/isc/Makefile.in +++ b/lib/isc/nothreads/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000, 2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -19,7 +19,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = condition.h mutex.h once.h thread.h diff --git a/lib/isc/powerpc/include/isc/Makefile.in b/lib/isc/powerpc/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/powerpc/include/isc/Makefile.in +++ b/lib/isc/powerpc/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/pthreads/include/isc/Makefile.in b/lib/isc/pthreads/include/isc/Makefile.in index 7cadcf4b6f3d..68e6c76b8d6b 100644 --- a/lib/isc/pthreads/include/isc/Makefile.in +++ b/lib/isc/pthreads/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -19,7 +19,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = condition.h mutex.h once.h thread.h diff --git a/lib/isc/result.c b/lib/isc/result.c index 6cbd8b4722a1..27927e8f25d2 100644 --- a/lib/isc/result.c +++ b/lib/isc/result.c @@ -104,6 +104,7 @@ static const char *description[ISC_R_NRESULTS] = { "bad base32 encoding", /*%< 60 */ "unset", /*%< 61 */ "multiple", /*%< 62 */ + "would block", /*%< 63 */ }; #define ISC_RESULT_RESULTSET 2 diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index cee6d700c02e..195f1c1c739d 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2010-2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010-2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -205,7 +205,6 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { unsigned int length = 0; const unsigned char *s = NULL; unsigned int h = 0; - unsigned int g; unsigned int p = 0; const struct in6_addr *in6; @@ -239,12 +238,9 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { p = 0; } - h = isc_hash_calc(s, length, ISC_TRUE); - if (!address_only) { - g = isc_hash_calc((const unsigned char *)&p, sizeof(p), - ISC_TRUE); - h = h ^ g; /* XXX: we should concatenate h and p first */ - } + h = isc_hash_function(s, length, ISC_TRUE, NULL); + if (!address_only) + h = isc_hash_function(&p, sizeof(p), ISC_TRUE, &h); return (h); } @@ -368,7 +364,7 @@ isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { void isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, - in_port_t port) + in_port_t port) { memset(sockaddr, 0, sizeof(*sockaddr)); sockaddr->type.sin.sin_family = na->family; @@ -483,6 +479,17 @@ isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { return (ISC_FALSE); } +isc_boolean_t +isc_sockaddr_isnetzero(const isc_sockaddr_t *sockaddr) { + isc_netaddr_t netaddr; + + if (sockaddr->type.sa.sa_family == AF_INET) { + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_isnetzero(&netaddr)); + } + return (ISC_FALSE); +} + isc_result_t isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) { #ifdef ISC_PLATFORM_HAVESYSUNH diff --git a/lib/isc/sparc64/include/isc/Makefile.in b/lib/isc/sparc64/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/sparc64/include/isc/Makefile.in +++ b/lib/isc/sparc64/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/stats.c b/lib/isc/stats.c index 03d2a8a7d103..368dadfc323e 100644 --- a/lib/isc/stats.c +++ b/lib/isc/stats.c @@ -35,13 +35,45 @@ #define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't') #define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC) -#ifndef ISC_STATS_USEMULTIFIELDS -#if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEXADD) && !defined(ISC_PLATFORM_HAVEXADDQ) +/*% + * Local macro confirming prescence of 64-bit + * increment and store operations, just to make + * the later macros simpler + */ +#if defined(ISC_PLATFORM_HAVEXADDQ) && defined(ISC_PLATFORM_HAVEATOMICSTOREQ) +#define ISC_STATS_HAVEATOMICQ 1 +#else +#define ISC_STATS_HAVEATOMICQ 0 +#endif + +/*% + * Only lock the counters if 64-bit atomic operations are + * not available but cheap atomic lock operations are. + * On a modern 64-bit system this should never be the case. + * + * Normal locks are too expensive to be used whenever a counter + * is updated. + */ +#if !ISC_STATS_HAVEATOMICQ && defined(ISC_RWLOCK_HAVEATOMIC) +#define ISC_STATS_LOCKCOUNTERS 1 +#else +#define ISC_STATS_LOCKCOUNTERS 0 +#endif + +/*% + * If 64-bit atomic operations are not available but + * 32-bit operations are then split the counter into two, + * using the atomic operations to try to ensure that any carry + * from the low word is correctly carried into the high word. + * + * Otherwise, just rely on standard 64-bit data types + * and operations + */ +#if !ISC_STATS_HAVEATOMICQ && defined(ISC_PLATFORM_HAVEXADD) #define ISC_STATS_USEMULTIFIELDS 1 #else #define ISC_STATS_USEMULTIFIELDS 0 #endif -#endif /* ISC_STATS_USEMULTIFIELDS */ #if ISC_STATS_USEMULTIFIELDS typedef struct { @@ -65,7 +97,7 @@ struct isc_stats { * Locked by counterlock or unlocked if efficient rwlock is not * available. */ -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_t counterlock; #endif isc_stat_t *counters; @@ -111,7 +143,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) { goto clean_counters; } -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS result = isc_rwlock_init(&stats->counterlock, 0, 0); if (result != ISC_R_SUCCESS) goto clean_copiedcounters; @@ -131,7 +163,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) { clean_counters: isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters); -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS clean_copiedcounters: isc_mem_put(mctx, stats->copiedcounters, sizeof(isc_stat_t) * ncounters); @@ -177,7 +209,7 @@ isc_stats_detach(isc_stats_t **statsp) { sizeof(isc_stat_t) * stats->ncounters); UNLOCK(&stats->lock); DESTROYLOCK(&stats->lock); -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_destroy(&stats->counterlock); #endif isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats)); @@ -198,7 +230,7 @@ static inline void incrementcounter(isc_stats_t *stats, int counter) { isc_int32_t prev; -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS /* * We use a "read" lock to prevent other threads from reading the * counter while we "writing" a counter field. The write access itself @@ -219,7 +251,7 @@ incrementcounter(isc_stats_t *stats, int counter) { */ if (prev == (isc_int32_t)0xffffffff) isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi, 1); -#elif defined(ISC_PLATFORM_HAVEXADDQ) +#elif ISC_STATS_HAVEATOMICQ UNUSED(prev); isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], 1); #else @@ -227,7 +259,7 @@ incrementcounter(isc_stats_t *stats, int counter) { stats->counters[counter]++; #endif -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read); #endif } @@ -236,7 +268,7 @@ static inline void decrementcounter(isc_stats_t *stats, int counter) { isc_int32_t prev; -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read); #endif @@ -245,7 +277,7 @@ decrementcounter(isc_stats_t *stats, int counter) { if (prev == 0) isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi, -1); -#elif defined(ISC_PLATFORM_HAVEXADDQ) +#elif ISC_STATS_HAVEATOMICQ UNUSED(prev); isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], -1); #else @@ -253,7 +285,7 @@ decrementcounter(isc_stats_t *stats, int counter) { stats->counters[counter]--; #endif -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read); #endif } @@ -262,7 +294,7 @@ static void copy_counters(isc_stats_t *stats) { int i; -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS /* * We use a "write" lock before "reading" the statistics counters as * an exclusive lock. @@ -270,19 +302,21 @@ copy_counters(isc_stats_t *stats) { isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write); #endif -#if ISC_STATS_USEMULTIFIELDS for (i = 0; i < stats->ncounters; i++) { +#if ISC_STATS_USEMULTIFIELDS stats->copiedcounters[i] = - (isc_uint64_t)(stats->counters[i].hi) << 32 | - stats->counters[i].lo; - } + (isc_uint64_t)(stats->counters[i].hi) << 32 | + stats->counters[i].lo; +#elif ISC_STATS_HAVEATOMICQ + /* use xaddq(..., 0) as an atomic load */ + stats->copiedcounters[i] = + (isc_uint64_t)isc_atomic_xaddq((isc_int64_t *)&stats->counters[i], 0); #else - UNUSED(i); - memmove(stats->copiedcounters, stats->counters, - stats->ncounters * sizeof(isc_stat_t)); + stats->copiedcounters[i] = stats->counters[i]; #endif + } -#ifdef ISC_RWLOCK_USEATOMIC +#if ISC_STATS_LOCKCOUNTERS isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write); #endif } diff --git a/lib/isc/string.c b/lib/isc/string.c index 56ec444bffaa..04a25943734d 100644 --- a/lib/isc/string.c +++ b/lib/isc/string.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -56,14 +56,14 @@ #include <isc/string.h> #include <isc/util.h> -static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; +static const char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; isc_uint64_t isc_string_touint64(char *source, char **end, int base) { isc_uint64_t tmp; isc_uint64_t overflow; char *s = source; - char *o; + const char *o; char c; if ((base < 0) || (base == 1) || (base > 36)) { diff --git a/lib/isc/task.c b/lib/isc/task.c index 3503801e4517..81785e9a835b 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file * \author Principal Author: Bob Halley */ @@ -1638,11 +1636,11 @@ isc__taskmgr_dispatch(isc_taskmgr_t *manager0) { ISC_TASKFUNC_SCOPE void isc__taskmgr_pause(isc_taskmgr_t *manager0) { isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + manager->pause_requested = ISC_TRUE; LOCK(&manager->lock); while (manager->tasks_running > 0) { WAIT(&manager->paused, &manager->lock); } - manager->pause_requested = ISC_TRUE; UNLOCK(&manager->lock); } diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c index c2abd440e18c..3fc2a29125c4 100644 --- a/lib/isc/unix/file.c +++ b/lib/isc/unix/file.c @@ -204,8 +204,9 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen) { isc_result_t isc_file_template(const char *path, const char *templet, char *buf, - size_t buflen) { - char *s; + size_t buflen) +{ + const char *s; REQUIRE(path != NULL); REQUIRE(templet != NULL); @@ -262,7 +263,7 @@ isc_file_renameunique(const char *file, char *templet) { if (errno != EEXIST) return (isc__errno2result(errno)); for (cp = x;;) { - char *t; + const char *t; if (*cp == '\0') return (ISC_R_FAILURE); t = strchr(alphnum, *cp); @@ -461,7 +462,7 @@ isc_file_ischdiridempotent(const char *filename) { const char * isc_file_basename(const char *filename) { - char *s; + const char *s; REQUIRE(filename != NULL); @@ -579,9 +580,11 @@ isc_file_safecreate(const char *filename, FILE **fp) { } isc_result_t -isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename) +isc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname, + char const **basename) { - char *dir, *file, *slash; + char *dir; + const char *file, *slash; if (path == NULL) return (ISC_R_INVALIDFILE); diff --git a/lib/isc/unix/include/isc/Makefile.in b/lib/isc/unix/include/isc/Makefile.in index 9cd96d71b750..f37036ac10ff 100644 --- a/lib/isc/unix/include/isc/Makefile.in +++ b/lib/isc/unix/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007, 2012-2014 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2012-2015 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -19,7 +19,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = dir.h int.h keyboard.h net.h netdb.h offset.h stat.h \ stdtime.h strerror.h syslog.h time.h diff --git a/lib/isc/unix/net.c b/lib/isc/unix/net.c index c811d1ba4194..7ed73aad5b4f 100644 --- a/lib/isc/unix/net.c +++ b/lib/isc/unix/net.c @@ -103,10 +103,10 @@ const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT; # if defined(WANT_IPV6) static isc_once_t once_ipv6only = ISC_ONCE_INIT; -# endif -# if defined(ISC_PLATFORM_HAVEIN6PKTINFO) +# if defined(ISC_PLATFORM_HAVEIN6PKTINFO) static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; +# endif # endif #endif /* ISC_PLATFORM_HAVEIPV6 */ diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 5e6320d821c6..42fc47f6deaa 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -394,6 +394,9 @@ struct isc__socketmgr { /* Locked by fdlock. */ isc__socket_t **fds; int *fdstate; +#if defined(USE_EPOLL) + uint32_t *epoll_events; +#endif #ifdef USE_DEVPOLL pollinfo_t *fdpollinfo; #endif @@ -835,15 +838,27 @@ watch_fd(isc__socketmgr_t *manager, int fd, int msg) { return (result); #elif defined(USE_EPOLL) struct epoll_event event; + uint32_t oldevents; + int ret; + int op; + oldevents = manager->epoll_events[fd]; if (msg == SELECT_POKE_READ) - event.events = EPOLLIN; + manager->epoll_events[fd] |= EPOLLIN; else - event.events = EPOLLOUT; + manager->epoll_events[fd] |= EPOLLOUT; + + event.events = manager->epoll_events[fd]; memset(&event.data, 0, sizeof(event.data)); event.data.fd = fd; - if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 && - errno != EEXIST) { + + op = (oldevents == 0U) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD; + ret = epoll_ctl(manager->epoll_fd, op, fd, &event); + if (ret == -1) { + if (errno == EEXIST) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "epoll_ctl(ADD/MOD) returned " + "EEXIST for fd %d", fd); result = isc__errno2result(errno); } @@ -903,15 +918,21 @@ unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) { return (result); #elif defined(USE_EPOLL) struct epoll_event event; + int ret; + int op; if (msg == SELECT_POKE_READ) - event.events = EPOLLIN; + manager->epoll_events[fd] &= ~(EPOLLIN); else - event.events = EPOLLOUT; + manager->epoll_events[fd] &= ~(EPOLLOUT); + + event.events = manager->epoll_events[fd]; memset(&event.data, 0, sizeof(event.data)); event.data.fd = fd; - if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 && - errno != ENOENT) { + + op = (event.events == 0U) ? EPOLL_CTL_DEL : EPOLL_CTL_MOD; + ret = epoll_ctl(manager->epoll_fd, op, fd, &event); + if (ret == -1 && errno != ENOENT) { char strbuf[ISC_STRERRORSIZE]; isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -1553,15 +1574,19 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, msg->msg_iovlen = iovcount; #ifdef ISC_NET_BSD44MSGHDR - msg->msg_control = NULL; - msg->msg_controllen = 0; - msg->msg_flags = 0; #if defined(USE_CMSG) if (sock->type == isc_sockettype_udp) { msg->msg_control = sock->recvcmsgbuf; msg->msg_controllen = sock->recvcmsgbuflen; + } else { + msg->msg_control = NULL; + msg->msg_controllen = 0; } +#else + msg->msg_control = NULL; + msg->msg_controllen = 0; #endif /* USE_CMSG */ + msg->msg_flags = 0; #else /* ISC_NET_BSD44MSGHDR */ msg->msg_accrights = NULL; msg->msg_accrightslen = 0; @@ -1872,8 +1897,11 @@ doio_send(isc__socket_t *sock, isc_socketevent_t *dev) { if (send_errno == EINTR && ++attempts < NRETRIES) goto resend; - if (SOFT_ERROR(send_errno)) + if (SOFT_ERROR(send_errno)) { + if (errno == EWOULDBLOCK || errno == EAGAIN) + dev->result = ISC_R_WOULDBLOCK; return (DOIO_SOFT); + } #define SOFT_OR_HARD(_system, _isc) \ if (send_errno == _system) { \ @@ -2035,7 +2063,7 @@ destroy(isc__socket_t **sockp) { INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->send_list)); INSIST(sock->connect_ev == NULL); - REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks); + INSIST(sock->fd >= -1 && sock->fd < (int)manager->maxsocks); if (sock->fd >= 0) { fd = sock->fd; @@ -2192,8 +2220,8 @@ static void free_socket(isc__socket_t **socketp) { isc__socket_t *sock = *socketp; - INSIST(sock->references == 0); INSIST(VALID_SOCKET(sock)); + INSIST(sock->references == 0); INSIST(!sock->connecting); INSIST(!sock->pending_recv); INSIST(!sock->pending_send); @@ -2633,6 +2661,9 @@ socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, LOCK(&manager->fdlock[lockid]); manager->fds[sock->fd] = sock; manager->fdstate[sock->fd] = MANAGED; +#if defined(USE_EPOLL) + manager->epoll_events[sock->fd] = 0; +#endif #ifdef USE_DEVPOLL INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 && sock->manager->fdpollinfo[sock->fd].want_write == 0); @@ -2710,6 +2741,9 @@ isc__socket_open(isc_socket_t *sock0) { LOCK(&sock->manager->fdlock[lockid]); sock->manager->fds[sock->fd] = sock; sock->manager->fdstate[sock->fd] = MANAGED; +#if defined(USE_EPOLL) + sock->manager->epoll_events[sock->fd] = 0; +#endif #ifdef USE_DEVPOLL INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 && sock->manager->fdpollinfo[sock->fd].want_write == 0); @@ -2747,6 +2781,9 @@ isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags, REQUIRE(VALID_MANAGER(manager)); REQUIRE(socketp != NULL && *socketp == NULL); + if (fd < 0 || (unsigned int)fd >= manager->maxsocks) + return (ISC_R_RANGE); + result = allocate_socket(manager, isc_sockettype_fdwatch, &sock); if (result != ISC_R_SUCCESS) return (result); @@ -2771,6 +2808,9 @@ isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags, LOCK(&manager->fdlock[lockid]); manager->fds[sock->fd] = sock; manager->fdstate[sock->fd] = MANAGED; +#if defined(USE_EPOLL) + manager->epoll_events[sock->fd] = 0; +#endif UNLOCK(&manager->fdlock[lockid]); LOCK(&manager->lock); @@ -3310,6 +3350,9 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { LOCK(&manager->fdlock[lockid]); manager->fds[fd] = NEWCONNSOCK(dev); manager->fdstate[fd] = MANAGED; +#if defined(USE_EPOLL) + manager->epoll_events[fd] = 0; +#endif UNLOCK(&manager->fdlock[lockid]); LOCK(&manager->lock); @@ -4260,6 +4303,15 @@ isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, result = ISC_R_NOMEMORY; goto free_manager; } +#if defined(USE_EPOLL) + manager->epoll_events = isc_mem_get(mctx, (manager->maxsocks * + sizeof(uint32_t))); + if (manager->epoll_events == NULL) { + result = ISC_R_NOMEMORY; + goto free_manager; + } + memset(manager->epoll_events, 0, manager->maxsocks * sizeof(uint32_t)); +#endif manager->stats = NULL; manager->common.methods = &socketmgrmethods; @@ -4329,7 +4381,9 @@ isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, result = setup_watcher(mctx, manager); if (result != ISC_R_SUCCESS) goto cleanup; + memset(manager->fdstate, 0, manager->maxsocks * sizeof(int)); + #ifdef USE_WATCHER_THREAD /* * Start up the select/poll thread. @@ -4378,6 +4432,12 @@ free_manager: isc_mem_put(mctx, manager->fdlock, FDLOCK_COUNT * sizeof(isc_mutex_t)); } +#if defined(USE_EPOLL) + if (manager->epoll_events != NULL) { + isc_mem_put(mctx, manager->epoll_events, + manager->maxsocks * sizeof(uint32_t)); + } +#endif if (manager->fdstate != NULL) { isc_mem_put(mctx, manager->fdstate, manager->maxsocks * sizeof(int)); @@ -4493,6 +4553,10 @@ isc__socketmgr_destroy(isc_socketmgr_t **managerp) { if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */ (void)close(i); +#if defined(USE_EPOLL) + isc_mem_put(manager->mctx, manager->epoll_events, + manager->maxsocks * sizeof(uint32_t)); +#endif isc_mem_put(manager->mctx, manager->fds, manager->maxsocks * sizeof(isc__socket_t *)); isc_mem_put(manager->mctx, manager->fdstate, diff --git a/lib/isc/x86_32/include/isc/Makefile.in b/lib/isc/x86_32/include/isc/Makefile.in index 4927e210f38e..df7561585b0a 100644 --- a/lib/isc/x86_32/include/isc/Makefile.in +++ b/lib/isc/x86_32/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/x86_32/include/isc/atomic.h b/lib/isc/x86_32/include/isc/atomic.h index bf2148cb33f5..36088e4d53ae 100644 --- a/lib/isc/x86_32/include/isc/atomic.h +++ b/lib/isc/x86_32/include/isc/atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005, 2007, 2008, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -62,7 +62,7 @@ isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) { #endif /* ISC_PLATFORM_HAVEXADDQ */ /* - * This routine atomically stores the value 'val' in 'p'. + * This routine atomically stores the value 'val' in 'p' (32-bit version). */ static __inline__ void isc_atomic_store(isc_int32_t *p, isc_int32_t val) { @@ -81,6 +81,28 @@ isc_atomic_store(isc_int32_t *p, isc_int32_t val) { : "memory"); } +#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ +/* + * This routine atomically stores the value 'val' in 'p' (64-bit version). + */ +static __inline__ void +isc_atomic_storeq(isc_int64_t *p, isc_int64_t val) { + __asm__ volatile( +#ifdef ISC_PLATFORM_USETHREADS + /* + * xchg should automatically lock memory, but we add it + * explicitly just in case (it at least doesn't harm) + */ + "lock;" +#endif + + "xchgq %1, %0" + : + : "r"(val), "m"(*p) + : "memory"); +} +#endif /* ISC_PLATFORM_HAVEATOMICSTOREQ */ + /* * This routine atomically replaces the value in 'p' with 'val', if the * original value is equal to 'cmpval'. The original value is returned in any diff --git a/lib/isc/x86_64/include/isc/Makefile.in b/lib/isc/x86_64/include/isc/Makefile.in index 9a988bb76159..74b7f95cf3ec 100644 --- a/lib/isc/x86_64/include/isc/Makefile.in +++ b/lib/isc/x86_64/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2007, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -@BIND9_VERSION@ +VERSION=@BIND9_VERSION@ HEADERS = atomic.h diff --git a/lib/isc/x86_64/include/isc/atomic.h b/lib/isc/x86_64/include/isc/atomic.h index f57bd2a78672..431600b73c33 100644 --- a/lib/isc/x86_64/include/isc/atomic.h +++ b/lib/isc/x86_64/include/isc/atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005, 2007, 2008, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -87,12 +87,26 @@ isc_atomic_store(isc_int32_t *p, isc_int32_t val) { "lock;" #endif "xchgl (%rax), %edx\n" - /* - * XXX: assume %rax will be used as the return value. - */ ); } +#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ +static void +isc_atomic_storeq(isc_int64_t *p, isc_int64_t val) { + UNUSED(p); + UNUSED(val); + + __asm ( + "movq %rdi, %rax\n" + "movq %rsi, %rdx\n" +#ifdef ISC_PLATFORM_USETHREADS + "lock;" +#endif + "xchgq (%rax), %rdx\n" + ); +} +#endif + static isc_int32_t isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { UNUSED(p); @@ -100,6 +114,9 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { UNUSED(val); __asm ( + /* + * p is %rdi, cmpval is %esi, val is %edx. + */ "movl %edx, %ecx\n" "movl %esi, %eax\n" "movq %rdi, %rdx\n" @@ -108,8 +125,12 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { "lock;" #endif /* - * If (%rdi) == %eax then (%rdi) := %edx. - * %eax is set to old (%ecx), which will be the return value. + * If [%rdi] == %eax then [%rdi] := %ecx (equal to %edx + * from above), and %eax is untouched (equal to %esi) + * from above. + * + * Else if [%rdi] != %eax then [%rdi] := [%rdi] + * (rewritten in write cycle) and %eax := [%rdi]. */ "cmpxchgl %ecx, (%rdx)" ); |
