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:
Witold Krecicki 2018-11-15 06:35:47 -05:00
commit 9f35a59f71
14 changed files with 912 additions and 1384 deletions

View file

@ -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

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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>,

View file

@ -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);

View file

@ -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
/*@}*/
/*

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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;