mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-09 11:32:05 -04:00
Merge branch 'NG-unix-socket-mergable' into 'master'
Rewrite of unix/socket.c code Closes #666 See merge request isc-projects/bind9!987
This commit is contained in:
commit
9f35a59f71
14 changed files with 912 additions and 1384 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
5096. [func] Use multiple event loops in socket code, and
|
||||
make network threads CPU-affinitive. This
|
||||
significantly improves performance on large
|
||||
systems. [GL #666]
|
||||
|
||||
5095. [test] Converted all unit tests from ATF to CMocka;
|
||||
removed the source code for the ATF libraries.
|
||||
Build with "configure --with-cmocka" to enable
|
||||
|
|
|
|||
|
|
@ -793,10 +793,7 @@ create_managers(void) {
|
|||
named_g_udpdisp = 1;
|
||||
#else
|
||||
if (named_g_udpdisp == 0) {
|
||||
if (named_g_cpus_detected == 1)
|
||||
named_g_udpdisp = 1;
|
||||
else
|
||||
named_g_udpdisp = named_g_cpus_detected - 1;
|
||||
named_g_udpdisp = named_g_cpus_detected;
|
||||
}
|
||||
if (named_g_udpdisp > named_g_cpus)
|
||||
named_g_udpdisp = named_g_cpus;
|
||||
|
|
@ -824,7 +821,7 @@ create_managers(void) {
|
|||
}
|
||||
|
||||
result = isc_socketmgr_create2(named_g_mctx, &named_g_socketmgr,
|
||||
maxsocks);
|
||||
maxsocks, named_g_cpus);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_socketmgr_create() failed: %s",
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ status=`expr $status + $ret`
|
|||
copy_setports ns3/named3.conf.in ns3/named.conf
|
||||
$RNDCCMD reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
|
||||
|
||||
echo_i "checking lame server clients are dropped at the soft limit"
|
||||
echo_i "checking lame server clients are dropped near the soft limit"
|
||||
ret=0
|
||||
fail=0
|
||||
exceeded=0
|
||||
|
|
|
|||
|
|
@ -24,28 +24,6 @@ grep "another named process" ns2/named.run > /dev/null && ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
if [ ! "$CYGWIN" ]; then
|
||||
n=`expr $n + 1`
|
||||
echo_i "verifying that named checks for conflicting listeners ($n)"
|
||||
ret=0
|
||||
(cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
|
||||
for i in 1 2 3 4 5 6 7 8 9
|
||||
do
|
||||
grep "unable to listen on any configured interface" ns2/named2.run > /dev/null && break
|
||||
sleep 1
|
||||
done
|
||||
grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
|
||||
for i in 1 2 3 4 5 6 7 8 9
|
||||
do
|
||||
grep "exiting (due to fatal error)" ns2/named2.run > /dev/null && break
|
||||
sleep 1
|
||||
done
|
||||
pid=`cat ns2/named2.pid 2>/dev/null`
|
||||
test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
fi
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "verifying that named checks for conflicting named processes ($n)"
|
||||
ret=0
|
||||
|
|
|
|||
|
|
@ -131,6 +131,15 @@
|
|||
|
||||
<section xml:id="relnotes_features"><info><title>New Features</title></info>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Task manager and socket code have been substantially modified.
|
||||
The manager uses per-cpu queues for tasks and network stack runs
|
||||
multiple event loops in CPU-affinitive threads. This greatly
|
||||
improves performance on large systems, especially when using
|
||||
multi-queue NICs.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A new secondary zone option, <command>mirror</command>,
|
||||
|
|
|
|||
|
|
@ -299,7 +299,8 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
|
|||
isc_socketmgr_t *sockmgr,
|
||||
const isc_sockaddr_t *localaddr,
|
||||
isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket);
|
||||
isc_socket_t *dup_socket,
|
||||
bool duponly);
|
||||
static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
|
||||
isc_socketmgr_t *sockmgr,
|
||||
isc_taskmgr_t *taskmgr,
|
||||
|
|
@ -317,7 +318,7 @@ static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
|
|||
static isc_result_t open_socket(isc_socketmgr_t *mgr,
|
||||
const isc_sockaddr_t *local,
|
||||
unsigned int options, isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket);
|
||||
isc_socket_t *dup_socket, bool duponly);
|
||||
static bool portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
isc_sockaddr_t *sockaddrp);
|
||||
|
||||
|
|
@ -728,7 +729,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
|||
if (portentry != NULL)
|
||||
bindoptions |= ISC_SOCKET_REUSEADDRESS;
|
||||
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
|
||||
NULL);
|
||||
NULL, false);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (portentry == NULL) {
|
||||
portentry = new_portentry(disp, port);
|
||||
|
|
@ -1667,7 +1668,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
|
|||
static isc_result_t
|
||||
open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
|
||||
unsigned int options, isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket)
|
||||
isc_socket_t *dup_socket, bool duponly)
|
||||
{
|
||||
isc_socket_t *sock;
|
||||
isc_result_t result;
|
||||
|
|
@ -1675,12 +1676,16 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
|
|||
sock = *sockp;
|
||||
if (sock != NULL) {
|
||||
result = isc_socket_open(sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
} else if (dup_socket != NULL) {
|
||||
}
|
||||
} else if (dup_socket != NULL &&
|
||||
(!isc_socket_hasreuseport() || duponly))
|
||||
{
|
||||
result = isc_socket_dup(dup_socket, &sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_socket_setname(sock, "dispatcher", NULL);
|
||||
*sockp = sock;
|
||||
|
|
@ -1688,8 +1693,9 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
|
|||
} else {
|
||||
result = isc_socket_create(mgr, isc_sockaddr_pf(local),
|
||||
isc_sockettype_udp, &sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
isc_socket_setname(sock, "dispatcher", NULL);
|
||||
|
|
@ -1699,9 +1705,9 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
|
|||
#endif
|
||||
result = isc_socket_bind(sock, local, options);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (*sockp == NULL)
|
||||
if (*sockp == NULL) {
|
||||
isc_socket_detach(&sock);
|
||||
else {
|
||||
} else {
|
||||
isc_socket_close(sock);
|
||||
}
|
||||
return (result);
|
||||
|
|
@ -2757,7 +2763,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
static isc_result_t
|
||||
get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
||||
isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr,
|
||||
isc_socket_t **sockp, isc_socket_t *dup_socket)
|
||||
isc_socket_t **sockp, isc_socket_t *dup_socket, bool duponly)
|
||||
{
|
||||
unsigned int i, j;
|
||||
isc_socket_t *held[DNS_DISPATCH_HELD];
|
||||
|
|
@ -2795,7 +2801,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
|||
prt = ports[isc_random_uniform(nports)];
|
||||
isc_sockaddr_setport(&localaddr_bound, prt);
|
||||
result = open_socket(sockmgr, &localaddr_bound,
|
||||
0, &sock, NULL);
|
||||
0, &sock, NULL, false);
|
||||
/*
|
||||
* Continue if the port choosen is already in use
|
||||
* or the OS has reserved it.
|
||||
|
|
@ -2816,7 +2822,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
|||
/* Allow to reuse address for non-random ports. */
|
||||
result = open_socket(sockmgr, localaddr,
|
||||
ISC_SOCKET_REUSEADDRESS, &sock,
|
||||
dup_socket);
|
||||
dup_socket, duponly);
|
||||
|
||||
if (result == ISC_R_SUCCESS)
|
||||
*sockp = sock;
|
||||
|
|
@ -2828,7 +2834,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
|||
i = 0;
|
||||
|
||||
for (j = 0; j < 0xffffU; j++) {
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL, false);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto end;
|
||||
else if (portavailable(mgr, sock, NULL))
|
||||
|
|
@ -2872,22 +2878,27 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
dns_dispatch_t *disp;
|
||||
isc_socket_t *sock = NULL;
|
||||
int i = 0;
|
||||
bool duponly = ((attributes & DNS_DISPATCHATTR_CANREUSE) == 0);
|
||||
|
||||
/* This is an attribute needed only at creation time */
|
||||
attributes &= ~DNS_DISPATCHATTR_CANREUSE;
|
||||
/*
|
||||
* dispatch_allocate() checks mgr for us.
|
||||
*/
|
||||
disp = NULL;
|
||||
result = dispatch_allocate(mgr, maxrequests, &disp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
disp->socktype = isc_sockettype_udp;
|
||||
|
||||
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
|
||||
result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock,
|
||||
dup_socket);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
dup_socket, duponly);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto deallocate_dispatch;
|
||||
}
|
||||
|
||||
if (isc_log_wouldlog(dns_lctx, 90)) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
|
@ -2910,35 +2921,42 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
*/
|
||||
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
|
||||
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
|
||||
if (sock != NULL)
|
||||
result = open_socket(sockmgr, localaddr, 0,
|
||||
&sock, NULL, false);
|
||||
if (sock != NULL) {
|
||||
isc_socket_detach(&sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto deallocate_dispatch;
|
||||
}
|
||||
}
|
||||
|
||||
disp->port_table = isc_mem_get(mgr->mctx,
|
||||
sizeof(disp->port_table[0]) *
|
||||
DNS_DISPATCH_PORTTABLESIZE);
|
||||
if (disp->port_table == NULL)
|
||||
if (disp->port_table == NULL) {
|
||||
goto deallocate_dispatch;
|
||||
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
|
||||
}
|
||||
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
|
||||
ISC_LIST_INIT(disp->port_table[i]);
|
||||
}
|
||||
|
||||
result = isc_mempool_create(mgr->mctx, sizeof(dispportentry_t),
|
||||
&disp->portpool);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto deallocate_dispatch;
|
||||
}
|
||||
isc_mempool_setname(disp->portpool, "disp_portpool");
|
||||
isc_mempool_setfreemax(disp->portpool, 128);
|
||||
}
|
||||
disp->socket = sock;
|
||||
disp->local = *localaddr;
|
||||
|
||||
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
|
||||
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
|
||||
disp->ntasks = MAX_INTERNAL_TASKS;
|
||||
else
|
||||
} else {
|
||||
disp->ntasks = 1;
|
||||
}
|
||||
for (i = 0; i < disp->ntasks; i++) {
|
||||
disp->task[i] = NULL;
|
||||
result = isc_task_create(taskmgr, 50, &disp->task[i]);
|
||||
|
|
@ -2970,8 +2988,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
}
|
||||
|
||||
result = isc_mutex_init(&disp->sepool_lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto kill_sepool;
|
||||
}
|
||||
|
||||
isc_mempool_setname(disp->sepool, "disp_sepool");
|
||||
isc_mempool_setmaxalloc(disp->sepool, 32768);
|
||||
|
|
@ -2990,8 +3009,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
|
||||
mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
|
||||
dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */
|
||||
if (disp->socket != NULL)
|
||||
if (disp->socket != NULL) {
|
||||
dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
|
||||
}
|
||||
|
||||
*dispp = disp;
|
||||
|
||||
|
|
@ -3005,11 +3025,13 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
kill_ctlevent:
|
||||
isc_event_free(&disp->ctlevent);
|
||||
kill_task:
|
||||
for (i = 0; i < disp->ntasks; i++)
|
||||
for (i = 0; i < disp->ntasks; i++) {
|
||||
isc_task_detach(&disp->task[i]);
|
||||
}
|
||||
kill_socket:
|
||||
if (disp->socket != NULL)
|
||||
if (disp->socket != NULL) {
|
||||
isc_socket_detach(&disp->socket);
|
||||
}
|
||||
deallocate_dispatch:
|
||||
dispatch_free(&disp);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ struct dns_dispatchset {
|
|||
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
|
||||
#define DNS_DISPATCHATTR_FIXEDID 0x00000100U
|
||||
#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
|
||||
#define DNS_DISPATCHATTR_CANREUSE 0x00000400U
|
||||
/*@}*/
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -243,8 +243,7 @@ typedef enum {
|
|||
isc_sockettype_udp = 1,
|
||||
isc_sockettype_tcp = 2,
|
||||
isc_sockettype_unix = 3,
|
||||
isc_sockettype_fdwatch = 4,
|
||||
isc_sockettype_raw = 5
|
||||
isc_sockettype_raw = 4
|
||||
} isc_sockettype_t;
|
||||
|
||||
/*@{*/
|
||||
|
|
@ -275,14 +274,6 @@ typedef enum {
|
|||
#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */
|
||||
/*@}*/
|
||||
|
||||
/*@{*/
|
||||
/*!
|
||||
* Flags for fdwatchcreate.
|
||||
*/
|
||||
#define ISC_SOCKFDWATCH_READ 0x00000001 /*%< watch for readable */
|
||||
#define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */
|
||||
/*@}*/
|
||||
|
||||
/*%
|
||||
* This structure is actually just the common prefix of a socket manager
|
||||
* object implementation's version of an isc_socketmgr_t.
|
||||
|
|
@ -329,76 +320,6 @@ struct isc_socket {
|
|||
*** those functions which return an isc_result.
|
||||
***/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
|
||||
int fd,
|
||||
int flags,
|
||||
isc_sockfdwatch_t callback,
|
||||
void *cbarg,
|
||||
isc_task_t *task,
|
||||
isc_socket_t **socketp);
|
||||
/*%<
|
||||
* Create a new file descriptor watch socket managed by 'manager'.
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
*\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
|
||||
* until the callback completes.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'manager' is a valid manager
|
||||
*
|
||||
*\li 'socketp' is a valid pointer, and *socketp == NULL
|
||||
*
|
||||
*\li 'fd' be opened.
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
* '*socketp' is attached to the newly created fdwatch socket
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_NOMEMORY
|
||||
*\li #ISC_R_NORESOURCES
|
||||
*\li #ISC_R_UNEXPECTED
|
||||
*\li #ISC_R_RANGE
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_fdwatchpoke(isc_socket_t *sock,
|
||||
int flags);
|
||||
/*%<
|
||||
* Poke a file descriptor watch socket informing the manager that it
|
||||
* should restart watching the socket
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
*\li 'sock' is the socket returned by isc_socket_fdwatchcreate
|
||||
*
|
||||
*\li 'flags' indicates what the manager should watch for on the socket
|
||||
* in addition to what it may already be watching. It can be one or
|
||||
* both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE. To
|
||||
* temporarily disable watching on a socket the value indicating
|
||||
* no more data should be returned from the call back routine.
|
||||
*
|
||||
*\li This function is not available on Windows.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'sock' is a valid isc socket
|
||||
*
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_create(isc_socketmgr_t *manager,
|
||||
int pf,
|
||||
|
|
@ -407,9 +328,6 @@ isc_socket_create(isc_socketmgr_t *manager,
|
|||
/*%<
|
||||
* Create a new 'type' socket managed by 'manager'.
|
||||
*
|
||||
* For isc_sockettype_fdwatch sockets you should use isc_socket_fdwatchcreate()
|
||||
* rather than isc_socket_create().
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
*\li 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
|
||||
|
|
@ -420,8 +338,6 @@ isc_socket_create(isc_socketmgr_t *manager,
|
|||
*
|
||||
*\li 'socketp' is a valid pointer, and *socketp == NULL
|
||||
*
|
||||
*\li 'type' is not isc_sockettype_fdwatch
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
* '*socketp' is attached to the newly created socket
|
||||
|
|
@ -551,17 +467,12 @@ isc_socket_open(isc_socket_t *sock);
|
|||
* one. This optimization may not be available for some systems, in which
|
||||
* case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
|
||||
*
|
||||
* isc_socket_open() should not be called on sockets created by
|
||||
* isc_socket_fdwatchcreate().
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li there must be no other reference to this socket.
|
||||
*
|
||||
* \li 'socket' is a valid and previously closed by isc_socket_close()
|
||||
*
|
||||
* \li 'sock->type' is not isc_sockettype_fdwatch
|
||||
*
|
||||
* Returns:
|
||||
* Same as isc_socket_create().
|
||||
* \li ISC_R_NOTIMPLEMENTED
|
||||
|
|
@ -577,9 +488,6 @@ isc_socket_close(isc_socket_t *sock);
|
|||
* systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
|
||||
* must not be used.
|
||||
*
|
||||
* isc_socket_close() should not be called on sockets created by
|
||||
* isc_socket_fdwatchcreate().
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li The socket must have a valid descriptor.
|
||||
|
|
@ -588,8 +496,6 @@ isc_socket_close(isc_socket_t *sock);
|
|||
*
|
||||
* \li There must be no pending I/O requests.
|
||||
*
|
||||
* \li 'sock->type' is not isc_sockettype_fdwatch
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_NOTIMPLEMENTED
|
||||
*/
|
||||
|
|
@ -907,7 +813,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
|
|||
|
||||
isc_result_t
|
||||
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
|
||||
unsigned int maxsocks);
|
||||
unsigned int maxsocks, int nthreads);
|
||||
/*%<
|
||||
* Create a socket manager. If "maxsocks" is non-zero, it specifies the
|
||||
* maximum number of sockets that the created manager should handle.
|
||||
|
|
@ -1104,6 +1010,12 @@ isc_socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp);
|
|||
* Test interface. Drop UDP packet > 'maxudp'.
|
||||
*/
|
||||
|
||||
bool
|
||||
isc_socket_hasreuseport(void);
|
||||
/*%<
|
||||
* Return true if there is SO_REUSEPORT support
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
int
|
||||
isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ isc_thread_setaffinity(int cpu) {
|
|||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(cpu, &cpuset);
|
||||
if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
|
||||
&cpuset, sizeof(cpuset)) != 0) {
|
||||
sizeof(cpuset), &cpuset) != 0)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||
|
|
@ -118,7 +119,8 @@ isc_thread_setaffinity(int cpu) {
|
|||
CPU_ZERO(&set);
|
||||
CPU_SET(cpu, &set);
|
||||
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t),
|
||||
&set) != 0) {
|
||||
&set) != 0)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#elif defined(HAVE_PROCESSOR_BIND)
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ wake_all_queues(isc__taskmgr_t *manager);
|
|||
|
||||
static inline void
|
||||
wake_all_queues(isc__taskmgr_t *manager) {
|
||||
for (unsigned i=0; i < manager->workers; i++) {
|
||||
for (unsigned int i = 0; i < manager->workers; i++) {
|
||||
LOCK(&manager->queues[i].lock);
|
||||
BROADCAST(&manager->queues[i].work_available);
|
||||
UNLOCK(&manager->queues[i].lock);
|
||||
|
|
@ -379,8 +379,9 @@ task_ready(isc__task_t *task) {
|
|||
XTRACE("task_ready");
|
||||
LOCK(&manager->queues[task->threadid].lock);
|
||||
push_readyq(manager, task, task->threadid);
|
||||
if (manager->mode == isc_taskmgrmode_normal || has_privilege)
|
||||
if (manager->mode == isc_taskmgrmode_normal || has_privilege) {
|
||||
SIGNAL(&manager->queues[task->threadid].work_available);
|
||||
}
|
||||
UNLOCK(&manager->queues[task->threadid].lock);
|
||||
}
|
||||
|
||||
|
|
@ -898,16 +899,18 @@ static inline isc__task_t *
|
|||
pop_readyq(isc__taskmgr_t *manager, int c) {
|
||||
isc__task_t *task;
|
||||
|
||||
if (manager->mode == isc_taskmgrmode_normal)
|
||||
if (manager->mode == isc_taskmgrmode_normal) {
|
||||
task = HEAD(manager->queues[c].ready_tasks);
|
||||
else
|
||||
} else {
|
||||
task = HEAD(manager->queues[c].ready_priority_tasks);
|
||||
}
|
||||
|
||||
if (task != NULL) {
|
||||
DEQUEUE(manager->queues[c].ready_tasks, task, ready_link);
|
||||
if (ISC_LINK_LINKED(task, ready_priority_link))
|
||||
if (ISC_LINK_LINKED(task, ready_priority_link)) {
|
||||
DEQUEUE(manager->queues[c].ready_priority_tasks, task,
|
||||
ready_priority_link);
|
||||
}
|
||||
}
|
||||
|
||||
return (task);
|
||||
|
|
@ -922,9 +925,10 @@ pop_readyq(isc__taskmgr_t *manager, int c) {
|
|||
static inline void
|
||||
push_readyq(isc__taskmgr_t *manager, isc__task_t *task, int c) {
|
||||
ENQUEUE(manager->queues[c].ready_tasks, task, ready_link);
|
||||
if ((task->flags & TASK_F_PRIVILEGED) != 0)
|
||||
if ((task->flags & TASK_F_PRIVILEGED) != 0) {
|
||||
ENQUEUE(manager->queues[c].ready_priority_tasks, task,
|
||||
ready_priority_link);
|
||||
}
|
||||
atomic_fetch_add_explicit(&manager->tasks_ready, 1,
|
||||
memory_order_acquire);
|
||||
}
|
||||
|
|
@ -1001,19 +1005,26 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
|||
* If a pause has been requested, don't do any work
|
||||
* until it's been released.
|
||||
*/
|
||||
while ((empty_readyq(manager, threadid) && !manager->pause_requested &&
|
||||
!manager->exclusive_requested) && !FINISHED(manager))
|
||||
while ((empty_readyq(manager, threadid) &&
|
||||
!manager->pause_requested &&
|
||||
!manager->exclusive_requested) &&
|
||||
!FINISHED(manager))
|
||||
{
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
|
||||
ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_WAIT, "wait"));
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
|
||||
ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_WAIT, manager->pause_requested ? "paused" : "notpaused"));
|
||||
ISC_MSG_WAIT,
|
||||
manager->pause_requested
|
||||
? "paused" : "notpaused"));
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
|
||||
ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_WAIT, manager->exclusive_requested ? "excreq" : "notexcreq"));
|
||||
WAIT(&manager->queues[threadid].work_available, &manager->queues[threadid].lock);
|
||||
ISC_MSG_WAIT,
|
||||
manager->exclusive_requested
|
||||
? "excreq" : "notexcreq"));
|
||||
WAIT(&manager->queues[threadid].work_available,
|
||||
&manager->queues[threadid].lock);
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
|
||||
ISC_MSGSET_TASK,
|
||||
ISC_MSG_AWAKE, "awake"));
|
||||
|
|
@ -1027,19 +1038,24 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
|||
ISC_MSG_WORKING, "halting"));
|
||||
|
||||
/*
|
||||
* Switching to exclusive mode is done as a 2-phase-lock,
|
||||
* checking if we have to switch is done without any locks
|
||||
* on pause_requested and exclusive_requested to save time -
|
||||
* the worst thing that can happen is that we'll launch one task
|
||||
* more and exclusive task will be postponed a bit.
|
||||
* Switching to exclusive mode is done as a
|
||||
* 2-phase-lock, checking if we have to switch is
|
||||
* done without any locks on pause_requested and
|
||||
* exclusive_requested to save time - the worst
|
||||
* thing that can happen is that we'll launch one
|
||||
* task more and exclusive task will be postponed a
|
||||
* bit.
|
||||
*
|
||||
* Broadcasting on halt_cond seems suboptimal, but exclusive tasks
|
||||
* are rare enought that we don't care.
|
||||
* Broadcasting on halt_cond seems suboptimal, but
|
||||
* exclusive tasks are rare enought that we don't
|
||||
* care.
|
||||
*/
|
||||
LOCK(&manager->halt_lock);
|
||||
manager->halted++;
|
||||
BROADCAST(&manager->halt_cond);
|
||||
while (manager->pause_requested || manager->exclusive_requested) {
|
||||
while (manager->pause_requested ||
|
||||
manager->exclusive_requested)
|
||||
{
|
||||
WAIT(&manager->halt_cond, &manager->halt_lock);
|
||||
}
|
||||
manager->halted--;
|
||||
|
|
@ -1067,8 +1083,9 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
|||
* lock before exiting the 'if (task != NULL)' block.
|
||||
*/
|
||||
UNLOCK(&manager->queues[threadid].lock);
|
||||
RUNTIME_CHECK(atomic_fetch_sub_explicit(&manager->tasks_ready,
|
||||
1, memory_order_release) > 0);
|
||||
RUNTIME_CHECK(
|
||||
atomic_fetch_sub_explicit(&manager->tasks_ready,
|
||||
1, memory_order_release) > 0);
|
||||
atomic_fetch_add_explicit(&manager->tasks_running, 1,
|
||||
memory_order_acquire);
|
||||
|
||||
|
|
@ -1184,7 +1201,8 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
|||
if (finished)
|
||||
task_finished(task);
|
||||
|
||||
RUNTIME_CHECK(atomic_fetch_sub_explicit(&manager->tasks_running,
|
||||
RUNTIME_CHECK(
|
||||
atomic_fetch_sub_explicit(&manager->tasks_running,
|
||||
1, memory_order_release) > 0);
|
||||
LOCK(&manager->queues[threadid].lock);
|
||||
if (requeue) {
|
||||
|
|
@ -1236,7 +1254,7 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
|||
{
|
||||
bool empty = true;
|
||||
unsigned int i;
|
||||
for (i=0; i<manager->workers && empty; i++)
|
||||
for (i = 0; i < manager->workers && empty; i++)
|
||||
{
|
||||
LOCK(&manager->queues[i].lock);
|
||||
empty &= empty_readyq(manager, i);
|
||||
|
|
@ -1286,7 +1304,7 @@ run(void *queuep) {
|
|||
|
||||
static void
|
||||
manager_free(isc__taskmgr_t *manager) {
|
||||
for (unsigned int i=0; i < manager->workers; i++) {
|
||||
for (unsigned int i = 0; i < manager->workers; i++) {
|
||||
DESTROYLOCK(&manager->queues[i].lock);
|
||||
}
|
||||
DESTROYLOCK(&manager->lock);
|
||||
|
|
@ -1321,19 +1339,17 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
|||
RUNTIME_CHECK(isc_mutex_init(&manager->lock) == ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_mutex_init(&manager->excl_lock) == ISC_R_SUCCESS);
|
||||
|
||||
RUNTIME_CHECK(isc_mutex_init(&manager->halt_lock)
|
||||
== ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_condition_init(&manager->halt_cond)
|
||||
== ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_mutex_init(&manager->halt_lock) == ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_condition_init(&manager->halt_cond) == ISC_R_SUCCESS);
|
||||
|
||||
manager->workers = workers;
|
||||
|
||||
if (default_quantum == 0)
|
||||
if (default_quantum == 0) {
|
||||
default_quantum = DEFAULT_DEFAULT_QUANTUM;
|
||||
}
|
||||
manager->default_quantum = default_quantum;
|
||||
INIT_LIST(manager->tasks);
|
||||
manager->queues = isc_mem_get(mctx, workers *
|
||||
sizeof(isc__taskqueue_t));
|
||||
manager->queues = isc_mem_get(mctx, workers * sizeof(isc__taskqueue_t));
|
||||
RUNTIME_CHECK(manager->queues != NULL);
|
||||
|
||||
manager->tasks_running = 0;
|
||||
|
|
@ -1357,7 +1373,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
|||
RUNTIME_CHECK(isc_mutex_init(&manager->queues[i].lock)
|
||||
== ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_condition_init(
|
||||
&manager->queues[i].work_available)
|
||||
&manager->queues[i].work_available)
|
||||
== ISC_R_SUCCESS);
|
||||
manager->queues[i].manager = manager;
|
||||
manager->queues[i].threadid = i;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -78,6 +78,7 @@ isc_socket_getpeername
|
|||
isc_socket_getsockname
|
||||
isc_socket_gettag
|
||||
isc_socket_gettype
|
||||
isc_socket_hasreuseport
|
||||
isc_socket_ipv6only
|
||||
isc_socket_listen
|
||||
isc_socket_open
|
||||
|
|
|
|||
|
|
@ -508,8 +508,6 @@ iocompletionport_init(isc_socketmgr_t *manager) {
|
|||
strbuf);
|
||||
}
|
||||
|
||||
manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
|
||||
|
||||
/* Now Create the Completion Port */
|
||||
manager->hIoCompletionPort = CreateIoCompletionPort(
|
||||
INVALID_HANDLE_VALUE, NULL,
|
||||
|
|
@ -1551,7 +1549,6 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
|||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
REQUIRE(socketp != NULL && *socketp == NULL);
|
||||
REQUIRE(type != isc_sockettype_fdwatch);
|
||||
|
||||
#ifndef SOCK_RAW
|
||||
if (type == isc_sockettype_raw)
|
||||
|
|
@ -1757,7 +1754,6 @@ isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
|
|||
isc_result_t
|
||||
isc_socket_open(isc_socket_t *sock) {
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(sock->type != isc_sockettype_fdwatch);
|
||||
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
|
@ -1789,7 +1785,6 @@ isc_socket_detach(isc_socket_t **socketp) {
|
|||
REQUIRE(socketp != NULL);
|
||||
sock = *socketp;
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(sock->type != isc_sockettype_fdwatch);
|
||||
|
||||
LOCK(&sock->lock);
|
||||
CONSISTENT(sock);
|
||||
|
|
@ -1815,7 +1810,6 @@ isc_socket_detach(isc_socket_t **socketp) {
|
|||
isc_result_t
|
||||
isc_socket_close(isc_socket_t *sock) {
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(sock->type != isc_sockettype_fdwatch);
|
||||
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
|
@ -2542,7 +2536,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
|
|||
|
||||
isc_result_t
|
||||
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
|
||||
unsigned int maxsocks)
|
||||
unsigned int maxsocks, int nthreads)
|
||||
{
|
||||
isc_socketmgr_t *manager;
|
||||
isc_result_t result;
|
||||
|
|
@ -2578,6 +2572,10 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
|
|||
}
|
||||
|
||||
isc_mem_attach(mctx, &manager->mctx);
|
||||
if (nthreads == 0) {
|
||||
nthreads = isc_os_ncpus() + 1;
|
||||
}
|
||||
manager->maxIOCPThreads = min(nthreads, MAX_IOCPTHREADS);
|
||||
|
||||
iocompletionport_init(manager); /* Create the Completion Ports */
|
||||
|
||||
|
|
@ -2903,7 +2901,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||
isc_result_t ret;
|
||||
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(sock->type != isc_sockettype_fdwatch);
|
||||
|
||||
LOCK(&sock->lock);
|
||||
CONSISTENT(sock);
|
||||
|
|
@ -3696,20 +3693,25 @@ isc_socket_socketevent(isc_mem_t *mctx, void *sender,
|
|||
return (allocate_socketevent(mctx, sender, eventtype, action, arg));
|
||||
}
|
||||
|
||||
bool
|
||||
isc_socket_hasreuseport() {
|
||||
return (false);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
|
||||
static const char *
|
||||
_socktype(isc_sockettype_t type) {
|
||||
if (type == isc_sockettype_udp)
|
||||
switch (type) {
|
||||
case isc_sockettype_udp:
|
||||
return ("udp");
|
||||
else if (type == isc_sockettype_tcp)
|
||||
case isc_sockettype_tcp:
|
||||
return ("tcp");
|
||||
else if (type == isc_sockettype_unix)
|
||||
case isc_sockettype_unix:
|
||||
return ("unix");
|
||||
else if (type == isc_sockettype_fdwatch)
|
||||
return ("fdwatch");
|
||||
else
|
||||
default:
|
||||
return ("not-initialized");
|
||||
}
|
||||
}
|
||||
|
||||
#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
|
||||
|
|
|
|||
|
|
@ -470,6 +470,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
|||
else
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
attrs |= DNS_DISPATCHATTR_NOLISTEN;
|
||||
attrs |= DNS_DISPATCHATTR_CANREUSE;
|
||||
attrmask = 0;
|
||||
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
|
||||
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
|
||||
|
|
|
|||
Loading…
Reference in a new issue