Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/mpl/bind/dist/lib/isc graft back the fdwatch crap t...



details:   https://anonhg.NetBSD.org/src/rev/989c6c30e2e2
branches:  trunk
changeset: 838638:989c6c30e2e2
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Jan 27 01:51:00 2019 +0000

description:
graft back the fdwatch crap that dhcpd needs.

diffstat:

 external/mpl/bind/dist/lib/isc/include/isc/socket.h |   81 ++++-
 external/mpl/bind/dist/lib/isc/unix/socket.c        |  351 +++++++++++++++++++-
 2 files changed, 424 insertions(+), 8 deletions(-)

diffs (truncated from 608 to 300 lines):

diff -r c48ca3651d89 -r 989c6c30e2e2 external/mpl/bind/dist/lib/isc/include/isc/socket.h
--- a/external/mpl/bind/dist/lib/isc/include/isc/socket.h       Sat Jan 26 18:33:53 2019 +0000
+++ b/external/mpl/bind/dist/lib/isc/include/isc/socket.h       Sun Jan 27 01:51:00 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: socket.h,v 1.3 2019/01/09 16:55:15 christos Exp $      */
+/*     $NetBSD: socket.h,v 1.4 2019/01/27 01:51:00 christos Exp $      */
 
 /*
  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
@@ -245,7 +245,8 @@
        isc_sockettype_udp = 1,
        isc_sockettype_tcp = 2,
        isc_sockettype_unix = 3,
-       isc_sockettype_raw = 4
+       isc_sockettype_raw = 4,
+       isc_sockettype_fdwatch = 5
 } isc_sockettype_t;
 
 /*@{*/
@@ -1039,6 +1040,82 @@
  */
 typedef isc_result_t
 (*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+/*!
+ * Flags for fdwatchcreate.
+ */
+#define ISC_SOCKFDWATCH_READ   0x00000001      /*%< watch for readable */
+#define ISC_SOCKFDWATCH_WRITE  0x00000002      /*%< watch for writable */
+/*@}*/
+
+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_LANG_ENDDECLS
 
diff -r c48ca3651d89 -r 989c6c30e2e2 external/mpl/bind/dist/lib/isc/unix/socket.c
--- a/external/mpl/bind/dist/lib/isc/unix/socket.c      Sat Jan 26 18:33:53 2019 +0000
+++ b/external/mpl/bind/dist/lib/isc/unix/socket.c      Sun Jan 27 01:51:00 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: socket.c,v 1.4 2019/01/09 16:55:17 christos Exp $      */
+/*     $NetBSD: socket.c,v 1.5 2019/01/27 01:51:00 christos Exp $      */
 
 /*
  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
@@ -351,6 +351,14 @@
        char                            name[16];
        void *                          tag;
 
+       /*
+        * Internal events.  Posted when a descriptor is readable or
+        * writable.  These are statically allocated and never freed.
+        * They will be set to non-purgable before use.
+        */
+       intev_t                 readable_ev;
+       intev_t                 writable_ev;
+
        ISC_LIST(isc_socketevent_t)             send_list;
        ISC_LIST(isc_socketevent_t)             recv_list;
        ISC_LIST(isc_socket_newconnev_t)        accept_list;
@@ -358,7 +366,9 @@
 
        isc_sockaddr_t          peer_address;       /* remote address */
 
-       unsigned int            listener : 1,       /* listener socket */
+       unsigned int            pending_recv : 1,
+                               pending_send : 1,
+                               listener : 1,       /* listener socket */
                                connected : 1,
                                connecting : 1,     /* connect pending */
                                bound : 1,          /* bound to local addr */
@@ -370,6 +380,10 @@
        unsigned char           overflow; /* used for MSG_TRUNC fake */
 #endif
 
+        void                    *fdwatcharg;    
+        isc_sockfdwatch_t       fdwatchcb;
+        int                     fdwatchflags;
+        isc_task_t              *fdwatchtask;
        unsigned int            dscp;
 };
 
@@ -460,6 +474,8 @@
 static void internal_connect(isc__socket_t *);
 static void internal_recv(isc__socket_t *);
 static void internal_send(isc__socket_t *);
+static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
+static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
 static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
 static void build_msghdr_send(isc__socket_t *, char *, isc_socketevent_t *,
                              struct msghdr *, struct iovec *, size_t *);
@@ -1609,6 +1625,7 @@
        case isc_sockettype_udp:
        case isc_sockettype_raw:
                break;
+       case isc_sockettype_fdwatch:
        default:
                INSIST(0);
                ISC_UNREACHABLE();
@@ -1816,9 +1833,26 @@
         */
        LOCK(&thread->fdlock[lockid]);
        thread->fds[fd] = NULL;
-       thread->fdstate[fd] = CLOSE_PENDING;
+       if (sock->type == isc_sockettype_fdwatch)
+               thread->fdstate[fd] = CLOSED;
+       else
+               thread->fdstate[fd] = CLOSE_PENDING;
        UNLOCK(&thread->fdlock[lockid]);
-       select_poke(thread->manager, thread->threadid, fd, SELECT_POKE_CLOSE);
+       if (sock->type == isc_sockettype_fdwatch) {
+               /*
+                * The caller may close the socket once this function returns,
+                * and `fd' may be reassigned for a new socket.  So we do
+                * unwatch_fd() here, rather than defer it via select_poke().
+                * Note: this may complicate data protection among threads and
+                * may reduce performance due to additional locks.  One way to
+                * solve this would be to dup() the watched descriptor, but we
+                * take a simpler approach at this moment.
+                */
+               (void)unwatch_fd(thread, fd, SELECT_POKE_READ);
+               (void)unwatch_fd(thread, fd, SELECT_POKE_WRITE);
+       } else
+               select_poke(thread->manager, thread->threadid, fd,
+                   SELECT_POKE_CLOSE);
 
        inc_stats(thread->manager->stats, sock->statsindex[STATID_CLOSE]);
        if (sock->active == 1) {
@@ -1928,6 +1962,8 @@
        ISC_LIST_INIT(sock->accept_list);
        ISC_LIST_INIT(sock->connect_list);
        sock->listener = 0;
+       sock->pending_recv = 0;
+       sock->pending_send = 0;
        sock->connected = 0;
        sock->connecting = 0;
        sock->bound = 0;
@@ -1938,6 +1974,16 @@
         */
        isc_mutex_init(&sock->lock);
 
+       /*
+        * Initialize readable and writable events.
+        */
+       ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t),
+                      ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR,
+                      NULL, sock, sock, NULL, NULL);
+       ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t),
+                      ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
+                      NULL, sock, sock, NULL, NULL);
+
        sock->common.magic = ISCAPI_SOCKET_MAGIC;
        sock->common.impmagic = SOCKET_MAGIC;
        *socketp = sock;
@@ -1959,6 +2005,8 @@
        INSIST(VALID_SOCKET(sock));
        INSIST(isc_refcount_current(&sock->references) == 0);
        INSIST(!sock->connecting);
+       INSIST(!sock->pending_recv);
+       INSIST(!sock->pending_send);
        INSIST(ISC_LIST_EMPTY(sock->recv_list));
        INSIST(ISC_LIST_EMPTY(sock->send_list));
        INSIST(ISC_LIST_EMPTY(sock->accept_list));
@@ -2226,6 +2274,13 @@
                        }
 #endif
                        break;
+               case isc_sockettype_fdwatch:
+                       /*
+                        * We should not be called for isc_sockettype_fdwatch
+                        * sockets.
+                        */
+                       INSIST(0);
+                       break;
                }
        } else {
                sock->fd = dup(dup_socket->fd);
@@ -2560,6 +2615,7 @@
 
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(socketp != NULL && *socketp == NULL);
+       REQUIRE(type != isc_sockettype_fdwatch);
 
        result = allocate_socket(manager, type, &sock);
        if (result != ISC_R_SUCCESS)
@@ -2680,6 +2736,7 @@
         */
        REQUIRE(sock->fd == -1);
        REQUIRE(sock->threadid == -1);
+       REQUIRE(sock->type != isc_sockettype_fdwatch);
 
        result = opensocket(sock->manager, sock, NULL);
        if (result != ISC_R_SUCCESS) {
@@ -2759,9 +2816,12 @@
 
        LOCK(&sock->lock);
 
+       REQUIRE(sock->type != isc_sockettype_fdwatch);
        REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
 
        INSIST(!sock->connecting);
+       INSIST(!sock->pending_recv);
+       INSIST(!sock->pending_send);
        INSIST(ISC_LIST_EMPTY(sock->recv_list));
        INSIST(ISC_LIST_EMPTY(sock->send_list));
        INSIST(ISC_LIST_EMPTY(sock->accept_list));
@@ -2790,6 +2850,67 @@
 }
 
 /*
+ * I/O is possible on a given socket.  Schedule an event to this task that
+ * will call an internal function to do the I/O.  This will charge the
+ * task with the I/O operation and let our select loop handler get back
+ * to doing something real as fast as possible.
+ *
+ * The socket and manager must be locked before calling this function.
+ */
+static void
+dispatch_recv(isc__socket_t *sock) {
+       intev_t *iev;
+       isc_task_t *sender;
+
+       if (sock->type != isc_sockettype_fdwatch) {
+               internal_recv(sock);
+               return;
+       }
+#if 0
+       INSIST(!sock->pending_recv);
+#else
+       // XXX: locking
+       if (sock->pending_recv)
+               return;
+#endif
+



Home | Main Index | Thread Index | Old Index