diff options
author | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2016-04-28 00:01:16 +0200 |
---|---|---|
committer | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2016-04-28 00:01:16 +0200 |
commit | acbd8675a283a51a409991ac1393294c9af726e7 (patch) | |
tree | 01fa0ca4b463fd84edb3d3fbe2751ad76229b9d9 /src/core/iomgr | |
parent | 23df75a97054822e1a7f89ab5a0601d6bd4b3aa6 (diff) | |
parent | cec42984a0374465de9b2626f16b0efa960a66d0 (diff) |
Merge branch 'master' of https://github.com/grpc/grpc into what-the-fuzz
Diffstat (limited to 'src/core/iomgr')
76 files changed, 0 insertions, 11111 deletions
diff --git a/src/core/iomgr/closure.c b/src/core/iomgr/closure.c deleted file mode 100644 index 3a96f7385f..0000000000 --- a/src/core/iomgr/closure.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/closure.h" - -#include <grpc/support/alloc.h> - -void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, - void *cb_arg) { - closure->cb = cb; - closure->cb_arg = cb_arg; - closure->final_data = 0; -} - -void grpc_closure_list_add(grpc_closure_list *closure_list, - grpc_closure *closure, bool success) { - if (closure == NULL) return; - closure->final_data = (success != 0); - if (closure_list->head == NULL) { - closure_list->head = closure; - } else { - closure_list->tail->final_data |= (uintptr_t)closure; - } - closure_list->tail = closure; -} - -bool grpc_closure_list_empty(grpc_closure_list closure_list) { - return closure_list.head == NULL; -} - -void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) { - if (src->head == NULL) { - return; - } - if (dst->head == NULL) { - *dst = *src; - } else { - dst->tail->final_data |= (uintptr_t)src->head; - dst->tail = src->tail; - } - src->head = src->tail = NULL; -} - -typedef struct { - grpc_iomgr_cb_func cb; - void *cb_arg; - grpc_closure wrapper; -} wrapped_closure; - -static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - wrapped_closure *wc = arg; - grpc_iomgr_cb_func cb = wc->cb; - void *cb_arg = wc->cb_arg; - gpr_free(wc); - cb(exec_ctx, cb_arg, success); -} - -grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) { - wrapped_closure *wc = gpr_malloc(sizeof(*wc)); - wc->cb = cb; - wc->cb_arg = cb_arg; - grpc_closure_init(&wc->wrapper, closure_wrapper, wc); - return &wc->wrapper; -} - -grpc_closure *grpc_closure_next(grpc_closure *closure) { - return (grpc_closure *)(closure->final_data & ~(uintptr_t)1); -} diff --git a/src/core/iomgr/closure.h b/src/core/iomgr/closure.h deleted file mode 100644 index ea96c19c71..0000000000 --- a/src/core/iomgr/closure.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H -#define GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H - -#include <grpc/support/port_platform.h> -#include <stdbool.h> - -struct grpc_closure; -typedef struct grpc_closure grpc_closure; - -/* forward declaration for exec_ctx.h */ -struct grpc_exec_ctx; -typedef struct grpc_exec_ctx grpc_exec_ctx; - -typedef struct grpc_closure_list { - grpc_closure *head; - grpc_closure *tail; -} grpc_closure_list; - -/** gRPC Callback definition. - * - * \param arg Arbitrary input. - * \param success An indication on the state of the iomgr. On false, cleanup - * actions should be taken (eg, shutdown). */ -typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, - bool success); - -/** A closure over a grpc_iomgr_cb_func. */ -struct grpc_closure { - /** Bound callback. */ - grpc_iomgr_cb_func cb; - - /** Arguments to be passed to "cb". */ - void *cb_arg; - - /** Once enqueued, contains in the lower bit the success of the closure, - and in the upper bits the pointer to the next closure in the list. - Before enqueing for execution, this is usable for scratch data. */ - uintptr_t final_data; -}; - -/** Initializes \a closure with \a cb and \a cb_arg. */ -void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, - void *cb_arg); - -/* Create a heap allocated closure: try to avoid except for very rare events */ -grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg); - -#define GRPC_CLOSURE_LIST_INIT \ - { NULL, NULL } - -/** add \a closure to the end of \a list and set \a closure's success to \a - * success */ -void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure, - bool success); - -/** append all closures from \a src to \a dst and empty \a src. */ -void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst); - -/** return whether \a list is empty. */ -bool grpc_closure_list_empty(grpc_closure_list list); - -/** return the next pointer for a queued closure list */ -grpc_closure *grpc_closure_next(grpc_closure *closure); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H */ diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c deleted file mode 100644 index bd64707669..0000000000 --- a/src/core/iomgr/endpoint.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/endpoint.h" - -void grpc_endpoint_read(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, - gpr_slice_buffer* slices, grpc_closure* cb) { - ep->vtable->read(exec_ctx, ep, slices, cb); -} - -void grpc_endpoint_write(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, - gpr_slice_buffer* slices, grpc_closure* cb) { - ep->vtable->write(exec_ctx, ep, slices, cb); -} - -void grpc_endpoint_add_to_pollset(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, - grpc_pollset* pollset) { - ep->vtable->add_to_pollset(exec_ctx, ep, pollset); -} - -void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx, - grpc_endpoint* ep, - grpc_pollset_set* pollset_set) { - ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set); -} - -void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { - ep->vtable->shutdown(exec_ctx, ep); -} - -void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { - ep->vtable->destroy(exec_ctx, ep); -} - -char* grpc_endpoint_get_peer(grpc_endpoint* ep) { - return ep->vtable->get_peer(ep); -} diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h deleted file mode 100644 index cbdc947abb..0000000000 --- a/src/core/iomgr/endpoint.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_H -#define GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_H - -#include "src/core/iomgr/pollset.h" -#include "src/core/iomgr/pollset_set.h" -#include <grpc/support/slice.h> -#include <grpc/support/slice_buffer.h> -#include <grpc/support/time.h> - -/* An endpoint caps a streaming channel between two communicating processes. - Examples may be: a tcp socket, <stdin+stdout>, or some shared memory. */ - -typedef struct grpc_endpoint grpc_endpoint; -typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; - -struct grpc_endpoint_vtable { - void (*read)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *slices, grpc_closure *cb); - void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *slices, grpc_closure *cb); - void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset); - void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pollset); - void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); - void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); - char *(*get_peer)(grpc_endpoint *ep); -}; - -/* When data is available on the connection, calls the callback with slices. - Callback success indicates that the endpoint can accept more reads, failure - indicates the endpoint is closed. - Valid slices may be placed into \a slices even on callback success == 0. */ -void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *slices, grpc_closure *cb); - -char *grpc_endpoint_get_peer(grpc_endpoint *ep); - -/* Write slices out to the socket. - - If the connection is ready for more data after the end of the call, it - returns GRPC_ENDPOINT_DONE. - Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the - connection is ready for more data. - \a slices may be mutated at will by the endpoint until cb is called. - No guarantee is made to the content of slices after a write EXCEPT that - it is a valid slice buffer. - */ -void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *slices, grpc_closure *cb); - -/* Causes any pending read/write callbacks to run immediately with - success==0 */ -void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); -void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); - -/* Add an endpoint to a pollset, so that when the pollset is polled, events from - this endpoint are considered */ -void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset); -void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_endpoint *ep, - grpc_pollset_set *pollset_set); - -struct grpc_endpoint { - const grpc_endpoint_vtable *vtable; -}; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_H */ diff --git a/src/core/iomgr/endpoint_pair.h b/src/core/iomgr/endpoint_pair.h deleted file mode 100644 index 095ec5fcc9..0000000000 --- a/src/core/iomgr/endpoint_pair.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_PAIR_H -#define GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_PAIR_H - -#include "src/core/iomgr/endpoint.h" - -typedef struct { - grpc_endpoint *client; - grpc_endpoint *server; -} grpc_endpoint_pair; - -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, - size_t read_slice_size); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_PAIR_H */ diff --git a/src/core/iomgr/endpoint_pair_posix.c b/src/core/iomgr/endpoint_pair_posix.c deleted file mode 100644 index 56f6f146fd..0000000000 --- a/src/core/iomgr/endpoint_pair_posix.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/endpoint_pair.h" -#include "src/core/iomgr/socket_utils_posix.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include "src/core/iomgr/tcp_posix.h" -#include "src/core/support/string.h" -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> - -static void create_sockets(int sv[2]) { - int flags; - GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0])); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1])); -} - -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, - size_t read_slice_size) { - int sv[2]; - grpc_endpoint_pair p; - char *final_name; - create_sockets(sv); - - gpr_asprintf(&final_name, "%s:client", name); - p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size, - "socketpair-server"); - gpr_free(final_name); - gpr_asprintf(&final_name, "%s:server", name); - p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size, - "socketpair-client"); - gpr_free(final_name); - return p; -} - -#endif diff --git a/src/core/iomgr/endpoint_pair_windows.c b/src/core/iomgr/endpoint_pair_windows.c deleted file mode 100644 index db9d092dca..0000000000 --- a/src/core/iomgr/endpoint_pair_windows.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/endpoint_pair.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> - -#include "src/core/iomgr/tcp_windows.h" -#include "src/core/iomgr/socket_windows.h" -#include <grpc/support/log.h> - -static void create_sockets(SOCKET sv[2]) { - SOCKET svr_sock = INVALID_SOCKET; - SOCKET lst_sock = INVALID_SOCKET; - SOCKET cli_sock = INVALID_SOCKET; - SOCKADDR_IN addr; - int addr_len = sizeof(addr); - - lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, - WSA_FLAG_OVERLAPPED); - GPR_ASSERT(lst_sock != INVALID_SOCKET); - - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_family = AF_INET; - GPR_ASSERT(bind(lst_sock, (struct sockaddr *)&addr, sizeof(addr)) != - SOCKET_ERROR); - GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR); - GPR_ASSERT(getsockname(lst_sock, (struct sockaddr *)&addr, &addr_len) != - SOCKET_ERROR); - - cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, - WSA_FLAG_OVERLAPPED); - GPR_ASSERT(cli_sock != INVALID_SOCKET); - - GPR_ASSERT(WSAConnect(cli_sock, (struct sockaddr *)&addr, addr_len, NULL, - NULL, NULL, NULL) == 0); - svr_sock = accept(lst_sock, (struct sockaddr *)&addr, &addr_len); - GPR_ASSERT(svr_sock != INVALID_SOCKET); - - closesocket(lst_sock); - grpc_tcp_prepare_socket(cli_sock); - grpc_tcp_prepare_socket(svr_sock); - - sv[1] = cli_sock; - sv[0] = svr_sock; -} - -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, - size_t read_slice_size) { - SOCKET sv[2]; - grpc_endpoint_pair p; - create_sockets(sv); - p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"), - "endpoint:server"); - p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"), - "endpoint:client"); - return p; -} - -#endif diff --git a/src/core/iomgr/exec_ctx.c b/src/core/iomgr/exec_ctx.c deleted file mode 100644 index 893fe4515c..0000000000 --- a/src/core/iomgr/exec_ctx.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/exec_ctx.h" - -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> - -#include "src/core/profiling/timers.h" - -#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER -bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { - bool did_something = 0; - GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0); - while (!grpc_closure_list_empty(exec_ctx->closure_list)) { - grpc_closure *c = exec_ctx->closure_list.head; - exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL; - while (c != NULL) { - bool success = (bool)(c->final_data & 1); - grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1); - did_something = true; - GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0); - c->cb(exec_ctx, c->cb_arg, success); - GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0); - c = next; - } - } - GPR_TIMER_END("grpc_exec_ctx_flush", 0); - return did_something; -} - -void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) { - grpc_exec_ctx_flush(exec_ctx); -} - -void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - bool success, - grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); - grpc_closure_list_add(&exec_ctx->closure_list, closure, success); -} - -void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx, - grpc_closure_list *list, - grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); - grpc_closure_list_move(list, &exec_ctx->closure_list); -} - -void grpc_exec_ctx_global_init(void) {} -void grpc_exec_ctx_global_shutdown(void) {} -#else -static gpr_mu g_mu; -static gpr_cv g_cv; -static int g_threads = 0; - -static void run_closure(void *arg) { - grpc_closure *closure = arg; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(&g_mu); - if (--g_threads == 0) { - gpr_cv_signal(&g_cv); - } - gpr_mu_unlock(&g_mu); -} - -static void start_closure(grpc_closure *closure) { - gpr_thd_id id; - gpr_mu_lock(&g_mu); - g_threads++; - gpr_mu_unlock(&g_mu); - gpr_thd_new(&id, run_closure, closure, NULL); -} - -bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; } - -void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {} - -void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - bool success, - grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); - if (closure == NULL) return; - closure->final_data = success; - start_closure(closure); -} - -void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx, - grpc_closure_list *list, - grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); - if (list == NULL) return; - grpc_closure *p = list->head; - while (p) { - grpc_closure *start = p; - p = grpc_closure_next(start); - start_closure(start); - } - grpc_closure_list r = GRPC_CLOSURE_LIST_INIT; - *list = r; -} - -void grpc_exec_ctx_global_init(void) { - gpr_mu_init(&g_mu); - gpr_cv_init(&g_cv); -} - -void grpc_exec_ctx_global_shutdown(void) { - gpr_mu_lock(&g_mu); - while (g_threads != 0) { - gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&g_mu); - - gpr_mu_destroy(&g_mu); - gpr_cv_destroy(&g_cv); -} -#endif diff --git a/src/core/iomgr/exec_ctx.h b/src/core/iomgr/exec_ctx.h deleted file mode 100644 index 1b627a5dcf..0000000000 --- a/src/core/iomgr/exec_ctx.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_EXEC_CTX_H -#define GRPC_INTERNAL_CORE_IOMGR_EXEC_CTX_H - -#include "src/core/iomgr/closure.h" - -/* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */ - -/** A workqueue represents a list of work to be executed asynchronously. - Forward declared here to avoid a circular dependency with workqueue.h. */ -struct grpc_workqueue; -typedef struct grpc_workqueue grpc_workqueue; - -#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER -/** Execution context. - * A bag of data that collects information along a callstack. - * Generally created at public API entry points, and passed down as - * pointer to child functions that manipulate it. - * - * Specific responsibilities (this may grow in the future): - * - track a list of work that needs to be delayed until the top of the - * call stack (this provides a convenient mechanism to run callbacks - * without worrying about locking issues) - * - * CONVENTIONS: - * Instance of this must ALWAYS be constructed on the stack, never - * heap allocated. Instances and pointers to them must always be called - * exec_ctx. Instances are always passed as the first argument - * to a function that takes it, and always as a pointer (grpc_exec_ctx - * is never copied). - */ -struct grpc_exec_ctx { - grpc_closure_list closure_list; -}; - -#define GRPC_EXEC_CTX_INIT \ - { GRPC_CLOSURE_LIST_INIT } -#else -struct grpc_exec_ctx { - int unused; -}; -#define GRPC_EXEC_CTX_INIT \ - { 0 } -#endif - -/** Flush any work that has been enqueued onto this grpc_exec_ctx. - * Caller must guarantee that no interfering locks are held. - * Returns true if work was performed, false otherwise. */ -bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx); -/** Finish any pending work for a grpc_exec_ctx. Must be called before - * the instance is destroyed, or work may be lost. */ -void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx); -/** Add a closure to be executed at the next flush/finish point */ -void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - bool success, - grpc_workqueue *offload_target_or_null); -/** Add a list of closures to be executed at the next flush/finish point. - * Leaves \a list empty. */ -void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx, - grpc_closure_list *list, - grpc_workqueue *offload_target_or_null); - -void grpc_exec_ctx_global_init(void); -void grpc_exec_ctx_global_shutdown(void); - -#endif diff --git a/src/core/iomgr/executor.c b/src/core/iomgr/executor.c deleted file mode 100644 index f22d8f30ac..0000000000 --- a/src/core/iomgr/executor.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/executor.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> -#include "src/core/iomgr/exec_ctx.h" - -typedef struct grpc_executor_data { - int busy; /**< is the thread currently running? */ - int shutting_down; /**< has \a grpc_shutdown() been invoked? */ - int pending_join; /**< has the thread finished but not been joined? */ - grpc_closure_list closures; /**< collection of pending work */ - gpr_thd_id tid; /**< thread id of the thread, only valid if \a busy or \a - pending_join are true */ - gpr_thd_options options; - gpr_mu mu; -} grpc_executor; - -static grpc_executor g_executor; - -void grpc_executor_init() { - memset(&g_executor, 0, sizeof(grpc_executor)); - gpr_mu_init(&g_executor.mu); - g_executor.options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&g_executor.options); -} - -/* thread body */ -static void closure_exec_thread_func(void *ignored) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - while (1) { - gpr_mu_lock(&g_executor.mu); - if (g_executor.shutting_down != 0) { - gpr_mu_unlock(&g_executor.mu); - break; - } - if (grpc_closure_list_empty(g_executor.closures)) { - /* no more work, time to die */ - GPR_ASSERT(g_executor.busy == 1); - g_executor.busy = 0; - gpr_mu_unlock(&g_executor.mu); - break; - } else { - grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL); - } - gpr_mu_unlock(&g_executor.mu); - grpc_exec_ctx_flush(&exec_ctx); - } - grpc_exec_ctx_finish(&exec_ctx); -} - -/* Spawn the thread if new work has arrived a no thread is up */ -static void maybe_spawn_locked() { - if (grpc_closure_list_empty(g_executor.closures) == 1) { - return; - } - if (g_executor.shutting_down == 1) { - return; - } - - if (g_executor.busy != 0) { - /* Thread still working. New work will be picked up by already running - * thread. Not spawning anything. */ - return; - } else if (g_executor.pending_join != 0) { - /* Pickup the remains of the previous incarnations of the thread. */ - gpr_thd_join(g_executor.tid); - g_executor.pending_join = 0; - } - - /* All previous instances of the thread should have been joined at this point. - * Spawn time! */ - g_executor.busy = 1; - gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL, - &g_executor.options); - g_executor.pending_join = 1; -} - -void grpc_executor_enqueue(grpc_closure *closure, bool success) { - gpr_mu_lock(&g_executor.mu); - if (g_executor.shutting_down == 0) { - grpc_closure_list_add(&g_executor.closures, closure, success); - maybe_spawn_locked(); - } - gpr_mu_unlock(&g_executor.mu); -} - -void grpc_executor_shutdown() { - int pending_join; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_mu_lock(&g_executor.mu); - pending_join = g_executor.pending_join; - g_executor.shutting_down = 1; - gpr_mu_unlock(&g_executor.mu); - /* we can release the lock at this point despite the access to the closure - * list below because we aren't accepting new work */ - - /* Execute pending callbacks, some may be performing cleanups */ - grpc_exec_ctx_enqueue_list(&exec_ctx, &g_executor.closures, NULL); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(grpc_closure_list_empty(g_executor.closures)); - if (pending_join) { - gpr_thd_join(g_executor.tid); - } - gpr_mu_destroy(&g_executor.mu); -} diff --git a/src/core/iomgr/executor.h b/src/core/iomgr/executor.h deleted file mode 100644 index aac057ddf5..0000000000 --- a/src/core/iomgr/executor.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_EXECUTOR_H -#define GRPC_INTERNAL_CORE_IOMGR_EXECUTOR_H - -#include "src/core/iomgr/closure.h" - -/** Initialize the global executor. - * - * This mechanism is meant to outsource work (grpc_closure instances) to a - * thread, for those cases where blocking isn't an option but there isn't a - * non-blocking solution available. */ -void grpc_executor_init(); - -/** Enqueue \a closure for its eventual execution of \a f(arg) on a separate - * thread */ -void grpc_executor_enqueue(grpc_closure *closure, bool success); - -/** Shutdown the executor, running all pending work as part of the call */ -void grpc_executor_shutdown(); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_EXECUTOR_H */ diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c deleted file mode 100644 index 4ba7c5df94..0000000000 --- a/src/core/iomgr/fd_posix.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/fd_posix.h" - -#include <assert.h> -#include <sys/socket.h> -#include <unistd.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/pollset_posix.h" - -#define CLOSURE_NOT_READY ((grpc_closure *)0) -#define CLOSURE_READY ((grpc_closure *)1) - -/* We need to keep a freelist not because of any concerns of malloc performance - * but instead so that implementations with multiple threads in (for example) - * epoll_wait deal with the race between pollset removal and incoming poll - * notifications. - * - * The problem is that the poller ultimately holds a reference to this - * object, so it is very difficult to know when is safe to free it, at least - * without some expensive synchronization. - * - * If we keep the object freelisted, in the worst case losing this race just - * becomes a spurious read notification on a reused fd. - */ -/* TODO(klempner): We could use some form of polling generation count to know - * when these are safe to free. */ -/* TODO(klempner): Consider disabling freelisting if we don't have multiple - * threads in poll on the same fd */ -/* TODO(klempner): Batch these allocations to reduce fragmentation */ -static grpc_fd *fd_freelist = NULL; -static gpr_mu fd_freelist_mu; - -static void freelist_fd(grpc_fd *fd) { - gpr_mu_lock(&fd_freelist_mu); - fd->freelist_next = fd_freelist; - fd_freelist = fd; - grpc_iomgr_unregister_object(&fd->iomgr_object); - gpr_mu_unlock(&fd_freelist_mu); -} - -static grpc_fd *alloc_fd(int fd) { - grpc_fd *r = NULL; - gpr_mu_lock(&fd_freelist_mu); - if (fd_freelist != NULL) { - r = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - } - gpr_mu_unlock(&fd_freelist_mu); - if (r == NULL) { - r = gpr_malloc(sizeof(grpc_fd)); - gpr_mu_init(&r->mu); - } - - gpr_atm_rel_store(&r->refst, 1); - r->shutdown = 0; - r->read_closure = CLOSURE_NOT_READY; - r->write_closure = CLOSURE_NOT_READY; - r->fd = fd; - r->inactive_watcher_root.next = r->inactive_watcher_root.prev = - &r->inactive_watcher_root; - r->freelist_next = NULL; - r->read_watcher = r->write_watcher = NULL; - r->on_done_closure = NULL; - r->closed = 0; - r->released = 0; - return r; -} - -static void destroy(grpc_fd *fd) { - gpr_mu_destroy(&fd->mu); - gpr_free(fd); -} - -#ifdef GRPC_FD_REF_COUNT_DEBUG -#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) -#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) -static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, - int line) { - gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, - gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); -#else -#define REF_BY(fd, n, reason) ref_by(fd, n) -#define UNREF_BY(fd, n, reason) unref_by(fd, n) -static void ref_by(grpc_fd *fd, int n) { -#endif - GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); -} - -#ifdef GRPC_FD_REF_COUNT_DEBUG -static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, - int line) { - gpr_atm old; - gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, - gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); -#else -static void unref_by(grpc_fd *fd, int n) { - gpr_atm old; -#endif - old = gpr_atm_full_fetch_add(&fd->refst, -n); - if (old == n) { - freelist_fd(fd); - } else { - GPR_ASSERT(old > n); - } -} - -void grpc_fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } - -void grpc_fd_global_shutdown(void) { - gpr_mu_lock(&fd_freelist_mu); - gpr_mu_unlock(&fd_freelist_mu); - while (fd_freelist != NULL) { - grpc_fd *fd = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - destroy(fd); - } - gpr_mu_destroy(&fd_freelist_mu); -} - -grpc_fd *grpc_fd_create(int fd, const char *name) { - grpc_fd *r = alloc_fd(fd); - char *name2; - gpr_asprintf(&name2, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&r->iomgr_object, name2); - gpr_free(name2); -#ifdef GRPC_FD_REF_COUNT_DEBUG - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name); -#endif - return r; -} - -int grpc_fd_is_orphaned(grpc_fd *fd) { - return (gpr_atm_acq_load(&fd->refst) & 1) == 0; -} - -static void pollset_kick_locked(grpc_fd_watcher *watcher) { - gpr_mu_lock(&watcher->pollset->mu); - GPR_ASSERT(watcher->worker); - grpc_pollset_kick_ext(watcher->pollset, watcher->worker, - GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP); - gpr_mu_unlock(&watcher->pollset->mu); -} - -static void maybe_wake_one_watcher_locked(grpc_fd *fd) { - if (fd->inactive_watcher_root.next != &fd->inactive_watcher_root) { - pollset_kick_locked(fd->inactive_watcher_root.next); - } else if (fd->read_watcher) { - pollset_kick_locked(fd->read_watcher); - } else if (fd->write_watcher) { - pollset_kick_locked(fd->write_watcher); - } -} - -static void wake_all_watchers_locked(grpc_fd *fd) { - grpc_fd_watcher *watcher; - for (watcher = fd->inactive_watcher_root.next; - watcher != &fd->inactive_watcher_root; watcher = watcher->next) { - pollset_kick_locked(watcher); - } - if (fd->read_watcher) { - pollset_kick_locked(fd->read_watcher); - } - if (fd->write_watcher && fd->write_watcher != fd->read_watcher) { - pollset_kick_locked(fd->write_watcher); - } -} - -static int has_watchers(grpc_fd *fd) { - return fd->read_watcher != NULL || fd->write_watcher != NULL || - fd->inactive_watcher_root.next != &fd->inactive_watcher_root; -} - -static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - fd->closed = 1; - if (!fd->released) { - close(fd->fd); - } else { - grpc_remove_fd_from_all_epoll_sets(fd->fd); - } - grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL); -} - -int grpc_fd_wrapped_fd(grpc_fd *fd) { - if (fd->released || fd->closed) { - return -1; - } else { - return fd->fd; - } -} - -void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, - int *release_fd, const char *reason) { - fd->on_done_closure = on_done; - fd->released = release_fd != NULL; - if (!fd->released) { - shutdown(fd->fd, SHUT_RDWR); - } else { - *release_fd = fd->fd; - } - gpr_mu_lock(&fd->mu); - REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ - if (!has_watchers(fd)) { - close_fd_locked(exec_ctx, fd); - } else { - wake_all_watchers_locked(fd); - } - gpr_mu_unlock(&fd->mu); - UNREF_BY(fd, 2, reason); /* drop the reference */ -} - -/* increment refcount by two to avoid changing the orphan bit */ -#ifdef GRPC_FD_REF_COUNT_DEBUG -void grpc_fd_ref(grpc_fd *fd, const char *reason, const char *file, int line) { - ref_by(fd, 2, reason, file, line); -} - -void grpc_fd_unref(grpc_fd *fd, const char *reason, const char *file, - int line) { - unref_by(fd, 2, reason, file, line); -} -#else -void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); } - -void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } -#endif - -static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure **st, grpc_closure *closure) { - if (*st == CLOSURE_NOT_READY) { - /* not ready ==> switch to a waiting state by setting the closure */ - *st = closure; - } else if (*st == CLOSURE_READY) { - /* already ready ==> queue the closure to run immediately */ - *st = CLOSURE_NOT_READY; - grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL); - maybe_wake_one_watcher_locked(fd); - } else { - /* upcallptr was set to a different closure. This is an error! */ - gpr_log(GPR_ERROR, - "User called a notify_on function with a previous callback still " - "pending"); - abort(); - } -} - -/* returns 1 if state becomes not ready */ -static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure **st) { - if (*st == CLOSURE_READY) { - /* duplicate ready ==> ignore */ - return 0; - } else if (*st == CLOSURE_NOT_READY) { - /* not ready, and not waiting ==> flag ready */ - *st = CLOSURE_READY; - return 0; - } else { - /* waiting ==> queue closure */ - grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL); - *st = CLOSURE_NOT_READY; - return 1; - } -} - -static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure **st) { - /* only one set_ready can be active at once (but there may be a racing - notify_on) */ - gpr_mu_lock(&fd->mu); - set_ready_locked(exec_ctx, fd, st); - gpr_mu_unlock(&fd->mu); -} - -void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - gpr_mu_lock(&fd->mu); - GPR_ASSERT(!fd->shutdown); - fd->shutdown = 1; - set_ready_locked(exec_ctx, fd, &fd->read_closure); - set_ready_locked(exec_ctx, fd, &fd->write_closure); - gpr_mu_unlock(&fd->mu); -} - -void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure) { - gpr_mu_lock(&fd->mu); - notify_on_locked(exec_ctx, fd, &fd->read_closure, closure); - gpr_mu_unlock(&fd->mu); -} - -void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure) { - gpr_mu_lock(&fd->mu); - notify_on_locked(exec_ctx, fd, &fd->write_closure, closure); - gpr_mu_unlock(&fd->mu); -} - -uint32_t grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - grpc_pollset_worker *worker, uint32_t read_mask, - uint32_t write_mask, grpc_fd_watcher *watcher) { - uint32_t mask = 0; - grpc_closure *cur; - int requested; - /* keep track of pollers that have requested our events, in case they change - */ - GRPC_FD_REF(fd, "poll"); - - gpr_mu_lock(&fd->mu); - - /* if we are shutdown, then don't add to the watcher set */ - if (fd->shutdown) { - watcher->fd = NULL; - watcher->pollset = NULL; - watcher->worker = NULL; - gpr_mu_unlock(&fd->mu); - GRPC_FD_UNREF(fd, "poll"); - return 0; - } - - /* if there is nobody polling for read, but we need to, then start doing so */ - cur = fd->read_closure; - requested = cur != CLOSURE_READY; - if (read_mask && fd->read_watcher == NULL && requested) { - fd->read_watcher = watcher; - mask |= read_mask; - } - /* if there is nobody polling for write, but we need to, then start doing so - */ - cur = fd->write_closure; - requested = cur != CLOSURE_READY; - if (write_mask && fd->write_watcher == NULL && requested) { - fd->write_watcher = watcher; - mask |= write_mask; - } - /* if not polling, remember this watcher in case we need someone to later */ - if (mask == 0 && worker != NULL) { - watcher->next = &fd->inactive_watcher_root; - watcher->prev = watcher->next->prev; - watcher->next->prev = watcher->prev->next = watcher; - } - watcher->pollset = pollset; - watcher->worker = worker; - watcher->fd = fd; - gpr_mu_unlock(&fd->mu); - - return mask; -} - -void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher, - int got_read, int got_write) { - int was_polling = 0; - int kick = 0; - grpc_fd *fd = watcher->fd; - - if (fd == NULL) { - return; - } - - gpr_mu_lock(&fd->mu); - - if (watcher == fd->read_watcher) { - /* remove read watcher, kick if we still need a read */ - was_polling = 1; - if (!got_read) { - kick = 1; - } - fd->read_watcher = NULL; - } - if (watcher == fd->write_watcher) { - /* remove write watcher, kick if we still need a write */ - was_polling = 1; - if (!got_write) { - kick = 1; - } - fd->write_watcher = NULL; - } - if (!was_polling && watcher->worker != NULL) { - /* remove from inactive list */ - watcher->next->prev = watcher->prev; - watcher->prev->next = watcher->next; - } - if (got_read) { - if (set_ready_locked(exec_ctx, fd, &fd->read_closure)) { - kick = 1; - } - } - if (got_write) { - if (set_ready_locked(exec_ctx, fd, &fd->write_closure)) { - kick = 1; - } - } - if (kick) { - maybe_wake_one_watcher_locked(fd); - } - if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) { - close_fd_locked(exec_ctx, fd); - } - gpr_mu_unlock(&fd->mu); - - GRPC_FD_UNREF(fd, "poll"); -} - -void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - set_ready(exec_ctx, fd, &fd->read_closure); -} - -void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - set_ready(exec_ctx, fd, &fd->write_closure); -} - -#endif diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h deleted file mode 100644 index 17e7de88ff..0000000000 --- a/src/core/iomgr/fd_posix.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H - -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/pollset.h" -#include <grpc/support/atm.h> -#include <grpc/support/sync.h> -#include <grpc/support/time.h> - -typedef struct grpc_fd grpc_fd; - -typedef struct grpc_fd_watcher { - struct grpc_fd_watcher *next; - struct grpc_fd_watcher *prev; - grpc_pollset *pollset; - grpc_pollset_worker *worker; - grpc_fd *fd; -} grpc_fd_watcher; - -struct grpc_fd { - int fd; - /* refst format: - bit0: 1=active/0=orphaned - bit1-n: refcount - meaning that mostly we ref by two to avoid altering the orphaned bit, - and just unref by 1 when we're ready to flag the object as orphaned */ - gpr_atm refst; - - gpr_mu mu; - int shutdown; - int closed; - int released; - - /* The watcher list. - - The following watcher related fields are protected by watcher_mu. - - An fd_watcher is an ephemeral object created when an fd wants to - begin polling, and destroyed after the poll. - - It denotes the fd's interest in whether to read poll or write poll - or both or neither on this fd. - - If a watcher is asked to poll for reads or writes, the read_watcher - or write_watcher fields are set respectively. A watcher may be asked - to poll for both, in which case both fields will be set. - - read_watcher and write_watcher may be NULL if no watcher has been - asked to poll for reads or writes. - - If an fd_watcher is not asked to poll for reads or writes, it's added - to a linked list of inactive watchers, rooted at inactive_watcher_root. - If at a later time there becomes need of a poller to poll, one of - the inactive pollers may be kicked out of their poll loops to take - that responsibility. */ - grpc_fd_watcher inactive_watcher_root; - grpc_fd_watcher *read_watcher; - grpc_fd_watcher *write_watcher; - - grpc_closure *read_closure; - grpc_closure *write_closure; - - struct grpc_fd *freelist_next; - - grpc_closure *on_done_closure; - - grpc_iomgr_object iomgr_object; -}; - -/* Create a wrapped file descriptor. - Requires fd is a non-blocking file descriptor. - This takes ownership of closing fd. */ -grpc_fd *grpc_fd_create(int fd, const char *name); - -/* Return the wrapped fd, or -1 if it has been released or closed. */ -int grpc_fd_wrapped_fd(grpc_fd *fd); - -/* Releases fd to be asynchronously destroyed. - on_done is called when the underlying file descriptor is definitely close()d. - If on_done is NULL, no callback will be made. - If release_fd is not NULL, it's set to fd and fd will not be closed. - Requires: *fd initialized; no outstanding notify_on_read or - notify_on_write. - MUST NOT be called with a pollset lock taken */ -void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, - int *release_fd, const char *reason); - -/* Begin polling on an fd. - Registers that the given pollset is interested in this fd - so that if read - or writability interest changes, the pollset can be kicked to pick up that - new interest. - Return value is: - (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0) - i.e. a combination of read_mask and write_mask determined by the fd's current - interest in said events. - Polling strategies that do not need to alter their behavior depending on the - fd's current interest (such as epoll) do not need to call this function. - MUST NOT be called with a pollset lock taken */ -uint32_t grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - grpc_pollset_worker *worker, uint32_t read_mask, - uint32_t write_mask, grpc_fd_watcher *rec); -/* Complete polling previously started with grpc_fd_begin_poll - MUST NOT be called with a pollset lock taken - if got_read or got_write are 1, also does the become_{readable,writable} as - appropriate. */ -void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec, - int got_read, int got_write); - -/* Return 1 if this fd is orphaned, 0 otherwise */ -int grpc_fd_is_orphaned(grpc_fd *fd); - -/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */ -void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd); - -/* Register read interest, causing read_cb to be called once when fd becomes - readable, on deadline specified by deadline, or on shutdown triggered by - grpc_fd_shutdown. - read_cb will be called with read_cb_arg when *fd becomes readable. - read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, - GRPC_CALLBACK_TIMED_OUT if the call timed out, - and CANCELLED if the call was cancelled. - - Requires:This method must not be called before the read_cb for any previous - call runs. Edge triggered events are used whenever they are supported by the - underlying platform. This means that users must drain fd in read_cb before - calling notify_on_read again. Users are also expected to handle spurious - events, i.e read_cb is called while nothing can be readable from fd */ -void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure); - -/* Exactly the same semantics as above, except based on writable events. */ -void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure); - -/* Notification from the poller to an fd that it has become readable or - writable. - If allow_synchronous_callback is 1, allow running the fd callback inline - in this callstack, otherwise register an asynchronous callback and return */ -void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd); -void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd); - -/* Reference counting for fds */ -/*#define GRPC_FD_REF_COUNT_DEBUG*/ -#ifdef GRPC_FD_REF_COUNT_DEBUG -void grpc_fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); -void grpc_fd_unref(grpc_fd *fd, const char *reason, const char *file, int line); -#define GRPC_FD_REF(fd, reason) grpc_fd_ref(fd, reason, __FILE__, __LINE__) -#define GRPC_FD_UNREF(fd, reason) grpc_fd_unref(fd, reason, __FILE__, __LINE__) -#else -void grpc_fd_ref(grpc_fd *fd); -void grpc_fd_unref(grpc_fd *fd); -#define GRPC_FD_REF(fd, reason) grpc_fd_ref(fd) -#define GRPC_FD_UNREF(fd, reason) grpc_fd_unref(fd) -#endif - -void grpc_fd_global_init(void); -void grpc_fd_global_shutdown(void); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H */ diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c deleted file mode 100644 index fa87e5246b..0000000000 --- a/src/core/iomgr/iocp_windows.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include <winsock2.h> - -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/alloc.h> -#include <grpc/support/thd.h> - -#include "src/core/iomgr/timer.h" -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/socket_windows.h" - -static ULONG g_iocp_kick_token; -static OVERLAPPED g_iocp_custom_overlap; - -static gpr_atm g_custom_events = 0; - -static HANDLE g_iocp; - -static DWORD deadline_to_millis_timeout(gpr_timespec deadline, - gpr_timespec now) { - gpr_timespec timeout; - static const int64_t max_spin_polling_us = 10; - if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { - return INFINITE; - } - if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( - max_spin_polling_us, - GPR_TIMESPAN))) <= 0) { - return 0; - } - timeout = gpr_time_sub(deadline, now); - return (DWORD)gpr_time_to_millis(gpr_time_add( - timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); -} - -grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, - gpr_timespec deadline) { - BOOL success; - DWORD bytes = 0; - DWORD flags = 0; - ULONG_PTR completion_key; - LPOVERLAPPED overlapped; - grpc_winsocket *socket; - grpc_winsocket_callback_info *info; - grpc_closure *closure = NULL; - success = GetQueuedCompletionStatus( - g_iocp, &bytes, &completion_key, &overlapped, - deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); - if (success == 0 && overlapped == NULL) { - return GRPC_IOCP_WORK_TIMEOUT; - } - GPR_ASSERT(completion_key && overlapped); - if (overlapped == &g_iocp_custom_overlap) { - gpr_atm_full_fetch_add(&g_custom_events, -1); - if (completion_key == (ULONG_PTR)&g_iocp_kick_token) { - /* We were awoken from a kick. */ - return GRPC_IOCP_WORK_KICK; - } - gpr_log(GPR_ERROR, "Unknown custom completion key."); - abort(); - } - - socket = (grpc_winsocket *)completion_key; - if (overlapped == &socket->write_info.overlapped) { - info = &socket->write_info; - } else if (overlapped == &socket->read_info.overlapped) { - info = &socket->read_info; - } else { - gpr_log(GPR_ERROR, "Unknown IOCP operation"); - abort(); - } - success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, - FALSE, &flags); - info->bytes_transfered = bytes; - info->wsa_error = success ? 0 : WSAGetLastError(); - GPR_ASSERT(overlapped == &info->overlapped); - GPR_ASSERT(!info->has_pending_iocp); - gpr_mu_lock(&socket->state_mu); - if (info->closure) { - closure = info->closure; - info->closure = NULL; - } else { - info->has_pending_iocp = 1; - } - gpr_mu_unlock(&socket->state_mu); - grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); - return GRPC_IOCP_WORK_WORK; -} - -void grpc_iocp_init(void) { - g_iocp = - CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); - GPR_ASSERT(g_iocp); -} - -void grpc_iocp_kick(void) { - BOOL success; - - gpr_atm_full_fetch_add(&g_custom_events, 1); - success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR)&g_iocp_kick_token, - &g_iocp_custom_overlap); - GPR_ASSERT(success); -} - -void grpc_iocp_flush(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_iocp_work_status work_status; - - do { - work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC)); - } while (work_status == GRPC_IOCP_WORK_KICK || - grpc_exec_ctx_flush(&exec_ctx)); -} - -void grpc_iocp_shutdown(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - while (gpr_atm_acq_load(&g_custom_events)) { - grpc_iocp_work(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - grpc_exec_ctx_flush(&exec_ctx); - } - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(CloseHandle(g_iocp)); -} - -void grpc_iocp_add_socket(grpc_winsocket *socket) { - HANDLE ret; - if (socket->added_to_iocp) return; - ret = CreateIoCompletionPort((HANDLE)socket->socket, g_iocp, - (uintptr_t)socket, 0); - if (!ret) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "Unable to add socket to iocp: %s", utf8_message); - gpr_free(utf8_message); - __debugbreak(); - abort(); - } - socket->added_to_iocp = 1; - GPR_ASSERT(ret == g_iocp); -} - -/* Calling notify_on_read or write means either of two things: - -) The IOCP already completed in the background, and we need to call - the callback now. - -) The IOCP hasn't completed yet, and we're queuing it for later. */ -static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx, - grpc_winsocket *socket, grpc_closure *closure, - grpc_winsocket_callback_info *info) { - GPR_ASSERT(info->closure == NULL); - gpr_mu_lock(&socket->state_mu); - if (info->has_pending_iocp) { - info->has_pending_iocp = 0; - grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); - } else { - info->closure = closure; - } - gpr_mu_unlock(&socket->state_mu); -} - -void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx, - grpc_winsocket *socket, - grpc_closure *closure) { - socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info); -} - -void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, - grpc_closure *closure) { - socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info); -} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/iocp_windows.h b/src/core/iomgr/iocp_windows.h deleted file mode 100644 index 8b2b1aeb5c..0000000000 --- a/src/core/iomgr/iocp_windows.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_IOCP_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_IOCP_WINDOWS_H - -#include <grpc/support/sync.h> - -#include "src/core/iomgr/socket_windows.h" - -typedef enum { - GRPC_IOCP_WORK_WORK, - GRPC_IOCP_WORK_TIMEOUT, - GRPC_IOCP_WORK_KICK -} grpc_iocp_work_status; - -grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, - gpr_timespec deadline); -void grpc_iocp_init(void); -void grpc_iocp_kick(void); -void grpc_iocp_flush(void); -void grpc_iocp_shutdown(void); -void grpc_iocp_add_socket(grpc_winsocket *); - -void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx, - grpc_winsocket *winsocket, - grpc_closure *closure); - -void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, - grpc_winsocket *winsocket, - grpc_closure *closure); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_IOCP_WINDOWS_H */ diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c deleted file mode 100644 index 3ab4430668..0000000000 --- a/src/core/iomgr/iomgr.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/iomgr.h" - -#include <stdlib.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/exec_ctx.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/timer.h" -#include "src/core/support/env.h" -#include "src/core/support/string.h" - -static gpr_mu g_mu; -static gpr_cv g_rcv; -static int g_shutdown; -static grpc_iomgr_object g_root_object; - -void grpc_iomgr_init(void) { - g_shutdown = 0; - gpr_mu_init(&g_mu); - gpr_cv_init(&g_rcv); - grpc_exec_ctx_global_init(); - grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC)); - g_root_object.next = g_root_object.prev = &g_root_object; - g_root_object.name = "root"; - grpc_iomgr_platform_init(); - grpc_pollset_global_init(); -} - -static size_t count_objects(void) { - grpc_iomgr_object *obj; - size_t n = 0; - for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { - n++; - } - return n; -} - -static void dump_objects(const char *kind) { - grpc_iomgr_object *obj; - for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { - gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj); - } -} - -void grpc_iomgr_shutdown(void) { - gpr_timespec shutdown_deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); - gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_iomgr_platform_flush(); - - gpr_mu_lock(&g_mu); - g_shutdown = 1; - while (g_root_object.next != &g_root_object) { - if (gpr_time_cmp( - gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time), - gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { - if (g_root_object.next != &g_root_object) { - gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed", - count_objects()); - } - last_warning_time = gpr_now(GPR_CLOCK_REALTIME); - } - if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC), - NULL)) { - gpr_mu_unlock(&g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(&g_mu); - continue; - } - if (g_root_object.next != &g_root_object) { - gpr_timespec short_deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); - if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) { - if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { - if (g_root_object.next != &g_root_object) { - gpr_log(GPR_DEBUG, - "Failed to free %d iomgr objects before shutdown deadline: " - "memory leaks are likely", - count_objects()); - dump_objects("LEAKED"); - if (grpc_iomgr_abort_on_leaks()) { - abort(); - } - } - break; - } - } - } - } - gpr_mu_unlock(&g_mu); - - grpc_timer_list_shutdown(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); - - /* ensure all threads have left g_mu */ - gpr_mu_lock(&g_mu); - gpr_mu_unlock(&g_mu); - - grpc_pollset_global_shutdown(); - grpc_iomgr_platform_shutdown(); - grpc_exec_ctx_global_shutdown(); - gpr_mu_destroy(&g_mu); - gpr_cv_destroy(&g_rcv); -} - -void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) { - obj->name = gpr_strdup(name); - gpr_mu_lock(&g_mu); - obj->next = &g_root_object; - obj->prev = g_root_object.prev; - obj->next->prev = obj->prev->next = obj; - gpr_mu_unlock(&g_mu); -} - -void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) { - gpr_mu_lock(&g_mu); - obj->next->prev = obj->prev; - obj->prev->next = obj->next; - gpr_cv_signal(&g_rcv); - gpr_mu_unlock(&g_mu); - gpr_free(obj->name); -} - -bool grpc_iomgr_abort_on_leaks(void) { - char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS"); - if (env == NULL) return false; - static const char *truthy[] = {"yes", "Yes", "YES", "true", - "True", "TRUE", "1"}; - for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) { - if (0 == strcmp(env, truthy[i])) return true; - } - return false; -} diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h deleted file mode 100644 index c9ea84c605..0000000000 --- a/src/core/iomgr/iomgr.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_H -#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_H - -/** Initializes the iomgr. */ -void grpc_iomgr_init(void); - -/** Signals the intention to shutdown the iomgr. */ -void grpc_iomgr_shutdown(void); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */ diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h deleted file mode 100644 index ac2c46ebe6..0000000000 --- a/src/core/iomgr/iomgr_internal.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H -#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H - -#include <stdbool.h> - -#include "src/core/iomgr/iomgr.h" -#include <grpc/support/sync.h> - -typedef struct grpc_iomgr_object { - char *name; - struct grpc_iomgr_object *next; - struct grpc_iomgr_object *prev; -} grpc_iomgr_object; - -void grpc_pollset_global_init(void); -void grpc_pollset_global_shutdown(void); - -void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name); -void grpc_iomgr_unregister_object(grpc_iomgr_object *obj); - -void grpc_iomgr_platform_init(void); -/** flush any globally queued work from iomgr */ -void grpc_iomgr_platform_flush(void); -/** tear down all platform specific global iomgr structures */ -void grpc_iomgr_platform_shutdown(void); - -bool grpc_iomgr_abort_on_leaks(void); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H */ diff --git a/src/core/iomgr/iomgr_posix.c b/src/core/iomgr/iomgr_posix.c deleted file mode 100644 index fecb7b9760..0000000000 --- a/src/core/iomgr/iomgr_posix.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/iomgr_posix.h" -#include "src/core/debug/trace.h" -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/tcp_posix.h" - -void grpc_iomgr_platform_init(void) { - grpc_fd_global_init(); - grpc_register_tracer("tcp", &grpc_tcp_trace); -} - -void grpc_iomgr_platform_flush(void) {} - -void grpc_iomgr_platform_shutdown(void) { grpc_fd_global_shutdown(); } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/src/core/iomgr/iomgr_posix.h b/src/core/iomgr/iomgr_posix.h deleted file mode 100644 index 068a5c6d7c..0000000000 --- a/src/core/iomgr/iomgr_posix.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_POSIX_H - -#include "src/core/iomgr/iomgr_internal.h" - -#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_POSIX_H */ diff --git a/src/core/iomgr/iomgr_windows.c b/src/core/iomgr/iomgr_windows.c deleted file mode 100644 index 14775516bb..0000000000 --- a/src/core/iomgr/iomgr_windows.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include "src/core/iomgr/sockaddr_win32.h" - -#include <grpc/support/log.h> - -#include "src/core/iomgr/socket_windows.h" -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/iomgr.h" - -/* Windows' io manager is going to be fully designed using IO completion - ports. All of what we're doing here is basically make sure that - Windows sockets are initialized in and out. */ - -static void winsock_init(void) { - WSADATA wsaData; - int status = WSAStartup(MAKEWORD(2, 0), &wsaData); - GPR_ASSERT(status == 0); -} - -static void winsock_shutdown(void) { - int status = WSACleanup(); - GPR_ASSERT(status == 0); -} - -void grpc_iomgr_platform_init(void) { - winsock_init(); - grpc_iocp_init(); -} - -void grpc_iomgr_platform_flush(void) { grpc_iocp_flush(); } - -void grpc_iomgr_platform_shutdown(void) { - grpc_iocp_shutdown(); - winsock_shutdown(); -} - -#endif /* GRPC_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h deleted file mode 100644 index ee1debfb71..0000000000 --- a/src/core/iomgr/pollset.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_H - -#include <grpc/support/port_platform.h> -#include <grpc/support/sync.h> -#include <grpc/support/time.h> - -#include "src/core/iomgr/exec_ctx.h" - -#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) - -/* A grpc_pollset is a set of file descriptors that a higher level item is - interested in. For example: - - a server will typically keep a pollset containing all connected channels, - so that it can find new calls to service - - a completion queue might keep a pollset with an entry for each transport - that is servicing a call that it's tracking */ - -typedef struct grpc_pollset grpc_pollset; -typedef struct grpc_pollset_worker grpc_pollset_worker; - -size_t grpc_pollset_size(void); -void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu); -/* Begin shutting down the pollset, and call closure when done. - * pollset's mutex must be held */ -void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_closure *closure); -/** Reset the pollset to its initial state (perhaps with some cached objects); - * must have been previously shutdown */ -void grpc_pollset_reset(grpc_pollset *pollset); -void grpc_pollset_destroy(grpc_pollset *pollset); - -/* Do some work on a pollset. - May involve invoking asynchronous callbacks, or actually polling file - descriptors. - Requires pollset's mutex locked. - May unlock its mutex during its execution. - - worker is a (platform-specific) handle that can be used to wake up - from grpc_pollset_work before any events are received and before the timeout - has expired. It is both initialized and destroyed by grpc_pollset_work. - Initialization of worker is guaranteed to occur BEFORE the - pollset's mutex is released for the first time by grpc_pollset_work - and it is guaranteed that it will not be released by grpc_pollset_work - AFTER worker has been destroyed. - - Tries not to block past deadline. - May call grpc_closure_list_run on grpc_closure_list, without holding the - pollset - lock */ -void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker **worker, gpr_timespec now, - gpr_timespec deadline); - -/* Break one polling thread out of polling work for this pollset. - If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers. - Otherwise, if specific_worker is non-NULL, then kick that worker. */ -void grpc_pollset_kick(grpc_pollset *pollset, - grpc_pollset_worker *specific_worker); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_H */ diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c deleted file mode 100644 index 2e0f27fab8..0000000000 --- a/src/core/iomgr/pollset_multipoller_with_epoll.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_LINUX_MULTIPOLL_WITH_EPOLL - -#include <errno.h> -#include <poll.h> -#include <string.h> -#include <sys/epoll.h> -#include <unistd.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/profiling/timers.h" -#include "src/core/support/block_annotate.h" - -struct epoll_fd_list { - int *epoll_fds; - size_t count; - size_t capacity; -}; - -static struct epoll_fd_list epoll_fd_global_list; -static gpr_once init_epoll_fd_list_mu = GPR_ONCE_INIT; -static gpr_mu epoll_fd_list_mu; - -static void init_mu(void) { gpr_mu_init(&epoll_fd_list_mu); } - -static void add_epoll_fd_to_global_list(int epoll_fd) { - gpr_once_init(&init_epoll_fd_list_mu, init_mu); - - gpr_mu_lock(&epoll_fd_list_mu); - if (epoll_fd_global_list.count == epoll_fd_global_list.capacity) { - epoll_fd_global_list.capacity = - GPR_MAX((size_t)8, epoll_fd_global_list.capacity * 2); - epoll_fd_global_list.epoll_fds = - gpr_realloc(epoll_fd_global_list.epoll_fds, - epoll_fd_global_list.capacity * sizeof(int)); - } - epoll_fd_global_list.epoll_fds[epoll_fd_global_list.count++] = epoll_fd; - gpr_mu_unlock(&epoll_fd_list_mu); -} - -static void remove_epoll_fd_from_global_list(int epoll_fd) { - gpr_mu_lock(&epoll_fd_list_mu); - GPR_ASSERT(epoll_fd_global_list.count > 0); - for (size_t i = 0; i < epoll_fd_global_list.count; i++) { - if (epoll_fd == epoll_fd_global_list.epoll_fds[i]) { - epoll_fd_global_list.epoll_fds[i] = - epoll_fd_global_list.epoll_fds[--(epoll_fd_global_list.count)]; - break; - } - } - gpr_mu_unlock(&epoll_fd_list_mu); -} - -void grpc_remove_fd_from_all_epoll_sets(int fd) { - int err; - gpr_once_init(&init_epoll_fd_list_mu, init_mu); - gpr_mu_lock(&epoll_fd_list_mu); - if (epoll_fd_global_list.count == 0) { - gpr_mu_unlock(&epoll_fd_list_mu); - return; - } - for (size_t i = 0; i < epoll_fd_global_list.count; i++) { - err = epoll_ctl(epoll_fd_global_list.epoll_fds[i], EPOLL_CTL_DEL, fd, NULL); - if (err < 0 && errno != ENOENT) { - gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd, - strerror(errno)); - } - } - gpr_mu_unlock(&epoll_fd_list_mu); -} - -typedef struct { - grpc_pollset *pollset; - grpc_fd *fd; - grpc_closure closure; -} delayed_add; - -typedef struct { int epoll_fd; } pollset_hdr; - -static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd) { - pollset_hdr *h = pollset->data.ptr; - struct epoll_event ev; - int err; - grpc_fd_watcher watcher; - - /* We pretend to be polling whilst adding an fd to keep the fd from being - closed during the add. This may result in a spurious wakeup being assigned - to this pollset whilst adding, but that should be benign. */ - GPR_ASSERT(grpc_fd_begin_poll(fd, pollset, NULL, 0, 0, &watcher) == 0); - if (watcher.fd != NULL) { - ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET); - ev.data.ptr = fd; - err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, fd->fd, &ev); - if (err < 0) { - /* FDs may be added to a pollset multiple times, so EEXIST is normal. */ - if (errno != EEXIST) { - gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", fd->fd, - strerror(errno)); - } - } - } - grpc_fd_end_poll(exec_ctx, &watcher, 0, 0); -} - -static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg, - bool iomgr_status) { - delayed_add *da = arg; - - if (!grpc_fd_is_orphaned(da->fd)) { - finally_add_fd(exec_ctx, da->pollset, da->fd); - } - - gpr_mu_lock(&da->pollset->mu); - da->pollset->in_flight_cbs--; - if (da->pollset->shutting_down) { - /* We don't care about this pollset anymore. */ - if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) { - da->pollset->called_shutdown = 1; - grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, true, NULL); - } - } - gpr_mu_unlock(&da->pollset->mu); - - GRPC_FD_UNREF(da->fd, "delayed_add"); - - gpr_free(da); -} - -static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_fd *fd, - int and_unlock_pollset) { - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - finally_add_fd(exec_ctx, pollset, fd); - } else { - delayed_add *da = gpr_malloc(sizeof(*da)); - da->pollset = pollset; - da->fd = fd; - GRPC_FD_REF(fd, "delayed_add"); - grpc_closure_init(&da->closure, perform_delayed_add, da); - pollset->in_flight_cbs++; - grpc_exec_ctx_enqueue(exec_ctx, &da->closure, true, NULL); - } -} - -/* TODO(klempner): We probably want to turn this down a bit */ -#define GRPC_EPOLL_MAX_EVENTS 1000 - -static void multipoll_with_epoll_pollset_maybe_work_and_unlock( - grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now) { - struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; - int ep_rv; - int poll_rv; - pollset_hdr *h = pollset->data.ptr; - int timeout_ms; - struct pollfd pfds[2]; - - /* If you want to ignore epoll's ability to sanely handle parallel pollers, - * for a more apples-to-apples performance comparison with poll, add a - * if (pollset->counter != 0) { return 0; } - * here. - */ - - gpr_mu_unlock(&pollset->mu); - - timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now); - - pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfds[0].events = POLLIN; - pfds[0].revents = 0; - pfds[1].fd = h->epoll_fd; - pfds[1].events = POLLIN; - pfds[1].revents = 0; - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - GPR_TIMER_BEGIN("poll", 0); - GRPC_SCHEDULING_START_BLOCKING_REGION; - poll_rv = grpc_poll_function(pfds, 2, timeout_ms); - GRPC_SCHEDULING_END_BLOCKING_REGION; - GPR_TIMER_END("poll", 0); - - if (poll_rv < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - } else if (poll_rv == 0) { - /* do nothing */ - } else { - if (pfds[0].revents) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - if (pfds[1].revents) { - do { - /* The following epoll_wait never blocks; it has a timeout of 0 */ - ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0); - if (ep_rv < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "epoll_wait() failed: %s", strerror(errno)); - } - } else { - int i; - for (i = 0; i < ep_rv; ++i) { - grpc_fd *fd = ep_ev[i].data.ptr; - /* TODO(klempner): We might want to consider making err and pri - * separate events */ - int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); - int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); - int write_ev = ep_ev[i].events & EPOLLOUT; - if (fd == NULL) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } else { - if (read_ev || cancel) { - grpc_fd_become_readable(exec_ctx, fd); - } - if (write_ev || cancel) { - grpc_fd_become_writable(exec_ctx, fd); - } - } - } - } - } while (ep_rv == GRPC_EPOLL_MAX_EVENTS); - } - } -} - -static void multipoll_with_epoll_pollset_finish_shutdown( - grpc_pollset *pollset) {} - -static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) { - pollset_hdr *h = pollset->data.ptr; - close(h->epoll_fd); - remove_epoll_fd_from_global_list(h->epoll_fd); - gpr_free(h); -} - -static const grpc_pollset_vtable multipoll_with_epoll_pollset = { - multipoll_with_epoll_pollset_add_fd, - multipoll_with_epoll_pollset_maybe_work_and_unlock, - multipoll_with_epoll_pollset_finish_shutdown, - multipoll_with_epoll_pollset_destroy}; - -static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, grpc_fd **fds, - size_t nfds) { - size_t i; - pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); - struct epoll_event ev; - int err; - - pollset->vtable = &multipoll_with_epoll_pollset; - pollset->data.ptr = h; - h->epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (h->epoll_fd < 0) { - /* TODO(klempner): Fall back to poll here, especially on ENOSYS */ - gpr_log(GPR_ERROR, "epoll_create1 failed: %s", strerror(errno)); - abort(); - } - add_epoll_fd_to_global_list(h->epoll_fd); - - ev.events = (uint32_t)(EPOLLIN | EPOLLET); - ev.data.ptr = NULL; - err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, - GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), &ev); - if (err < 0) { - gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", - GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), - strerror(errno)); - } - - for (i = 0; i < nfds; i++) { - multipoll_with_epoll_pollset_add_fd(exec_ctx, pollset, fds[i], 0); - } -} - -grpc_platform_become_multipoller_type grpc_platform_become_multipoller = - epoll_become_multipoller; - -#else /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */ - -void grpc_remove_fd_from_all_epoll_sets(int fd) {} - -#endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */ diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c deleted file mode 100644 index 92d6fb7241..0000000000 --- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/pollset_posix.h" - -#include <errno.h> -#include <poll.h> -#include <stdlib.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/support/block_annotate.h" - -typedef struct { - /* all polled fds */ - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; - /* fds that have been removed from the pollset explicitly */ - size_t del_count; - size_t del_capacity; - grpc_fd **dels; -} pollset_hdr; - -static void multipoll_with_poll_pollset_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_fd *fd, - int and_unlock_pollset) { - size_t i; - pollset_hdr *h = pollset->data.ptr; - /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */ - for (i = 0; i < h->fd_count; i++) { - if (h->fds[i] == fd) goto exit; - } - if (h->fd_count == h->fd_capacity) { - h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2); - h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity); - } - h->fds[h->fd_count++] = fd; - GRPC_FD_REF(fd, "multipoller"); -exit: - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - } -} - -static void multipoll_with_poll_pollset_maybe_work_and_unlock( - grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now) { -#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR) -#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR) - - int timeout; - int r; - size_t i, j, fd_count; - nfds_t pfd_count; - pollset_hdr *h; - /* TODO(ctiller): inline some elements to avoid an allocation */ - grpc_fd_watcher *watchers; - struct pollfd *pfds; - - h = pollset->data.ptr; - timeout = grpc_poll_deadline_to_millis_timeout(deadline, now); - /* TODO(ctiller): perform just one malloc here if we exceed the inline case */ - pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 2)); - watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 2)); - fd_count = 0; - pfd_count = 2; - pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd); - pfds[0].events = POLLIN; - pfds[0].revents = 0; - pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfds[1].events = POLLIN; - pfds[1].revents = 0; - for (i = 0; i < h->fd_count; i++) { - int remove = grpc_fd_is_orphaned(h->fds[i]); - for (j = 0; !remove && j < h->del_count; j++) { - if (h->fds[i] == h->dels[j]) remove = 1; - } - if (remove) { - GRPC_FD_UNREF(h->fds[i], "multipoller"); - } else { - h->fds[fd_count++] = h->fds[i]; - watchers[pfd_count].fd = h->fds[i]; - GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start"); - pfds[pfd_count].fd = h->fds[i]->fd; - pfds[pfd_count].revents = 0; - pfd_count++; - } - } - for (j = 0; j < h->del_count; j++) { - GRPC_FD_UNREF(h->dels[j], "multipoller_del"); - } - h->del_count = 0; - h->fd_count = fd_count; - gpr_mu_unlock(&pollset->mu); - - for (i = 2; i < pfd_count; i++) { - grpc_fd *fd = watchers[i].fd; - pfds[i].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN, - POLLOUT, &watchers[i]); - GRPC_FD_UNREF(fd, "multipoller_start"); - } - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - GRPC_SCHEDULING_START_BLOCKING_REGION; - r = grpc_poll_function(pfds, pfd_count, timeout); - GRPC_SCHEDULING_END_BLOCKING_REGION; - - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - for (i = 2; i < pfd_count; i++) { - grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0); - } - } else if (r == 0) { - for (i = 2; i < pfd_count; i++) { - grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0); - } - } else { - if (pfds[0].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } - if (pfds[1].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - for (i = 2; i < pfd_count; i++) { - if (watchers[i].fd == NULL) { - grpc_fd_end_poll(exec_ctx, &watchers[i], 0, 0); - continue; - } - grpc_fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK, - pfds[i].revents & POLLOUT_CHECK); - } - } - - gpr_free(pfds); - gpr_free(watchers); -} - -static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) { - size_t i; - pollset_hdr *h = pollset->data.ptr; - for (i = 0; i < h->fd_count; i++) { - GRPC_FD_UNREF(h->fds[i], "multipoller"); - } - for (i = 0; i < h->del_count; i++) { - GRPC_FD_UNREF(h->dels[i], "multipoller_del"); - } - h->fd_count = 0; - h->del_count = 0; -} - -static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) { - pollset_hdr *h = pollset->data.ptr; - multipoll_with_poll_pollset_finish_shutdown(pollset); - gpr_free(h->fds); - gpr_free(h->dels); - gpr_free(h); -} - -static const grpc_pollset_vtable multipoll_with_poll_pollset = { - multipoll_with_poll_pollset_add_fd, - multipoll_with_poll_pollset_maybe_work_and_unlock, - multipoll_with_poll_pollset_finish_shutdown, - multipoll_with_poll_pollset_destroy}; - -void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, grpc_fd **fds, - size_t nfds) { - size_t i; - pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); - pollset->vtable = &multipoll_with_poll_pollset; - pollset->data.ptr = h; - h->fd_count = nfds; - h->fd_capacity = nfds; - h->fds = gpr_malloc(nfds * sizeof(grpc_fd *)); - h->del_count = 0; - h->del_capacity = 0; - h->dels = NULL; - for (i = 0; i < nfds; i++) { - h->fds[i] = fds[i]; - GRPC_FD_REF(fds[i], "multipoller"); - } -} - -#endif /* GPR_POSIX_SOCKET */ - -#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL -grpc_platform_become_multipoller_type grpc_platform_become_multipoller = - grpc_poll_become_multipoller; -#endif diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c deleted file mode 100644 index e895a77884..0000000000 --- a/src/core/iomgr/pollset_posix.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/pollset_posix.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/thd.h> -#include <grpc/support/tls.h> -#include <grpc/support/useful.h> -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/socket_utils_posix.h" -#include "src/core/profiling/timers.h" -#include "src/core/support/block_annotate.h" - -GPR_TLS_DECL(g_current_thread_poller); -GPR_TLS_DECL(g_current_thread_worker); - -/** Default poll() function - a pointer so that it can be overridden by some - * tests */ -grpc_poll_function_type grpc_poll_function = poll; - -/** The alarm system needs to be able to wakeup 'some poller' sometimes - * (specifically when a new alarm needs to be triggered earlier than the next - * alarm 'epoch'). - * This wakeup_fd gives us something to alert on when such a case occurs. */ -grpc_wakeup_fd grpc_global_wakeup_fd; - -static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->prev->next = worker->next; - worker->next->prev = worker->prev; -} - -int grpc_pollset_has_workers(grpc_pollset *p) { - return p->root_worker.next != &p->root_worker; -} - -static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { - if (grpc_pollset_has_workers(p)) { - grpc_pollset_worker *w = p->root_worker.next; - remove_worker(p, w); - return w; - } else { - return NULL; - } -} - -static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->next = &p->root_worker; - worker->prev = worker->next->prev; - worker->prev->next = worker->next->prev = worker; -} - -static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->prev = &p->root_worker; - worker->next = worker->prev->next; - worker->prev->next = worker->next->prev = worker; -} - -size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); } - -void grpc_pollset_kick_ext(grpc_pollset *p, - grpc_pollset_worker *specific_worker, - uint32_t flags) { - GPR_TIMER_BEGIN("grpc_pollset_kick_ext", 0); - - /* pollset->mu already held */ - if (specific_worker != NULL) { - if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { - GPR_TIMER_BEGIN("grpc_pollset_kick_ext.broadcast", 0); - GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); - for (specific_worker = p->root_worker.next; - specific_worker != &p->root_worker; - specific_worker = specific_worker->next) { - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - p->kicked_without_pollers = 1; - GPR_TIMER_END("grpc_pollset_kick_ext.broadcast", 0); - } else if (gpr_tls_get(&g_current_thread_worker) != - (intptr_t)specific_worker) { - GPR_TIMER_MARK("different_thread_worker", 0); - if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { - specific_worker->reevaluate_polling_on_wakeup = 1; - } - specific_worker->kicked_specifically = 1; - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) { - GPR_TIMER_MARK("kick_yoself", 0); - if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { - specific_worker->reevaluate_polling_on_wakeup = 1; - } - specific_worker->kicked_specifically = 1; - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) { - GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); - GPR_TIMER_MARK("kick_anonymous", 0); - specific_worker = pop_front_worker(p); - if (specific_worker != NULL) { - if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) { - GPR_TIMER_MARK("kick_anonymous_not_self", 0); - push_back_worker(p, specific_worker); - specific_worker = pop_front_worker(p); - if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 && - gpr_tls_get(&g_current_thread_worker) == - (intptr_t)specific_worker) { - push_back_worker(p, specific_worker); - specific_worker = NULL; - } - } - if (specific_worker != NULL) { - GPR_TIMER_MARK("finally_kick", 0); - push_back_worker(p, specific_worker); - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - } else { - GPR_TIMER_MARK("kicked_no_pollers", 0); - p->kicked_without_pollers = 1; - } - } - - GPR_TIMER_END("grpc_pollset_kick_ext", 0); -} - -void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) { - grpc_pollset_kick_ext(p, specific_worker, 0); -} - -/* global state management */ - -void grpc_pollset_global_init(void) { - gpr_tls_init(&g_current_thread_poller); - gpr_tls_init(&g_current_thread_worker); - grpc_wakeup_fd_global_init(); - grpc_wakeup_fd_init(&grpc_global_wakeup_fd); -} - -void grpc_pollset_global_shutdown(void) { - grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd); - gpr_tls_destroy(&g_current_thread_poller); - gpr_tls_destroy(&g_current_thread_worker); - grpc_wakeup_fd_global_destroy(); -} - -void grpc_kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); } - -/* main interface */ - -static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null); - -void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { - gpr_mu_init(&pollset->mu); - *mu = &pollset->mu; - pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; - pollset->in_flight_cbs = 0; - pollset->shutting_down = 0; - pollset->called_shutdown = 0; - pollset->kicked_without_pollers = 0; - pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL; - pollset->local_wakeup_cache = NULL; - pollset->kicked_without_pollers = 0; - become_basic_pollset(pollset, NULL); -} - -void grpc_pollset_destroy(grpc_pollset *pollset) { - GPR_ASSERT(pollset->in_flight_cbs == 0); - GPR_ASSERT(!grpc_pollset_has_workers(pollset)); - GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); - pollset->vtable->destroy(pollset); - while (pollset->local_wakeup_cache) { - grpc_cached_wakeup_fd *next = pollset->local_wakeup_cache->next; - grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd); - gpr_free(pollset->local_wakeup_cache); - pollset->local_wakeup_cache = next; - } -} - -void grpc_pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT(pollset->in_flight_cbs == 0); - GPR_ASSERT(!grpc_pollset_has_workers(pollset)); - GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); - pollset->vtable->destroy(pollset); - pollset->shutting_down = 0; - pollset->called_shutdown = 0; - pollset->kicked_without_pollers = 0; - become_basic_pollset(pollset, NULL); -} - -void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd) { - gpr_mu_lock(&pollset->mu); - pollset->vtable->add_fd(exec_ctx, pollset, fd, 1); -/* the following (enabled only in debug) will reacquire and then release - our lock - meaning that if the unlocking flag passed to add_fd above is - not respected, the code will deadlock (in a way that we have a chance of - debugging) */ -#ifndef NDEBUG - gpr_mu_lock(&pollset->mu); - gpr_mu_unlock(&pollset->mu); -#endif -} - -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { - GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs)); - pollset->vtable->finish_shutdown(pollset); - grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL); -} - -void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker **worker_hdl, gpr_timespec now, - gpr_timespec deadline) { - grpc_pollset_worker worker; - *worker_hdl = &worker; - - /* pollset->mu already held */ - int added_worker = 0; - int locked = 1; - int queued_work = 0; - int keep_polling = 0; - GPR_TIMER_BEGIN("grpc_pollset_work", 0); - /* this must happen before we (potentially) drop pollset->mu */ - worker.next = worker.prev = NULL; - worker.reevaluate_polling_on_wakeup = 0; - if (pollset->local_wakeup_cache != NULL) { - worker.wakeup_fd = pollset->local_wakeup_cache; - pollset->local_wakeup_cache = worker.wakeup_fd->next; - } else { - worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd)); - grpc_wakeup_fd_init(&worker.wakeup_fd->fd); - } - worker.kicked_specifically = 0; - /* If there's work waiting for the pollset to be idle, and the - pollset is idle, then do that work */ - if (!grpc_pollset_has_workers(pollset) && - !grpc_closure_list_empty(pollset->idle_jobs)) { - GPR_TIMER_MARK("grpc_pollset_work.idle_jobs", 0); - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - goto done; - } - /* If we're shutting down then we don't execute any extended work */ - if (pollset->shutting_down) { - GPR_TIMER_MARK("grpc_pollset_work.shutting_down", 0); - goto done; - } - /* Give do_promote priority so we don't starve it out */ - if (pollset->in_flight_cbs) { - GPR_TIMER_MARK("grpc_pollset_work.in_flight_cbs", 0); - gpr_mu_unlock(&pollset->mu); - locked = 0; - goto done; - } - /* Start polling, and keep doing so while we're being asked to - re-evaluate our pollers (this allows poll() based pollers to - ensure they don't miss wakeups) */ - keep_polling = 1; - while (keep_polling) { - keep_polling = 0; - if (!pollset->kicked_without_pollers) { - if (!added_worker) { - push_front_worker(pollset, &worker); - added_worker = 1; - gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); - } - gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset); - GPR_TIMER_BEGIN("maybe_work_and_unlock", 0); - pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker, - deadline, now); - GPR_TIMER_END("maybe_work_and_unlock", 0); - locked = 0; - gpr_tls_set(&g_current_thread_poller, 0); - } else { - GPR_TIMER_MARK("grpc_pollset_work.kicked_without_pollers", 0); - pollset->kicked_without_pollers = 0; - } - /* Finished execution - start cleaning up. - Note that we may arrive here from outside the enclosing while() loop. - In that case we won't loop though as we haven't added worker to the - worker list, which means nobody could ask us to re-evaluate polling). */ - done: - if (!locked) { - queued_work |= grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); - locked = 1; - } - /* If we're forced to re-evaluate polling (via grpc_pollset_kick with - GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force - a loop */ - if (worker.reevaluate_polling_on_wakeup) { - worker.reevaluate_polling_on_wakeup = 0; - pollset->kicked_without_pollers = 0; - if (queued_work || worker.kicked_specifically) { - /* If there's queued work on the list, then set the deadline to be - immediate so we get back out of the polling loop quickly */ - deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); - } - keep_polling = 1; - } - } - if (added_worker) { - remove_worker(pollset, &worker); - gpr_tls_set(&g_current_thread_worker, 0); - } - /* release wakeup fd to the local pool */ - worker.wakeup_fd->next = pollset->local_wakeup_cache; - pollset->local_wakeup_cache = worker.wakeup_fd; - /* check shutdown conditions */ - if (pollset->shutting_down) { - if (grpc_pollset_has_workers(pollset)) { - grpc_pollset_kick(pollset, NULL); - } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) { - pollset->called_shutdown = 1; - gpr_mu_unlock(&pollset->mu); - finish_shutdown(exec_ctx, pollset); - grpc_exec_ctx_flush(exec_ctx); - /* Continuing to access pollset here is safe -- it is the caller's - * responsibility to not destroy when it has outstanding calls to - * grpc_pollset_work. - * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */ - gpr_mu_lock(&pollset->mu); - } else if (!grpc_closure_list_empty(pollset->idle_jobs)) { - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - gpr_mu_unlock(&pollset->mu); - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); - } - } - *worker_hdl = NULL; - GPR_TIMER_END("grpc_pollset_work", 0); -} - -void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_closure *closure) { - GPR_ASSERT(!pollset->shutting_down); - pollset->shutting_down = 1; - pollset->shutdown_done = closure; - grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - if (!grpc_pollset_has_workers(pollset)) { - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - } - if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 && - !grpc_pollset_has_workers(pollset)) { - pollset->called_shutdown = 1; - finish_shutdown(exec_ctx, pollset); - } -} - -int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, - gpr_timespec now) { - gpr_timespec timeout; - static const int64_t max_spin_polling_us = 10; - if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { - return -1; - } - if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( - max_spin_polling_us, - GPR_TIMESPAN))) <= 0) { - return 0; - } - timeout = gpr_time_sub(deadline, now); - return gpr_time_to_millis(gpr_time_add( - timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); -} - -/* - * basic_pollset - a vtable that provides polling for zero or one file - * descriptor via poll() - */ - -typedef struct grpc_unary_promote_args { - const grpc_pollset_vtable *original_vtable; - grpc_pollset *pollset; - grpc_fd *fd; - grpc_closure promotion_closure; -} grpc_unary_promote_args; - -static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args, - bool success) { - grpc_unary_promote_args *up_args = args; - const grpc_pollset_vtable *original_vtable = up_args->original_vtable; - grpc_pollset *pollset = up_args->pollset; - grpc_fd *fd = up_args->fd; - - /* - * This is quite tricky. There are a number of cases to keep in mind here: - * 1. fd may have been orphaned - * 2. The pollset may no longer be a unary poller (and we can't let case #1 - * leak to other pollset types!) - * 3. pollset's fd (which may have changed) may have been orphaned - * 4. The pollset may be shutting down. - */ - - gpr_mu_lock(&pollset->mu); - /* First we need to ensure that nobody is polling concurrently */ - GPR_ASSERT(!grpc_pollset_has_workers(pollset)); - - gpr_free(up_args); - /* At this point the pollset may no longer be a unary poller. In that case - * we should just call the right add function and be done. */ - /* TODO(klempner): If we're not careful this could cause infinite recursion. - * That's not a problem for now because empty_pollset has a trivial poller - * and we don't have any mechanism to unbecome multipoller. */ - pollset->in_flight_cbs--; - if (pollset->shutting_down) { - /* We don't care about this pollset anymore. */ - if (pollset->in_flight_cbs == 0 && !pollset->called_shutdown) { - pollset->called_shutdown = 1; - finish_shutdown(exec_ctx, pollset); - } - } else if (grpc_fd_is_orphaned(fd)) { - /* Don't try to add it to anything, we'll drop our ref on it below */ - } else if (pollset->vtable != original_vtable) { - pollset->vtable->add_fd(exec_ctx, pollset, fd, 0); - } else if (fd != pollset->data.ptr) { - grpc_fd *fds[2]; - fds[0] = pollset->data.ptr; - fds[1] = fd; - - if (fds[0] && !grpc_fd_is_orphaned(fds[0])) { - grpc_platform_become_multipoller(exec_ctx, pollset, fds, - GPR_ARRAY_SIZE(fds)); - GRPC_FD_UNREF(fds[0], "basicpoll"); - } else { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - /* Note that it is possible that fds[1] is also orphaned at this point. - * That's okay, we'll correct it at the next add or poll. */ - if (fds[0]) GRPC_FD_UNREF(fds[0], "basicpoll"); - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } - } - - gpr_mu_unlock(&pollset->mu); - - /* Matching ref in basic_pollset_add_fd */ - GRPC_FD_UNREF(fd, "basicpoll_add"); -} - -static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd, int and_unlock_pollset) { - grpc_unary_promote_args *up_args; - GPR_ASSERT(fd); - if (fd == pollset->data.ptr) goto exit; - - if (!grpc_pollset_has_workers(pollset)) { - /* Fast path -- no in flight cbs */ - /* TODO(klempner): Comment this out and fix any test failures or establish - * they are due to timing issues */ - grpc_fd *fds[2]; - fds[0] = pollset->data.ptr; - fds[1] = fd; - - if (fds[0] == NULL) { - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } else if (!grpc_fd_is_orphaned(fds[0])) { - grpc_platform_become_multipoller(exec_ctx, pollset, fds, - GPR_ARRAY_SIZE(fds)); - GRPC_FD_UNREF(fds[0], "basicpoll"); - } else { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - GRPC_FD_UNREF(fds[0], "basicpoll"); - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } - goto exit; - } - - /* Now we need to promote. This needs to happen when we're not polling. Since - * this may be called from poll, the wait needs to happen asynchronously. */ - GRPC_FD_REF(fd, "basicpoll_add"); - pollset->in_flight_cbs++; - up_args = gpr_malloc(sizeof(*up_args)); - up_args->fd = fd; - up_args->original_vtable = pollset->vtable; - up_args->pollset = pollset; - up_args->promotion_closure.cb = basic_do_promote; - up_args->promotion_closure.cb_arg = up_args; - - grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1); - grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - -exit: - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - } -} - -static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_pollset_worker *worker, - gpr_timespec deadline, - gpr_timespec now) { -#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR) -#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR) - - struct pollfd pfd[3]; - grpc_fd *fd; - grpc_fd_watcher fd_watcher; - int timeout; - int r; - nfds_t nfds; - - fd = pollset->data.ptr; - if (fd && grpc_fd_is_orphaned(fd)) { - GRPC_FD_UNREF(fd, "basicpoll"); - fd = pollset->data.ptr = NULL; - } - timeout = grpc_poll_deadline_to_millis_timeout(deadline, now); - pfd[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd); - pfd[0].events = POLLIN; - pfd[0].revents = 0; - pfd[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfd[1].events = POLLIN; - pfd[1].revents = 0; - nfds = 2; - if (fd) { - pfd[2].fd = fd->fd; - pfd[2].revents = 0; - GRPC_FD_REF(fd, "basicpoll_begin"); - gpr_mu_unlock(&pollset->mu); - pfd[2].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN, - POLLOUT, &fd_watcher); - if (pfd[2].events != 0) { - nfds++; - } - } else { - gpr_mu_unlock(&pollset->mu); - } - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - /* poll fd count (argument 2) is shortened by one if we have no events - to poll on - such that it only includes the kicker */ - GPR_TIMER_BEGIN("poll", 0); - GRPC_SCHEDULING_START_BLOCKING_REGION; - r = grpc_poll_function(pfd, nfds, timeout); - GRPC_SCHEDULING_END_BLOCKING_REGION; - GPR_TIMER_END("poll", 0); - - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - if (fd) { - grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0); - } - } else if (r == 0) { - if (fd) { - grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0); - } - } else { - if (pfd[0].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } - if (pfd[1].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - if (nfds > 2) { - grpc_fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK, - pfd[2].revents & POLLOUT_CHECK); - } else if (fd) { - grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0); - } - } - - if (fd) { - GRPC_FD_UNREF(fd, "basicpoll_begin"); - } -} - -static void basic_pollset_destroy(grpc_pollset *pollset) { - if (pollset->data.ptr != NULL) { - GRPC_FD_UNREF(pollset->data.ptr, "basicpoll"); - pollset->data.ptr = NULL; - } -} - -static const grpc_pollset_vtable basic_pollset = { - basic_pollset_add_fd, basic_pollset_maybe_work_and_unlock, - basic_pollset_destroy, basic_pollset_destroy}; - -static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) { - pollset->vtable = &basic_pollset; - pollset->data.ptr = fd_or_null; - if (fd_or_null != NULL) { - GRPC_FD_REF(fd_or_null, "basicpoll"); - } -} - -#endif /* GPR_POSIX_POLLSET */ diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h deleted file mode 100644 index bbedb66b00..0000000000 --- a/src/core/iomgr/pollset_posix.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H - -#include <poll.h> - -#include <grpc/support/sync.h> - -#include "src/core/iomgr/exec_ctx.h" -#include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/pollset.h" -#include "src/core/iomgr/wakeup_fd_posix.h" - -typedef struct grpc_pollset_vtable grpc_pollset_vtable; - -/* forward declare only in this file to avoid leaking impl details via - pollset.h; real users of grpc_fd should always include 'fd_posix.h' and not - use the struct tag */ -struct grpc_fd; - -typedef struct grpc_cached_wakeup_fd { - grpc_wakeup_fd fd; - struct grpc_cached_wakeup_fd *next; -} grpc_cached_wakeup_fd; - -struct grpc_pollset_worker { - grpc_cached_wakeup_fd *wakeup_fd; - int reevaluate_polling_on_wakeup; - int kicked_specifically; - struct grpc_pollset_worker *next; - struct grpc_pollset_worker *prev; -}; - -struct grpc_pollset { - /* pollsets under posix can mutate representation as fds are added and - removed. - For example, we may choose a poll() based implementation on linux for - few fds, and an epoll() based implementation for many fds */ - const grpc_pollset_vtable *vtable; - gpr_mu mu; - grpc_pollset_worker root_worker; - int in_flight_cbs; - int shutting_down; - int called_shutdown; - int kicked_without_pollers; - grpc_closure *shutdown_done; - grpc_closure_list idle_jobs; - union { - int fd; - void *ptr; - } data; - /* Local cache of eventfds for workers */ - grpc_cached_wakeup_fd *local_wakeup_cache; -}; - -struct grpc_pollset_vtable { - void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - struct grpc_fd *fd, int and_unlock_pollset); - void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now); - void (*finish_shutdown)(grpc_pollset *pollset); - void (*destroy)(grpc_pollset *pollset); -}; - -/* Add an fd to a pollset */ -void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - struct grpc_fd *fd); - -/* Returns the fd to listen on for kicks */ -int grpc_kick_read_fd(grpc_pollset *p); -/* Call after polling has been kicked to leave the kicked state */ -void grpc_kick_drain(grpc_pollset *p); - -/* Convert a timespec to milliseconds: - - very small or negative poll times are clamped to zero to do a - non-blocking poll (which becomes spin polling) - - other small values are rounded up to one millisecond - - longer than a millisecond polls are rounded up to the next nearest - millisecond to avoid spinning - - infinite timeouts are converted to -1 */ -int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, - gpr_timespec now); - -/* Allow kick to wakeup the currently polling worker */ -#define GRPC_POLLSET_CAN_KICK_SELF 1 -/* Force the wakee to repoll when awoken */ -#define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2 -/* As per grpc_pollset_kick, with an extended set of flags (defined above) - -- mostly for fd_posix's use. */ -void grpc_pollset_kick_ext(grpc_pollset *p, - grpc_pollset_worker *specific_worker, - uint32_t flags); - -/* turn a pollset into a multipoller: platform specific */ -typedef void (*grpc_platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - struct grpc_fd **fds, - size_t fd_count); -extern grpc_platform_become_multipoller_type grpc_platform_become_multipoller; - -void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, struct grpc_fd **fds, - size_t fd_count); - -/* Return 1 if the pollset has active threads in grpc_pollset_work (pollset must - * be locked) */ -int grpc_pollset_has_workers(grpc_pollset *pollset); - -void grpc_remove_fd_from_all_epoll_sets(int fd); - -/* override to allow tests to hook poll() usage */ -/* NOTE: Any changes to grpc_poll_function must take place when the gRPC - is certainly not doing any polling anywhere. - Otherwise, there might be a race between changing the variable and actually - doing a polling operation */ -typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int); -extern grpc_poll_function_type grpc_poll_function; -extern grpc_wakeup_fd grpc_global_wakeup_fd; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H */ diff --git a/src/core/iomgr/pollset_set.h b/src/core/iomgr/pollset_set.h deleted file mode 100644 index dddcd8313f..0000000000 --- a/src/core/iomgr/pollset_set.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_H - -#include "src/core/iomgr/pollset.h" - -/* A grpc_pollset_set is a set of pollsets that are interested in an - action. Adding a pollset to a pollset_set automatically adds any - fd's (etc) that have been registered with the set_set to that pollset. - Registering fd's automatically adds them to all current pollsets. */ - -typedef struct grpc_pollset_set grpc_pollset_set; - -grpc_pollset_set *grpc_pollset_set_create(void); -void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set); -void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset); -void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset); -void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item); -void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_H */ diff --git a/src/core/iomgr/pollset_set_posix.c b/src/core/iomgr/pollset_set_posix.c deleted file mode 100644 index 9dc9aff4a8..0000000000 --- a/src/core/iomgr/pollset_set_posix.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include <stdlib.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/iomgr/pollset_set_posix.h" - -struct grpc_pollset_set { - gpr_mu mu; - - size_t pollset_count; - size_t pollset_capacity; - grpc_pollset **pollsets; - - size_t pollset_set_count; - size_t pollset_set_capacity; - struct grpc_pollset_set **pollset_sets; - - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; -}; - -grpc_pollset_set *grpc_pollset_set_create(void) { - grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set)); - memset(pollset_set, 0, sizeof(*pollset_set)); - gpr_mu_init(&pollset_set->mu); - return pollset_set; -} - -void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) { - size_t i; - gpr_mu_destroy(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); - } - gpr_free(pollset_set->pollsets); - gpr_free(pollset_set->pollset_sets); - gpr_free(pollset_set->fds); - gpr_free(pollset_set); -} - -void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i, j; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->pollset_count == pollset_set->pollset_capacity) { - pollset_set->pollset_capacity = - GPR_MAX(8, 2 * pollset_set->pollset_capacity); - pollset_set->pollsets = - gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity * - sizeof(*pollset_set->pollsets)); - } - pollset_set->pollsets[pollset_set->pollset_count++] = pollset; - for (i = 0, j = 0; i < pollset_set->fd_count; i++) { - if (grpc_fd_is_orphaned(pollset_set->fds[i])) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); - } else { - grpc_pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]); - pollset_set->fds[j++] = pollset_set->fds[i]; - } - } - pollset_set->fd_count = j; - gpr_mu_unlock(&pollset_set->mu); -} - -void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->pollset_count; i++) { - if (pollset_set->pollsets[i] == pollset) { - pollset_set->pollset_count--; - GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i], - pollset_set->pollsets[pollset_set->pollset_count]); - break; - } - } - gpr_mu_unlock(&pollset_set->mu); -} - -void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item) { - size_t i, j; - gpr_mu_lock(&bag->mu); - if (bag->pollset_set_count == bag->pollset_set_capacity) { - bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity); - bag->pollset_sets = - gpr_realloc(bag->pollset_sets, - bag->pollset_set_capacity * sizeof(*bag->pollset_sets)); - } - bag->pollset_sets[bag->pollset_set_count++] = item; - for (i = 0, j = 0; i < bag->fd_count; i++) { - if (grpc_fd_is_orphaned(bag->fds[i])) { - GRPC_FD_UNREF(bag->fds[i], "pollset_set"); - } else { - grpc_pollset_set_add_fd(exec_ctx, item, bag->fds[i]); - bag->fds[j++] = bag->fds[i]; - } - } - bag->fd_count = j; - gpr_mu_unlock(&bag->mu); -} - -void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item) { - size_t i; - gpr_mu_lock(&bag->mu); - for (i = 0; i < bag->pollset_set_count; i++) { - if (bag->pollset_sets[i] == item) { - bag->pollset_set_count--; - GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i], - bag->pollset_sets[bag->pollset_set_count]); - break; - } - } - gpr_mu_unlock(&bag->mu); -} - -void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->fd_count == pollset_set->fd_capacity) { - pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity); - pollset_set->fds = gpr_realloc( - pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds)); - } - GRPC_FD_REF(fd, "pollset_set"); - pollset_set->fds[pollset_set->fd_count++] = fd; - for (i = 0; i < pollset_set->pollset_count; i++) { - grpc_pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd); - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - grpc_pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); -} - -void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - if (pollset_set->fds[i] == fd) { - pollset_set->fd_count--; - GPR_SWAP(grpc_fd *, pollset_set->fds[i], - pollset_set->fds[pollset_set->fd_count]); - GRPC_FD_UNREF(fd, "pollset_set"); - break; - } - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - grpc_pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); -} - -#endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/iomgr/pollset_set_posix.h b/src/core/iomgr/pollset_set_posix.h deleted file mode 100644 index 7d1aaf4181..0000000000 --- a/src/core/iomgr/pollset_set_posix.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_POSIX_H - -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/pollset_set.h" - -void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd); -void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */ diff --git a/src/core/iomgr/pollset_set_windows.c b/src/core/iomgr/pollset_set_windows.c deleted file mode 100644 index 3b8eca28e6..0000000000 --- a/src/core/iomgr/pollset_set_windows.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include "src/core/iomgr/pollset_set_windows.h" - -grpc_pollset_set* grpc_pollset_set_create(pollset_set) { return NULL; } - -void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {} - -void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, - grpc_pollset_set* pollset_set, - grpc_pollset* pollset) {} - -void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx, - grpc_pollset_set* pollset_set, - grpc_pollset* pollset) {} - -void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx, - grpc_pollset_set* bag, - grpc_pollset_set* item) {} - -void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx, - grpc_pollset_set* bag, - grpc_pollset_set* item) {} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/pollset_set_windows.h b/src/core/iomgr/pollset_set_windows.h deleted file mode 100644 index 9661cd2c39..0000000000 --- a/src/core/iomgr/pollset_set_windows.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_WINDOWS_H - -#include "src/core/iomgr/pollset_set.h" - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */ diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c deleted file mode 100644 index c7f30f435f..0000000000 --- a/src/core/iomgr/pollset_windows.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include <grpc/support/log.h> -#include <grpc/support/thd.h> - -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/pollset.h" -#include "src/core/iomgr/pollset_windows.h" - -gpr_mu grpc_polling_mu; -static grpc_pollset_worker *g_active_poller; -static grpc_pollset_worker g_global_root_worker; - -void grpc_pollset_global_init() { - gpr_mu_init(&grpc_polling_mu); - g_active_poller = NULL; - g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next = - g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = - &g_global_root_worker; -} - -void grpc_pollset_global_shutdown() { gpr_mu_destroy(&grpc_polling_mu); } - -static void remove_worker(grpc_pollset_worker *worker, - grpc_pollset_worker_link_type type) { - worker->links[type].prev->links[type].next = worker->links[type].next; - worker->links[type].next->links[type].prev = worker->links[type].prev; - worker->links[type].next = worker->links[type].prev = worker; -} - -static int has_workers(grpc_pollset_worker *root, - grpc_pollset_worker_link_type type) { - return root->links[type].next != root; -} - -static grpc_pollset_worker *pop_front_worker( - grpc_pollset_worker *root, grpc_pollset_worker_link_type type) { - if (has_workers(root, type)) { - grpc_pollset_worker *w = root->links[type].next; - remove_worker(w, type); - return w; - } else { - return NULL; - } -} - -static void push_front_worker(grpc_pollset_worker *root, - grpc_pollset_worker_link_type type, - grpc_pollset_worker *worker) { - worker->links[type].prev = root; - worker->links[type].next = worker->links[type].prev->links[type].next; - worker->links[type].prev->links[type].next = - worker->links[type].next->links[type].prev = worker; -} - -size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); } - -/* There isn't really any such thing as a pollset under Windows, due to the - nature of the IO completion ports. We're still going to provide a minimal - set of features for the sake of the rest of grpc. But grpc_pollset_work - won't actually do any polling, and return as quickly as possible. */ - -void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { - *mu = &grpc_polling_mu; - memset(pollset, 0, sizeof(*pollset)); - pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next = - pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev = - &pollset->root_worker; -} - -void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_closure *closure) { - pollset->shutting_down = 1; - grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - if (!pollset->is_iocp_worker) { - grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); - } else { - pollset->on_shutdown = closure; - } -} - -void grpc_pollset_destroy(grpc_pollset *pollset) {} - -void grpc_pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT( - !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET)); - pollset->shutting_down = 0; - pollset->is_iocp_worker = 0; - pollset->kicked_without_pollers = 0; - pollset->on_shutdown = NULL; -} - -void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker **worker_hdl, gpr_timespec now, - gpr_timespec deadline) { - grpc_pollset_worker worker; - *worker_hdl = &worker; - - int added_worker = 0; - worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next = - worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev = - worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next = - worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL; - worker.kicked = 0; - worker.pollset = pollset; - gpr_cv_init(&worker.cv); - if (!pollset->kicked_without_pollers && !pollset->shutting_down) { - if (g_active_poller == NULL) { - grpc_pollset_worker *next_worker; - /* become poller */ - pollset->is_iocp_worker = 1; - g_active_poller = &worker; - gpr_mu_unlock(&grpc_polling_mu); - grpc_iocp_work(exec_ctx, deadline); - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&grpc_polling_mu); - pollset->is_iocp_worker = 0; - g_active_poller = NULL; - /* try to get a worker from this pollsets worker list */ - next_worker = pop_front_worker(&pollset->root_worker, - GRPC_POLLSET_WORKER_LINK_POLLSET); - if (next_worker == NULL) { - /* try to get a worker from the global list */ - next_worker = pop_front_worker(&g_global_root_worker, - GRPC_POLLSET_WORKER_LINK_GLOBAL); - } - if (next_worker != NULL) { - next_worker->kicked = 1; - gpr_cv_signal(&next_worker->cv); - } - - if (pollset->shutting_down && pollset->on_shutdown != NULL) { - grpc_exec_ctx_enqueue(exec_ctx, pollset->on_shutdown, true, NULL); - pollset->on_shutdown = NULL; - } - goto done; - } - push_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL, - &worker); - push_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET, - &worker); - added_worker = 1; - while (!worker.kicked) { - if (gpr_cv_wait(&worker.cv, &grpc_polling_mu, deadline)) { - break; - } - } - } else { - pollset->kicked_without_pollers = 0; - } -done: - if (!grpc_closure_list_empty(exec_ctx->closure_list)) { - gpr_mu_unlock(&grpc_polling_mu); - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&grpc_polling_mu); - } - if (added_worker) { - remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_GLOBAL); - remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_POLLSET); - } - gpr_cv_destroy(&worker.cv); - *worker_hdl = NULL; -} - -void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) { - if (specific_worker != NULL) { - if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { - for (specific_worker = - p->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next; - specific_worker != &p->root_worker; - specific_worker = - specific_worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next) { - specific_worker->kicked = 1; - gpr_cv_signal(&specific_worker->cv); - } - p->kicked_without_pollers = 1; - if (p->is_iocp_worker) { - grpc_iocp_kick(); - } - } else { - if (p->is_iocp_worker && g_active_poller == specific_worker) { - grpc_iocp_kick(); - } else { - specific_worker->kicked = 1; - gpr_cv_signal(&specific_worker->cv); - } - } - } else { - specific_worker = - pop_front_worker(&p->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET); - if (specific_worker != NULL) { - grpc_pollset_kick(p, specific_worker); - } else if (p->is_iocp_worker) { - grpc_iocp_kick(); - } else { - p->kicked_without_pollers = 1; - } - } -} - -void grpc_kick_poller(void) { grpc_iocp_kick(); } - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/pollset_windows.h b/src/core/iomgr/pollset_windows.h deleted file mode 100644 index dc0b7a4104..0000000000 --- a/src/core/iomgr/pollset_windows.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H - -#include <grpc/support/sync.h> - -#include "src/core/iomgr/socket_windows.h" - -/* There isn't really any such thing as a pollset under Windows, due to the - nature of the IO completion ports. A Windows "pollset" is merely a mutex - used to synchronize with the IOCP, and workers are condition variables - used to block threads until work is ready. */ - -typedef enum { - GRPC_POLLSET_WORKER_LINK_POLLSET = 0, - GRPC_POLLSET_WORKER_LINK_GLOBAL, - GRPC_POLLSET_WORKER_LINK_TYPES -} grpc_pollset_worker_link_type; - -typedef struct grpc_pollset_worker_link { - struct grpc_pollset_worker *next; - struct grpc_pollset_worker *prev; -} grpc_pollset_worker_link; - -struct grpc_pollset; -typedef struct grpc_pollset grpc_pollset; - -typedef struct grpc_pollset_worker { - gpr_cv cv; - int kicked; - struct grpc_pollset *pollset; - grpc_pollset_worker_link links[GRPC_POLLSET_WORKER_LINK_TYPES]; -} grpc_pollset_worker; - -struct grpc_pollset { - int shutting_down; - int kicked_without_pollers; - int is_iocp_worker; - grpc_pollset_worker root_worker; - grpc_closure *on_shutdown; -}; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */ diff --git a/src/core/iomgr/resolve_address.h b/src/core/iomgr/resolve_address.h deleted file mode 100644 index b059630457..0000000000 --- a/src/core/iomgr/resolve_address.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H -#define GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H - -#include <stddef.h> -#include "src/core/iomgr/exec_ctx.h" -#include "src/core/iomgr/iomgr.h" - -#define GRPC_MAX_SOCKADDR_SIZE 128 - -typedef struct { - char addr[GRPC_MAX_SOCKADDR_SIZE]; - size_t len; -} grpc_resolved_address; - -typedef struct { - size_t naddrs; - grpc_resolved_address *addrs; -} grpc_resolved_addresses; - -/* Async result callback: - On success: addresses is the result, and the callee must call - grpc_resolved_addresses_destroy when it's done with them - On failure: addresses is NULL */ -typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg, - grpc_resolved_addresses *addresses); -/* Asynchronously resolve addr. Use default_port if a port isn't designated - in addr, otherwise use the port in addr. */ -/* TODO(ctiller): add a timeout here */ -void grpc_resolve_address(const char *addr, const char *default_port, - grpc_resolve_cb cb, void *arg); -/* Destroy resolved addresses */ -void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses); - -/* Resolve addr in a blocking fashion. Returns NULL on failure. On success, - result must be freed with grpc_resolved_addresses_destroy. */ -extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)( - const char *name, const char *default_port); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H */ diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c deleted file mode 100644 index a6c9893f23..0000000000 --- a/src/core/iomgr/resolve_address_posix.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/resolve_address.h" -#include "src/core/iomgr/sockaddr.h" - -#include <string.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/host_port.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/thd.h> -#include <grpc/support/time.h> -#include <grpc/support/useful.h> -#include "src/core/iomgr/executor.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/support/block_annotate.h" -#include "src/core/support/string.h" - -typedef struct { - char *name; - char *default_port; - grpc_resolve_cb cb; - grpc_closure request_closure; - void *arg; -} request; - -static grpc_resolved_addresses *blocking_resolve_address_impl( - const char *name, const char *default_port) { - struct addrinfo hints; - struct addrinfo *result = NULL, *resp; - char *host; - char *port; - int s; - size_t i; - grpc_resolved_addresses *addrs = NULL; - struct sockaddr_un *un; - - if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' && - name[4] == ':' && name[5] != 0) { - addrs = gpr_malloc(sizeof(grpc_resolved_addresses)); - addrs->naddrs = 1; - addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address)); - un = (struct sockaddr_un *)addrs->addrs->addr; - un->sun_family = AF_UNIX; - strcpy(un->sun_path, name + 5); - addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1; - return addrs; - } - - /* parse name, splitting it into host and port parts */ - gpr_split_host_port(name, &host, &port); - if (host == NULL) { - gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name); - goto done; - } - if (port == NULL) { - if (default_port == NULL) { - gpr_log(GPR_ERROR, "no port in name '%s'", name); - goto done; - } - port = gpr_strdup(default_port); - } - - /* Call getaddrinfo */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ - hints.ai_socktype = SOCK_STREAM; /* stream socket */ - hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ - - GRPC_SCHEDULING_START_BLOCKING_REGION; - s = getaddrinfo(host, port, &hints, &result); - GRPC_SCHEDULING_END_BLOCKING_REGION; - - if (s != 0) { - /* Retry if well-known service name is recognized */ - char *svc[][2] = {{"http", "80"}, {"https", "443"}}; - for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) { - if (strcmp(port, svc[i][0]) == 0) { - GRPC_SCHEDULING_START_BLOCKING_REGION; - s = getaddrinfo(host, svc[i][1], &hints, &result); - GRPC_SCHEDULING_END_BLOCKING_REGION; - break; - } - } - } - - if (s != 0) { - gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s)); - goto done; - } - - /* Success path: set addrs non-NULL, fill it in */ - addrs = gpr_malloc(sizeof(grpc_resolved_addresses)); - addrs->naddrs = 0; - for (resp = result; resp != NULL; resp = resp->ai_next) { - addrs->naddrs++; - } - addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs); - i = 0; - for (resp = result; resp != NULL; resp = resp->ai_next) { - memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); - addrs->addrs[i].len = resp->ai_addrlen; - i++; - } - -done: - gpr_free(host); - gpr_free(port); - if (result) { - freeaddrinfo(result); - } - return addrs; -} - -grpc_resolved_addresses *(*grpc_blocking_resolve_address)( - const char *name, const char *default_port) = blocking_resolve_address_impl; - -/* Callback to be passed to grpc_executor to asynch-ify - * grpc_blocking_resolve_address */ -static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) { - request *r = rp; - grpc_resolved_addresses *resolved = - grpc_blocking_resolve_address(r->name, r->default_port); - void *arg = r->arg; - grpc_resolve_cb cb = r->cb; - gpr_free(r->name); - gpr_free(r->default_port); - cb(exec_ctx, arg, resolved); - gpr_free(r); -} - -void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { - gpr_free(addrs->addrs); - gpr_free(addrs); -} - -void grpc_resolve_address(const char *name, const char *default_port, - grpc_resolve_cb cb, void *arg) { - request *r = gpr_malloc(sizeof(request)); - grpc_closure_init(&r->request_closure, do_request_thread, r); - r->name = gpr_strdup(name); - r->default_port = gpr_strdup(default_port); - r->cb = cb; - r->arg = arg; - grpc_executor_enqueue(&r->request_closure, 1); -} - -#endif diff --git a/src/core/iomgr/resolve_address_windows.c b/src/core/iomgr/resolve_address_windows.c deleted file mode 100644 index 472e797163..0000000000 --- a/src/core/iomgr/resolve_address_windows.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> -#ifdef GPR_WINSOCK_SOCKET - -#include "src/core/iomgr/resolve_address.h" -#include "src/core/iomgr/sockaddr.h" - -#include <string.h> -#include <sys/types.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/host_port.h> -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/string_util.h> -#include <grpc/support/thd.h> -#include <grpc/support/time.h> -#include "src/core/iomgr/executor.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/support/block_annotate.h" -#include "src/core/support/string.h" - -typedef struct { - char *name; - char *default_port; - grpc_resolve_cb cb; - grpc_closure request_closure; - void *arg; -} request; - -static grpc_resolved_addresses *blocking_resolve_address_impl( - const char *name, const char *default_port) { - struct addrinfo hints; - struct addrinfo *result = NULL, *resp; - char *host; - char *port; - int s; - size_t i; - grpc_resolved_addresses *addrs = NULL; - - /* parse name, splitting it into host and port parts */ - gpr_split_host_port(name, &host, &port); - if (host == NULL) { - gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name); - goto done; - } - if (port == NULL) { - if (default_port == NULL) { - gpr_log(GPR_ERROR, "no port in name '%s'", name); - goto done; - } - port = gpr_strdup(default_port); - } - - /* Call getaddrinfo */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ - hints.ai_socktype = SOCK_STREAM; /* stream socket */ - hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ - - GRPC_SCHEDULING_START_BLOCKING_REGION; - s = getaddrinfo(host, port, &hints, &result); - GRPC_SCHEDULING_END_BLOCKING_REGION; - if (s != 0) { - char *error_message = gpr_format_message(s); - gpr_log(GPR_ERROR, "getaddrinfo: %s", error_message); - gpr_free(error_message); - goto done; - } - - /* Success path: set addrs non-NULL, fill it in */ - addrs = gpr_malloc(sizeof(grpc_resolved_addresses)); - addrs->naddrs = 0; - for (resp = result; resp != NULL; resp = resp->ai_next) { - addrs->naddrs++; - } - addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs); - i = 0; - for (resp = result; resp != NULL; resp = resp->ai_next) { - memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); - addrs->addrs[i].len = resp->ai_addrlen; - i++; - } - - { - for (i = 0; i < addrs->naddrs; i++) { - char *buf; - grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr, - 0); - gpr_free(buf); - } - } - -done: - gpr_free(host); - gpr_free(port); - if (result) { - freeaddrinfo(result); - } - return addrs; -} - -grpc_resolved_addresses *(*grpc_blocking_resolve_address)( - const char *name, const char *default_port) = blocking_resolve_address_impl; - -/* Callback to be passed to grpc_executor to asynch-ify - * grpc_blocking_resolve_address */ -static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) { - request *r = rp; - grpc_resolved_addresses *resolved = - grpc_blocking_resolve_address(r->name, r->default_port); - void *arg = r->arg; - grpc_resolve_cb cb = r->cb; - gpr_free(r->name); - gpr_free(r->default_port); - cb(exec_ctx, arg, resolved); - gpr_free(r); -} - -void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { - gpr_free(addrs->addrs); - gpr_free(addrs); -} - -void grpc_resolve_address(const char *name, const char *default_port, - grpc_resolve_cb cb, void *arg) { - request *r = gpr_malloc(sizeof(request)); - grpc_closure_init(&r->request_closure, do_request_thread, r); - r->name = gpr_strdup(name); - r->default_port = gpr_strdup(default_port); - r->cb = cb; - r->arg = arg; - grpc_executor_enqueue(&r->request_closure, 1); -} - -#endif diff --git a/src/core/iomgr/sockaddr.h b/src/core/iomgr/sockaddr.h deleted file mode 100644 index e41e1ec6b4..0000000000 --- a/src/core/iomgr/sockaddr.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_H - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WIN32 -#include "src/core/iomgr/sockaddr_win32.h" -#endif - -#ifdef GPR_POSIX_SOCKETADDR -#include "src/core/iomgr/sockaddr_posix.h" -#endif - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_H */ diff --git a/src/core/iomgr/sockaddr_posix.h b/src/core/iomgr/sockaddr_posix.h deleted file mode 100644 index 388abb3306..0000000000 --- a/src/core/iomgr/sockaddr_posix.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_POSIX_H - -#include <arpa/inet.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <netdb.h> -#include <unistd.h> - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_POSIX_H */ diff --git a/src/core/iomgr/sockaddr_utils.c b/src/core/iomgr/sockaddr_utils.c deleted file mode 100644 index 61006d7a7a..0000000000 --- a/src/core/iomgr/sockaddr_utils.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/sockaddr_utils.h" - -#include <errno.h> -#include <string.h> - -#ifdef GPR_POSIX_SOCKET -#include <sys/un.h> -#endif - -#include <grpc/support/alloc.h> -#include <grpc/support/host_port.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/string_util.h> - -#include "src/core/support/string.h" - -static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xff, 0xff}; - -int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr, - struct sockaddr_in *addr4_out) { - GPR_ASSERT(addr != (struct sockaddr *)addr4_out); - if (addr->sa_family == AF_INET6) { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; - if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix, - sizeof(kV4MappedPrefix)) == 0) { - if (addr4_out != NULL) { - /* Normalize ::ffff:0.0.0.0/96 to IPv4. */ - memset(addr4_out, 0, sizeof(*addr4_out)); - addr4_out->sin_family = AF_INET; - /* s6_addr32 would be nice, but it's non-standard. */ - memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4); - addr4_out->sin_port = addr6->sin6_port; - } - return 1; - } - } - return 0; -} - -int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr, - struct sockaddr_in6 *addr6_out) { - GPR_ASSERT(addr != (struct sockaddr *)addr6_out); - if (addr->sa_family == AF_INET) { - const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; - memset(addr6_out, 0, sizeof(*addr6_out)); - addr6_out->sin6_family = AF_INET6; - memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12); - memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4); - addr6_out->sin6_port = addr4->sin_port; - return 1; - } - return 0; -} - -int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out) { - struct sockaddr_in addr4_normalized; - if (grpc_sockaddr_is_v4mapped(addr, &addr4_normalized)) { - addr = (struct sockaddr *)&addr4_normalized; - } - if (addr->sa_family == AF_INET) { - /* Check for 0.0.0.0 */ - const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; - if (addr4->sin_addr.s_addr != 0) { - return 0; - } - *port_out = ntohs(addr4->sin_port); - return 1; - } else if (addr->sa_family == AF_INET6) { - /* Check for :: */ - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; - int i; - for (i = 0; i < 16; i++) { - if (addr6->sin6_addr.s6_addr[i] != 0) { - return 0; - } - } - *port_out = ntohs(addr6->sin6_port); - return 1; - } else { - return 0; - } -} - -void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out, - struct sockaddr_in6 *wild6_out) { - grpc_sockaddr_make_wildcard4(port, wild4_out); - grpc_sockaddr_make_wildcard6(port, wild6_out); -} - -void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out) { - GPR_ASSERT(port >= 0 && port < 65536); - memset(wild_out, 0, sizeof(*wild_out)); - wild_out->sin_family = AF_INET; - wild_out->sin_port = htons((uint16_t)port); -} - -void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out) { - GPR_ASSERT(port >= 0 && port < 65536); - memset(wild_out, 0, sizeof(*wild_out)); - wild_out->sin6_family = AF_INET6; - wild_out->sin6_port = htons((uint16_t)port); -} - -int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr, - int normalize) { - const int save_errno = errno; - struct sockaddr_in addr_normalized; - char ntop_buf[INET6_ADDRSTRLEN]; - const void *ip = NULL; - int port; - int ret; - - *out = NULL; - if (normalize && grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) { - addr = (const struct sockaddr *)&addr_normalized; - } - if (addr->sa_family == AF_INET) { - const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; - ip = &addr4->sin_addr; - port = ntohs(addr4->sin_port); - } else if (addr->sa_family == AF_INET6) { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; - ip = &addr6->sin6_addr; - port = ntohs(addr6->sin6_port); - } - /* Windows inet_ntop wants a mutable ip pointer */ - if (ip != NULL && - inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) != - NULL) { - ret = gpr_join_host_port(out, ntop_buf, port); - } else { - ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family); - } - /* This is probably redundant, but we wouldn't want to log the wrong error. */ - errno = save_errno; - return ret; -} - -char *grpc_sockaddr_to_uri(const struct sockaddr *addr) { - char *temp; - char *result; - struct sockaddr_in addr_normalized; - - if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) { - addr = (const struct sockaddr *)&addr_normalized; - } - - switch (addr->sa_family) { - case AF_INET: - grpc_sockaddr_to_string(&temp, addr, 0); - gpr_asprintf(&result, "ipv4:%s", temp); - gpr_free(temp); - return result; - case AF_INET6: - grpc_sockaddr_to_string(&temp, addr, 0); - gpr_asprintf(&result, "ipv6:%s", temp); - gpr_free(temp); - return result; -#ifdef GPR_POSIX_SOCKET - case AF_UNIX: - gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path); - return result; -#endif - } - - return NULL; -} - -int grpc_sockaddr_get_port(const struct sockaddr *addr) { - switch (addr->sa_family) { - case AF_INET: - return ntohs(((struct sockaddr_in *)addr)->sin_port); - case AF_INET6: - return ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - case AF_UNIX: - return 1; - default: - gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port", - addr->sa_family); - return 0; - } -} - -int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) { - switch (addr->sa_family) { - case AF_INET: - GPR_ASSERT(port >= 0 && port < 65536); - ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port); - return 1; - case AF_INET6: - GPR_ASSERT(port >= 0 && port < 65536); - ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port); - return 1; - default: - gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port", - addr->sa_family); - return 0; - } -} diff --git a/src/core/iomgr/sockaddr_utils.h b/src/core/iomgr/sockaddr_utils.h deleted file mode 100644 index 6f7a279900..0000000000 --- a/src/core/iomgr/sockaddr_utils.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H - -#include "src/core/iomgr/sockaddr.h" - -/* Returns true if addr is an IPv4-mapped IPv6 address within the - ::ffff:0.0.0.0/96 range, or false otherwise. - - If addr4_out is non-NULL, the inner IPv4 address will be copied here when - returning true. */ -int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr, - struct sockaddr_in *addr4_out); - -/* If addr is an AF_INET address, writes the corresponding ::ffff:0.0.0.0/96 - address to addr6_out and returns true. Otherwise returns false. */ -int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr, - struct sockaddr_in6 *addr6_out); - -/* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to - *port_out (if not NULL) and returns true, otherwise returns false. */ -int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out); - -/* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */ -void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out, - struct sockaddr_in6 *wild6_out); - -/* Writes 0.0.0.0:port. */ -void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out); - -/* Writes [::]:port. */ -void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out); - -/* Return the IP port number of a sockaddr */ -int grpc_sockaddr_get_port(const struct sockaddr *addr); - -/* Set IP port number of a sockaddr */ -int grpc_sockaddr_set_port(const struct sockaddr *addr, int port); - -/* Converts a sockaddr into a newly-allocated human-readable string. - - Currently, only the AF_INET and AF_INET6 families are recognized. - If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are - displayed as plain IPv4. - - Usage is similar to gpr_asprintf: returns the number of bytes written - (excluding the final '\0'), and *out points to a string which must later be - destroyed using gpr_free(). - - In the unlikely event of an error, returns -1 and sets *out to NULL. - The existing value of errno is always preserved. */ -int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr, - int normalize); - -char *grpc_sockaddr_to_uri(const struct sockaddr *addr); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H */ diff --git a/src/core/iomgr/sockaddr_win32.h b/src/core/iomgr/sockaddr_win32.h deleted file mode 100644 index 8e3946a7d8..0000000000 --- a/src/core/iomgr/sockaddr_win32.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_WIN32_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_WIN32_H - -#include <winsock2.h> -#include <ws2tcpip.h> -#include <mswsock.h> - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_WIN32_H */ diff --git a/src/core/iomgr/socket_utils_common_posix.c b/src/core/iomgr/socket_utils_common_posix.c deleted file mode 100644 index a9af594700..0000000000 --- a/src/core/iomgr/socket_utils_common_posix.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/socket_utils_posix.h" - -#include <arpa/inet.h> -#include <limits.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/support/string.h" -#include <grpc/support/host_port.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/sync.h> - -/* set a socket to non blocking mode */ -int grpc_set_socket_nonblocking(int fd, int non_blocking) { - int oldflags = fcntl(fd, F_GETFL, 0); - if (oldflags < 0) { - return 0; - } - - if (non_blocking) { - oldflags |= O_NONBLOCK; - } else { - oldflags &= ~O_NONBLOCK; - } - - if (fcntl(fd, F_SETFL, oldflags) != 0) { - return 0; - } - - return 1; -} - -int grpc_set_socket_no_sigpipe_if_possible(int fd) { -#ifdef GPR_HAVE_SO_NOSIGPIPE - int val = 1; - int newval; - socklen_t intlen = sizeof(newval); - return 0 == setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)) && - 0 == getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen) && - (newval != 0) == val; -#else - return 1; -#endif -} - -/* set a socket to close on exec */ -int grpc_set_socket_cloexec(int fd, int close_on_exec) { - int oldflags = fcntl(fd, F_GETFD, 0); - if (oldflags < 0) { - return 0; - } - - if (close_on_exec) { - oldflags |= FD_CLOEXEC; - } else { - oldflags &= ~FD_CLOEXEC; - } - - if (fcntl(fd, F_SETFD, oldflags) != 0) { - return 0; - } - - return 1; -} - -/* set a socket to reuse old addresses */ -int grpc_set_socket_reuse_addr(int fd, int reuse) { - int val = (reuse != 0); - int newval; - socklen_t intlen = sizeof(newval); - return 0 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) && - 0 == getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen) && - (newval != 0) == val; -} - -/* disable nagle */ -int grpc_set_socket_low_latency(int fd, int low_latency) { - int val = (low_latency != 0); - int newval; - socklen_t intlen = sizeof(newval); - return 0 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) && - 0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen) && - (newval != 0) == val; -} - -static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; -static int g_ipv6_loopback_available; - -static void probe_ipv6_once(void) { - int fd = socket(AF_INET6, SOCK_STREAM, 0); - g_ipv6_loopback_available = 0; - if (fd < 0) { - gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); - } else { - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ - if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { - g_ipv6_loopback_available = 1; - } else { - gpr_log(GPR_INFO, - "Disabling AF_INET6 sockets because ::1 is not available."); - } - close(fd); - } -} - -int grpc_ipv6_loopback_available(void) { - gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); - return g_ipv6_loopback_available; -} - -/* This should be 0 in production, but it may be enabled for testing or - debugging purposes, to simulate an environment where IPv6 sockets can't - also speak IPv4. */ -int grpc_forbid_dualstack_sockets_for_testing = 0; - -static int set_socket_dualstack(int fd) { - if (!grpc_forbid_dualstack_sockets_for_testing) { - const int off = 0; - return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); - } else { - /* Force an IPv6-only socket, for testing purposes. */ - const int on = 1; - setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); - return 0; - } -} - -int grpc_create_dualstack_socket(const struct sockaddr *addr, int type, - int protocol, grpc_dualstack_mode *dsmode) { - int family = addr->sa_family; - if (family == AF_INET6) { - int fd; - if (grpc_ipv6_loopback_available()) { - fd = socket(family, type, protocol); - } else { - fd = -1; - errno = EAFNOSUPPORT; - } - /* Check if we've got a valid dualstack socket. */ - if (fd >= 0 && set_socket_dualstack(fd)) { - *dsmode = GRPC_DSMODE_DUALSTACK; - return fd; - } - /* If this isn't an IPv4 address, then return whatever we've got. */ - if (!grpc_sockaddr_is_v4mapped(addr, NULL)) { - *dsmode = GRPC_DSMODE_IPV6; - return fd; - } - /* Fall back to AF_INET. */ - if (fd >= 0) { - close(fd); - } - family = AF_INET; - } - *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE; - return socket(family, type, protocol); -} - -#endif diff --git a/src/core/iomgr/socket_utils_linux.c b/src/core/iomgr/socket_utils_linux.c deleted file mode 100644 index a87625262b..0000000000 --- a/src/core/iomgr/socket_utils_linux.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_LINUX_SOCKETUTILS - -#include "src/core/iomgr/socket_utils_posix.h" - -#include <sys/types.h> -#include <sys/socket.h> - -int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, - int nonblock, int cloexec) { - int flags = 0; - flags |= nonblock ? SOCK_NONBLOCK : 0; - flags |= cloexec ? SOCK_CLOEXEC : 0; - return accept4(sockfd, addr, addrlen, flags); -} - -#endif diff --git a/src/core/iomgr/socket_utils_posix.c b/src/core/iomgr/socket_utils_posix.c deleted file mode 100644 index 3c56b46744..0000000000 --- a/src/core/iomgr/socket_utils_posix.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKETUTILS - -#include "src/core/iomgr/socket_utils_posix.h" - -#include <fcntl.h> -#include <sys/socket.h> -#include <unistd.h> - -#include <grpc/support/log.h> - -int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, - int nonblock, int cloexec) { - int fd, flags; - - fd = accept(sockfd, addr, addrlen); - if (fd >= 0) { - if (nonblock) { - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) goto close_and_error; - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) goto close_and_error; - } - if (cloexec) { - flags = fcntl(fd, F_GETFD, 0); - if (flags < 0) goto close_and_error; - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != 0) goto close_and_error; - } - } - return fd; - -close_and_error: - close(fd); - return -1; -} - -#endif /* GPR_POSIX_SOCKETUTILS */ diff --git a/src/core/iomgr/socket_utils_posix.h b/src/core/iomgr/socket_utils_posix.h deleted file mode 100644 index d330d1986e..0000000000 --- a/src/core/iomgr/socket_utils_posix.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKET_UTILS_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKET_UTILS_POSIX_H - -#include <unistd.h> -#include <sys/socket.h> - -/* a wrapper for accept or accept4 */ -int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, - int nonblock, int cloexec); - -/* set a socket to non blocking mode */ -int grpc_set_socket_nonblocking(int fd, int non_blocking); - -/* set a socket to close on exec */ -int grpc_set_socket_cloexec(int fd, int close_on_exec); - -/* set a socket to reuse old addresses */ -int grpc_set_socket_reuse_addr(int fd, int reuse); - -/* disable nagle */ -int grpc_set_socket_low_latency(int fd, int low_latency); - -/* Returns true if this system can create AF_INET6 sockets bound to ::1. - The value is probed once, and cached for the life of the process. - - This is more restrictive than checking for socket(AF_INET6) to succeed, - because Linux with "net.ipv6.conf.all.disable_ipv6 = 1" is able to create - and bind IPv6 sockets, but cannot connect to a getsockname() of [::]:port - without a valid loopback interface. Rather than expose this half-broken - state to library users, we turn off IPv6 sockets. */ -int grpc_ipv6_loopback_available(void); - -/* Tries to set SO_NOSIGPIPE if available on this platform. - Returns 1 on success, 0 on failure. - If SO_NO_SIGPIPE is not available, returns 1. */ -int grpc_set_socket_no_sigpipe_if_possible(int fd); - -/* An enum to keep track of IPv4/IPv6 socket modes. - - Currently, this information is only used when a socket is first created, but - in the future we may wish to store it alongside the fd. This would let calls - like sendto() know which family to use without asking the kernel first. */ -typedef enum grpc_dualstack_mode { - /* Uninitialized, or a non-IP socket. */ - GRPC_DSMODE_NONE, - /* AF_INET only. */ - GRPC_DSMODE_IPV4, - /* AF_INET6 only, because IPV6_V6ONLY could not be cleared. */ - GRPC_DSMODE_IPV6, - /* AF_INET6, which also supports ::ffff-mapped IPv4 addresses. */ - GRPC_DSMODE_DUALSTACK -} grpc_dualstack_mode; - -/* Only tests should use this flag. */ -extern int grpc_forbid_dualstack_sockets_for_testing; - -/* Creates a new socket for connecting to (or listening on) an address. - - If addr is AF_INET6, this creates an IPv6 socket first. If that fails, - and addr is within ::ffff:0.0.0.0/96, then it automatically falls back to - an IPv4 socket. - - If addr is AF_INET, AF_UNIX, or anything else, then this is similar to - calling socket() directly. - - Returns an fd on success, otherwise returns -1 with errno set to the result - of a failed socket() call. - - The *dsmode output indicates which address family was actually created. - The recommended way to use this is: - - First convert to IPv6 using grpc_sockaddr_to_v4mapped(). - - Create the socket. - - If *dsmode is IPV4, use grpc_sockaddr_is_v4mapped() to convert back to - IPv4, so that bind() or connect() see the correct family. - Also, it's important to distinguish between DUALSTACK and IPV6 when - listening on the [::] wildcard address. */ -int grpc_create_dualstack_socket(const struct sockaddr *addr, int type, - int protocol, grpc_dualstack_mode *dsmode); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKET_UTILS_POSIX_H */ diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c deleted file mode 100644 index fafb7b6622..0000000000 --- a/src/core/iomgr/socket_windows.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include <winsock2.h> -#include <mswsock.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/string_util.h> - -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/pollset.h" -#include "src/core/iomgr/pollset_windows.h" -#include "src/core/iomgr/socket_windows.h" - -grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { - char *final_name; - grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket)); - memset(r, 0, sizeof(grpc_winsocket)); - r->socket = socket; - gpr_mu_init(&r->state_mu); - gpr_asprintf(&final_name, "%s:socket=0x%p", name, r); - grpc_iomgr_register_object(&r->iomgr_object, final_name); - gpr_free(final_name); - grpc_iocp_add_socket(r); - return r; -} - -/* Schedule a shutdown of the socket operations. Will call the pending - operations to abort them. We need to do that this way because of the - various callsites of that function, which happens to be in various - mutex hold states, and that'd be unsafe to call them directly. */ -void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { - /* Grab the function pointer for DisconnectEx for that specific socket. - It may change depending on the interface. */ - int status; - GUID guid = WSAID_DISCONNECTEX; - LPFN_DISCONNECTEX DisconnectEx; - DWORD ioctl_num_bytes; - - status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, - &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx), - &ioctl_num_bytes, NULL, NULL); - - if (status == 0) { - DisconnectEx(winsocket->socket, NULL, 0, 0); - } else { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s", - utf8_message); - gpr_free(utf8_message); - } - closesocket(winsocket->socket); -} - -void grpc_winsocket_destroy(grpc_winsocket *winsocket) { - grpc_iomgr_unregister_object(&winsocket->iomgr_object); - gpr_mu_destroy(&winsocket->state_mu); - gpr_free(winsocket); -} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h deleted file mode 100644 index dfbfabe1f9..0000000000 --- a/src/core/iomgr/socket_windows.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_SOCKET_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_SOCKET_WINDOWS_H - -#include <grpc/support/port_platform.h> -#include <winsock2.h> - -#include <grpc/support/sync.h> -#include <grpc/support/atm.h> - -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/exec_ctx.h" - -/* This holds the data for an outstanding read or write on a socket. - The mutex to protect the concurrent access to that data is the one - inside the winsocket wrapper. */ -typedef struct grpc_winsocket_callback_info { - /* This is supposed to be a WSAOVERLAPPED, but in order to get that - definition, we need to include ws2tcpip.h, which needs to be included - from the top, otherwise it'll clash with a previous inclusion of - windows.h that in turns includes winsock.h. If anyone knows a way - to do it properly, feel free to send a patch. */ - OVERLAPPED overlapped; - /* The callback information for the pending operation. May be empty if the - caller hasn't registered a callback yet. */ - grpc_closure *closure; - /* A boolean to describe if the IO Completion Port got a notification for - that operation. This will happen if the operation completed before the - called had time to register a callback. We could avoid that behavior - altogether by forcing the caller to always register its callback before - proceeding queue an operation, but it is frequent for an IO Completion - Port to trigger quickly. This way we avoid a context switch for calling - the callback. We also simplify the read / write operations to avoid having - to hold a mutex for a long amount of time. */ - int has_pending_iocp; - /* The results of the overlapped operation. */ - DWORD bytes_transfered; - int wsa_error; -} grpc_winsocket_callback_info; - -/* This is a wrapper to a Windows socket. A socket can have one outstanding - read, and one outstanding write. Doing an asynchronous accept means waiting - for a read operation. Doing an asynchronous connect means waiting for a - write operation. These are completely arbitrary ties between the operation - and the kind of event, because we can have one overlapped per pending - operation, whichever its nature is. So we could have more dedicated pending - operation callbacks for connect and listen. But given the scope of listen - and accept, we don't need to go to that extent and waste memory. Also, this - is closer to what happens in posix world. */ -typedef struct grpc_winsocket { - SOCKET socket; - - grpc_winsocket_callback_info write_info; - grpc_winsocket_callback_info read_info; - - gpr_mu state_mu; - - /* You can't add the same socket twice to the same IO Completion Port. - This prevents that. */ - int added_to_iocp; - - grpc_closure shutdown_closure; - - /* A label for iomgr to track outstanding objects */ - grpc_iomgr_object iomgr_object; -} grpc_winsocket; - -/* Create a wrapped windows handle. This takes ownership of it, meaning that - it will be responsible for closing it. */ -grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name); - -/* Initiate an asynchronous shutdown of the socket. Will call off any pending - operation to cancel them. */ -void grpc_winsocket_shutdown(grpc_winsocket *socket); - -/* Destroy a socket. Should only be called if there's no pending operation. */ -void grpc_winsocket_destroy(grpc_winsocket *socket); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKET_WINDOWS_H */ diff --git a/src/core/iomgr/tcp_client.h b/src/core/iomgr/tcp_client.h deleted file mode 100644 index 5e18e71ca2..0000000000 --- a/src/core/iomgr/tcp_client.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TCP_CLIENT_H -#define GRPC_INTERNAL_CORE_IOMGR_TCP_CLIENT_H - -#include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/pollset_set.h" -#include "src/core/iomgr/sockaddr.h" -#include <grpc/support/time.h> - -/* Asynchronously connect to an address (specified as (addr, len)), and call - cb with arg and the completed connection when done (or call cb with arg and - NULL on failure). - interested_parties points to a set of pollsets that would be interested - in this connection being established (in order to continue their work) */ -void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect, - grpc_endpoint **endpoint, - grpc_pollset_set *interested_parties, - const struct sockaddr *addr, size_t addr_len, - gpr_timespec deadline); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_CLIENT_H */ diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c deleted file mode 100644 index 15727856ab..0000000000 --- a/src/core/iomgr/tcp_client_posix.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/tcp_client.h" - -#include <errno.h> -#include <netinet/in.h> -#include <string.h> -#include <unistd.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/time.h> - -#include "src/core/iomgr/iomgr_posix.h" -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/iomgr/pollset_set_posix.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/socket_utils_posix.h" -#include "src/core/iomgr/tcp_posix.h" -#include "src/core/iomgr/timer.h" -#include "src/core/support/string.h" - -extern int grpc_tcp_trace; - -typedef struct { - gpr_mu mu; - grpc_fd *fd; - gpr_timespec deadline; - grpc_timer alarm; - int refs; - grpc_closure write_closure; - grpc_pollset_set *interested_parties; - char *addr_str; - grpc_endpoint **ep; - grpc_closure *closure; -} async_connect; - -static int prepare_socket(const struct sockaddr *addr, int fd) { - if (fd < 0) { - goto error; - } - - if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) || - (addr->sa_family != AF_UNIX && !grpc_set_socket_low_latency(fd, 1)) || - !grpc_set_socket_no_sigpipe_if_possible(fd)) { - gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd, - strerror(errno)); - goto error; - } - - return 1; - -error: - if (fd >= 0) { - close(fd); - } - return 0; -} - -static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) { - int done; - async_connect *ac = acp; - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str, - success); - } - gpr_mu_lock(&ac->mu); - if (ac->fd != NULL) { - grpc_fd_shutdown(exec_ctx, ac->fd); - } - done = (--ac->refs == 0); - gpr_mu_unlock(&ac->mu); - if (done) { - gpr_mu_destroy(&ac->mu); - gpr_free(ac->addr_str); - gpr_free(ac); - } -} - -static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) { - async_connect *ac = acp; - int so_error = 0; - socklen_t so_error_size; - int err; - int done; - grpc_endpoint **ep = ac->ep; - grpc_closure *closure = ac->closure; - grpc_fd *fd; - - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d", - ac->addr_str, success); - } - - gpr_mu_lock(&ac->mu); - GPR_ASSERT(ac->fd); - fd = ac->fd; - ac->fd = NULL; - gpr_mu_unlock(&ac->mu); - - grpc_timer_cancel(exec_ctx, &ac->alarm); - - gpr_mu_lock(&ac->mu); - if (success) { - do { - so_error_size = sizeof(so_error); - err = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); - } while (err < 0 && errno == EINTR); - if (err < 0) { - gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s", - ac->addr_str, strerror(errno)); - goto finish; - } else if (so_error != 0) { - if (so_error == ENOBUFS) { - /* We will get one of these errors if we have run out of - memory in the kernel for the data structures allocated - when you connect a socket. If this happens it is very - likely that if we wait a little bit then try again the - connection will work (since other programs or this - program will close their network connections and free up - memory). This does _not_ indicate that there is anything - wrong with the server we are connecting to, this is a - local problem. - - If you are looking at this code, then chances are that - your program or another program on the same computer - opened too many network connections. The "easy" fix: - don't do that! */ - gpr_log(GPR_ERROR, "kernel out of buffers"); - gpr_mu_unlock(&ac->mu); - grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); - return; - } else { - switch (so_error) { - case ECONNREFUSED: - gpr_log( - GPR_ERROR, - "failed to connect to '%s': socket error: connection refused", - ac->addr_str); - break; - default: - gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d", - ac->addr_str, so_error); - break; - } - goto finish; - } - } else { - grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); - *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str); - fd = NULL; - goto finish; - } - } else { - gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred", - ac->addr_str); - goto finish; - } - - GPR_UNREACHABLE_CODE(return ); - -finish: - if (fd != NULL) { - grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); - grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan"); - fd = NULL; - } - done = (--ac->refs == 0); - gpr_mu_unlock(&ac->mu); - if (done) { - gpr_mu_destroy(&ac->mu); - gpr_free(ac->addr_str); - gpr_free(ac); - } - grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL); -} - -void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - grpc_endpoint **ep, - grpc_pollset_set *interested_parties, - const struct sockaddr *addr, size_t addr_len, - gpr_timespec deadline) { - int fd; - grpc_dualstack_mode dsmode; - int err; - async_connect *ac; - struct sockaddr_in6 addr6_v4mapped; - struct sockaddr_in addr4_copy; - grpc_fd *fdobj; - char *name; - char *addr_str; - - *ep = NULL; - - /* Use dualstack sockets where available. */ - if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { - addr = (const struct sockaddr *)&addr6_v4mapped; - addr_len = sizeof(addr6_v4mapped); - } - - fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode); - if (fd < 0) { - gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); - } - if (dsmode == GRPC_DSMODE_IPV4) { - /* If we got an AF_INET socket, map the address back to IPv4. */ - GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy)); - addr = (struct sockaddr *)&addr4_copy; - addr_len = sizeof(addr4_copy); - } - if (!prepare_socket(addr, fd)) { - grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL); - return; - } - - do { - GPR_ASSERT(addr_len < ~(socklen_t)0); - err = connect(fd, addr, (socklen_t)addr_len); - } while (err < 0 && errno == EINTR); - - addr_str = grpc_sockaddr_to_uri(addr); - gpr_asprintf(&name, "tcp-client:%s", addr_str); - - fdobj = grpc_fd_create(fd, name); - - if (err >= 0) { - *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str); - grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); - goto done; - } - - if (errno != EWOULDBLOCK && errno != EINPROGRESS) { - gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno)); - grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error"); - grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL); - goto done; - } - - grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj); - - ac = gpr_malloc(sizeof(async_connect)); - ac->closure = closure; - ac->ep = ep; - ac->fd = fdobj; - ac->interested_parties = interested_parties; - ac->addr_str = addr_str; - addr_str = NULL; - gpr_mu_init(&ac->mu); - ac->refs = 2; - ac->write_closure.cb = on_writable; - ac->write_closure.cb_arg = ac; - - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", - ac->addr_str); - } - - gpr_mu_lock(&ac->mu); - grpc_timer_init(exec_ctx, &ac->alarm, - gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), - tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC)); - grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure); - gpr_mu_unlock(&ac->mu); - -done: - gpr_free(name); - gpr_free(addr_str); -} - -#endif diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c deleted file mode 100644 index 689c6f7b10..0000000000 --- a/src/core/iomgr/tcp_client_windows.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include "src/core/iomgr/sockaddr_win32.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/slice_buffer.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/timer.h" -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/tcp_client.h" -#include "src/core/iomgr/tcp_windows.h" -#include "src/core/iomgr/sockaddr.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/socket_windows.h" - -typedef struct { - grpc_closure *on_done; - gpr_mu mu; - grpc_winsocket *socket; - gpr_timespec deadline; - grpc_timer alarm; - char *addr_name; - int refs; - grpc_closure on_connect; - grpc_endpoint **endpoint; -} async_connect; - -static void async_connect_unlock_and_cleanup(async_connect *ac) { - int done = (--ac->refs == 0); - gpr_mu_unlock(&ac->mu); - if (done) { - if (ac->socket != NULL) grpc_winsocket_destroy(ac->socket); - gpr_mu_destroy(&ac->mu); - gpr_free(ac->addr_name); - gpr_free(ac); - } -} - -static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool occured) { - async_connect *ac = acp; - gpr_mu_lock(&ac->mu); - /* If the alarm didn't occur, it got cancelled. */ - if (ac->socket != NULL && occured) { - grpc_winsocket_shutdown(ac->socket); - } - async_connect_unlock_and_cleanup(ac); -} - -static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) { - async_connect *ac = acp; - SOCKET sock = ac->socket->socket; - grpc_endpoint **ep = ac->endpoint; - grpc_winsocket_callback_info *info = &ac->socket->write_info; - grpc_closure *on_done = ac->on_done; - - grpc_timer_cancel(exec_ctx, &ac->alarm); - - gpr_mu_lock(&ac->mu); - - if (from_iocp) { - DWORD transfered_bytes = 0; - DWORD flags; - BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, - &transfered_bytes, FALSE, &flags); - GPR_ASSERT(transfered_bytes == 0); - if (!wsa_success) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); - gpr_free(utf8_message); - } else { - *ep = grpc_tcp_create(ac->socket, ac->addr_name); - ac->socket = NULL; - } - } - - async_connect_unlock_and_cleanup(ac); - /* If the connection was aborted, the callback was already called when - the deadline was met. */ - on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL); -} - -/* Tries to issue one async connection, then schedules both an IOCP - notification request for the connection, and one timeout alert. */ -void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done, - grpc_endpoint **endpoint, - grpc_pollset_set *interested_parties, - const struct sockaddr *addr, size_t addr_len, - gpr_timespec deadline) { - SOCKET sock = INVALID_SOCKET; - BOOL success; - int status; - struct sockaddr_in6 addr6_v4mapped; - struct sockaddr_in6 local_address; - async_connect *ac; - grpc_winsocket *socket = NULL; - LPFN_CONNECTEX ConnectEx; - GUID guid = WSAID_CONNECTEX; - DWORD ioctl_num_bytes; - const char *message = NULL; - char *utf8_message; - grpc_winsocket_callback_info *info; - - *endpoint = NULL; - - /* Use dualstack sockets where available. */ - if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { - addr = (const struct sockaddr *)&addr6_v4mapped; - addr_len = sizeof(addr6_v4mapped); - } - - sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, - WSA_FLAG_OVERLAPPED); - if (sock == INVALID_SOCKET) { - message = "Unable to create socket: %s"; - goto failure; - } - - if (!grpc_tcp_prepare_socket(sock)) { - message = "Unable to set socket options: %s"; - goto failure; - } - - /* Grab the function pointer for ConnectEx for that specific socket. - It may change depending on the interface. */ - status = - WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), - &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL); - - if (status != 0) { - message = "Unable to retrieve ConnectEx pointer: %s"; - goto failure; - } - - grpc_sockaddr_make_wildcard6(0, &local_address); - - status = bind(sock, (struct sockaddr *)&local_address, sizeof(local_address)); - if (status != 0) { - message = "Unable to bind socket: %s"; - goto failure; - } - - socket = grpc_winsocket_create(sock, "client"); - info = &socket->write_info; - success = - ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped); - - /* It wouldn't be unusual to get a success immediately. But we'll still get - an IOCP notification, so let's ignore it. */ - if (!success) { - int error = WSAGetLastError(); - if (error != ERROR_IO_PENDING) { - message = "ConnectEx failed: %s"; - goto failure; - } - } - - ac = gpr_malloc(sizeof(async_connect)); - ac->on_done = on_done; - ac->socket = socket; - gpr_mu_init(&ac->mu); - ac->refs = 2; - ac->addr_name = grpc_sockaddr_to_uri(addr); - ac->endpoint = endpoint; - grpc_closure_init(&ac->on_connect, on_connect, ac); - - grpc_timer_init(exec_ctx, &ac->alarm, deadline, on_alarm, ac, - gpr_now(GPR_CLOCK_MONOTONIC)); - grpc_socket_notify_on_write(exec_ctx, socket, &ac->on_connect); - return; - -failure: - utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, message, utf8_message); - gpr_free(utf8_message); - if (socket != NULL) { - grpc_winsocket_destroy(socket); - } else if (sock != INVALID_SOCKET) { - closesocket(sock); - } - grpc_exec_ctx_enqueue(exec_ctx, on_done, false, NULL); -} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c deleted file mode 100644 index f74eb3fe51..0000000000 --- a/src/core/iomgr/tcp_posix.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/tcp_posix.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/slice.h> -#include <grpc/support/string_util.h> -#include <grpc/support/sync.h> -#include <grpc/support/time.h> - -#include "src/core/debug/trace.h" -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/iomgr/pollset_set_posix.h" -#include "src/core/profiling/timers.h" -#include "src/core/support/string.h" - -#ifdef GPR_HAVE_MSG_NOSIGNAL -#define SENDMSG_FLAGS MSG_NOSIGNAL -#else -#define SENDMSG_FLAGS 0 -#endif - -#ifdef GPR_MSG_IOVLEN_TYPE -typedef GPR_MSG_IOVLEN_TYPE msg_iovlen_type; -#else -typedef size_t msg_iovlen_type; -#endif - -int grpc_tcp_trace = 0; - -typedef struct { - grpc_endpoint base; - grpc_fd *em_fd; - int fd; - int finished_edge; - msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */ - size_t slice_size; - gpr_refcount refcount; - - /* garbage after the last read */ - gpr_slice_buffer last_read_buffer; - - gpr_slice_buffer *incoming_buffer; - gpr_slice_buffer *outgoing_buffer; - /** slice within outgoing_buffer to write next */ - size_t outgoing_slice_idx; - /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */ - size_t outgoing_byte_idx; - - grpc_closure *read_cb; - grpc_closure *write_cb; - grpc_closure *release_fd_cb; - int *release_fd; - - grpc_closure read_closure; - grpc_closure write_closure; - - char *peer_string; -} grpc_tcp; - -static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, - bool success); -static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, - bool success); - -static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_fd_shutdown(exec_ctx, tcp->em_fd); -} - -static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { - grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd, - "tcp_unref_orphan"); - gpr_slice_buffer_destroy(&tcp->last_read_buffer); - gpr_free(tcp->peer_string); - gpr_free(tcp); -} - -/*#define GRPC_TCP_REFCOUNT_DEBUG*/ -#ifdef GRPC_TCP_REFCOUNT_DEBUG -#define TCP_UNREF(cl, tcp, reason) \ - tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__) -#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) -static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, - const char *reason, const char *file, int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count - 1); - if (gpr_unref(&tcp->refcount)) { - tcp_free(exec_ctx, tcp); - } -} - -static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count + 1); - gpr_ref(&tcp->refcount); -} -#else -#define TCP_UNREF(cl, tcp, reason) tcp_unref((cl), (tcp)) -#define TCP_REF(tcp, reason) tcp_ref((tcp)) -static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { - if (gpr_unref(&tcp->refcount)) { - tcp_free(exec_ctx, tcp); - } -} - -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } -#endif - -static void tcp_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - TCP_UNREF(exec_ctx, tcp, "destroy"); -} - -static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) { - grpc_closure *cb = tcp->read_cb; - - if (grpc_tcp_trace) { - size_t i; - gpr_log(GPR_DEBUG, "read: success=%d", success); - for (i = 0; i < tcp->incoming_buffer->count; i++) { - char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump); - gpr_free(dump); - } - } - - tcp->read_cb = NULL; - tcp->incoming_buffer = NULL; - cb->cb(exec_ctx, cb->cb_arg, success); -} - -#define MAX_READ_IOVEC 4 -static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { - struct msghdr msg; - struct iovec iov[MAX_READ_IOVEC]; - ssize_t read_bytes; - size_t i; - - GPR_ASSERT(!tcp->finished_edge); - GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); - GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); - GPR_TIMER_BEGIN("tcp_continue_read", 0); - - while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) { - gpr_slice_buffer_add_indexed(tcp->incoming_buffer, - gpr_slice_malloc(tcp->slice_size)); - } - for (i = 0; i < tcp->incoming_buffer->count; i++) { - iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); - iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); - } - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = tcp->iov_size; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - GPR_TIMER_BEGIN("recvmsg", 1); - do { - read_bytes = recvmsg(tcp->fd, &msg, 0); - } while (read_bytes < 0 && errno == EINTR); - GPR_TIMER_END("recvmsg", 0); - - if (read_bytes < 0) { - /* NB: After calling call_read_cb a parallel call of the read handler may - * be running. */ - if (errno == EAGAIN) { - if (tcp->iov_size > 1) { - tcp->iov_size /= 2; - } - /* We've consumed the edge, request a new one */ - grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure); - } else { - /* TODO(klempner): Log interesting errors */ - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(exec_ctx, tcp, 0); - TCP_UNREF(exec_ctx, tcp, "read"); - } - } else if (read_bytes == 0) { - /* 0 read size ==> end of stream */ - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(exec_ctx, tcp, 0); - TCP_UNREF(exec_ctx, tcp, "read"); - } else { - GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); - if ((size_t)read_bytes < tcp->incoming_buffer->length) { - gpr_slice_buffer_trim_end( - tcp->incoming_buffer, - tcp->incoming_buffer->length - (size_t)read_bytes, - &tcp->last_read_buffer); - } else if (tcp->iov_size < MAX_READ_IOVEC) { - ++tcp->iov_size; - } - GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); - call_read_cb(exec_ctx, tcp, 1); - TCP_UNREF(exec_ctx, tcp, "read"); - } - - GPR_TIMER_END("tcp_continue_read", 0); -} - -static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, - bool success) { - grpc_tcp *tcp = (grpc_tcp *)arg; - GPR_ASSERT(!tcp->finished_edge); - - if (!success) { - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(exec_ctx, tcp, 0); - TCP_UNREF(exec_ctx, tcp, "read"); - } else { - tcp_continue_read(exec_ctx, tcp); - } -} - -static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *incoming_buffer, grpc_closure *cb) { - grpc_tcp *tcp = (grpc_tcp *)ep; - GPR_ASSERT(tcp->read_cb == NULL); - tcp->read_cb = cb; - tcp->incoming_buffer = incoming_buffer; - gpr_slice_buffer_reset_and_unref(incoming_buffer); - gpr_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer); - TCP_REF(tcp, "read"); - if (tcp->finished_edge) { - tcp->finished_edge = 0; - grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure); - } else { - grpc_exec_ctx_enqueue(exec_ctx, &tcp->read_closure, true, NULL); - } -} - -typedef enum { FLUSH_DONE, FLUSH_PENDING, FLUSH_ERROR } flush_result; - -#define MAX_WRITE_IOVEC 16 -static flush_result tcp_flush(grpc_tcp *tcp) { - struct msghdr msg; - struct iovec iov[MAX_WRITE_IOVEC]; - msg_iovlen_type iov_size; - ssize_t sent_length; - size_t sending_length; - size_t trailing; - size_t unwind_slice_idx; - size_t unwind_byte_idx; - - for (;;) { - sending_length = 0; - unwind_slice_idx = tcp->outgoing_slice_idx; - unwind_byte_idx = tcp->outgoing_byte_idx; - for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && - iov_size != MAX_WRITE_IOVEC; - iov_size++) { - iov[iov_size].iov_base = - GPR_SLICE_START_PTR( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + - tcp->outgoing_byte_idx; - iov[iov_size].iov_len = - GPR_SLICE_LENGTH( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - - tcp->outgoing_byte_idx; - sending_length += iov[iov_size].iov_len; - tcp->outgoing_slice_idx++; - tcp->outgoing_byte_idx = 0; - } - GPR_ASSERT(iov_size > 0); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = iov_size; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - GPR_TIMER_BEGIN("sendmsg", 1); - do { - /* TODO(klempner): Cork if this is a partial write */ - sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); - } while (sent_length < 0 && errno == EINTR); - GPR_TIMER_END("sendmsg", 0); - - if (sent_length < 0) { - if (errno == EAGAIN) { - tcp->outgoing_slice_idx = unwind_slice_idx; - tcp->outgoing_byte_idx = unwind_byte_idx; - return FLUSH_PENDING; - } else { - /* TODO(klempner): Log some of these */ - return FLUSH_ERROR; - } - } - - GPR_ASSERT(tcp->outgoing_byte_idx == 0); - trailing = sending_length - (size_t)sent_length; - while (trailing > 0) { - size_t slice_length; - - tcp->outgoing_slice_idx--; - slice_length = GPR_SLICE_LENGTH( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); - if (slice_length > trailing) { - tcp->outgoing_byte_idx = slice_length - trailing; - break; - } else { - trailing -= slice_length; - } - } - - if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { - return FLUSH_DONE; - } - }; -} - -static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, - bool success) { - grpc_tcp *tcp = (grpc_tcp *)arg; - flush_result status; - grpc_closure *cb; - - if (!success) { - cb = tcp->write_cb; - tcp->write_cb = NULL; - cb->cb(exec_ctx, cb->cb_arg, 0); - TCP_UNREF(exec_ctx, tcp, "write"); - return; - } - - status = tcp_flush(tcp); - if (status == FLUSH_PENDING) { - grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); - } else { - cb = tcp->write_cb; - tcp->write_cb = NULL; - GPR_TIMER_BEGIN("tcp_handle_write.cb", 0); - cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE); - GPR_TIMER_END("tcp_handle_write.cb", 0); - TCP_UNREF(exec_ctx, tcp, "write"); - } -} - -static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *buf, grpc_closure *cb) { - grpc_tcp *tcp = (grpc_tcp *)ep; - flush_result status; - - if (grpc_tcp_trace) { - size_t i; - - for (i = 0; i < buf->count; i++) { - char *data = - gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); - gpr_free(data); - } - } - - GPR_TIMER_BEGIN("tcp_write", 0); - GPR_ASSERT(tcp->write_cb == NULL); - - if (buf->length == 0) { - GPR_TIMER_END("tcp_write", 0); - grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL); - return; - } - tcp->outgoing_buffer = buf; - tcp->outgoing_slice_idx = 0; - tcp->outgoing_byte_idx = 0; - - status = tcp_flush(tcp); - if (status == FLUSH_PENDING) { - TCP_REF(tcp, "write"); - tcp->write_cb = cb; - grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); - } else { - grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE, NULL); - } - - GPR_TIMER_END("tcp_write", 0); -} - -static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_pollset_add_fd(exec_ctx, pollset, tcp->em_fd); -} - -static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pollset_set) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd); -} - -static char *tcp_get_peer(grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - return gpr_strdup(tcp->peer_string); -} - -static const grpc_endpoint_vtable vtable = { - tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, - tcp_shutdown, tcp_destroy, tcp_get_peer}; - -grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, - const char *peer_string) { - grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); - tcp->base.vtable = &vtable; - tcp->peer_string = gpr_strdup(peer_string); - tcp->fd = em_fd->fd; - tcp->read_cb = NULL; - tcp->write_cb = NULL; - tcp->release_fd_cb = NULL; - tcp->release_fd = NULL; - tcp->incoming_buffer = NULL; - tcp->slice_size = slice_size; - tcp->iov_size = 1; - tcp->finished_edge = 1; - /* paired with unref in grpc_tcp_destroy */ - gpr_ref_init(&tcp->refcount, 1); - tcp->em_fd = em_fd; - tcp->read_closure.cb = tcp_handle_read; - tcp->read_closure.cb_arg = tcp; - tcp->write_closure.cb = tcp_handle_write; - tcp->write_closure.cb_arg = tcp; - gpr_slice_buffer_init(&tcp->last_read_buffer); - - return &tcp->base; -} - -int grpc_tcp_fd(grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - GPR_ASSERT(ep->vtable == &vtable); - return grpc_fd_wrapped_fd(tcp->em_fd); -} - -void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - int *fd, grpc_closure *done) { - grpc_tcp *tcp = (grpc_tcp *)ep; - GPR_ASSERT(ep->vtable == &vtable); - tcp->release_fd = fd; - tcp->release_fd_cb = done; - TCP_UNREF(exec_ctx, tcp, "destroy"); -} - -#endif diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h deleted file mode 100644 index 2a40cdd385..0000000000 --- a/src/core/iomgr/tcp_posix.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H -/* - Low level TCP "bottom half" implementation, for use by transports built on - top of a TCP connection. - - Note that this file does not (yet) include APIs for creating the socket in - the first place. - - All calls passing slice transfer ownership of a slice refcount unless - otherwise specified. -*/ - -#include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/fd_posix.h" - -#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 - -extern int grpc_tcp_trace; - -/* Create a tcp endpoint given a file desciptor and a read slice size. - Takes ownership of fd. */ -grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size, - const char *peer_string); - -/* Return the tcp endpoint's fd, or -1 if this is not available. Does not - release the fd. - Requires: ep must be a tcp endpoint. - */ -int grpc_tcp_fd(grpc_endpoint *ep); - -/* Destroy the tcp endpoint without closing its fd. *fd will be set and done - * will be called when the endpoint is destroyed. - * Requires: ep must be a tcp endpoint and fd must not be NULL. */ -void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - int *fd, grpc_closure *done); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */ diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h deleted file mode 100644 index a39dd3bafc..0000000000 --- a/src/core/iomgr/tcp_server.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H -#define GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H - -#include "src/core/iomgr/closure.h" -#include "src/core/iomgr/endpoint.h" - -/* Forward decl of grpc_tcp_server */ -typedef struct grpc_tcp_server grpc_tcp_server; - -typedef struct grpc_tcp_server_acceptor { - /* grpc_tcp_server_cb functions share a ref on from_server that is valid - until the function returns. */ - grpc_tcp_server *from_server; - /* Indices that may be passed to grpc_tcp_server_port_fd(). */ - unsigned port_index; - unsigned fd_index; -} grpc_tcp_server_acceptor; - -/* Called for newly connected TCP connections. */ -typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg, - grpc_endpoint *ep, - grpc_tcp_server_acceptor *acceptor); - -/* Create a server, initially not bound to any ports. The caller owns one ref. - If shutdown_complete is not NULL, it will be used by - grpc_tcp_server_unref() when the ref count reaches zero. */ -grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete); - -/* Start listening to bound ports */ -void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server, - grpc_pollset **pollsets, size_t pollset_count, - grpc_tcp_server_cb on_accept_cb, void *cb_arg); - -/* Add a port to the server, returning the newly allocated port on success, or - -1 on failure. - - The :: and 0.0.0.0 wildcard addresses are treated identically, accepting - both IPv4 and IPv6 connections, but :: is the preferred style. This usually - creates one socket, but possibly two on systems which support IPv6, - but not dualstack sockets. */ -/* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle - all of the multiple socket port matching logic in one place */ -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len); - -/* Number of fds at the given port_index, or 0 if port_index is out of - bounds. */ -unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index); - -/* Returns the file descriptor of the Mth (fd_index) listening socket of the Nth - (port_index) call to add_port() on this server, or -1 if the indices are out - of bounds. The file descriptor remains owned by the server, and will be - cleaned up when the ref count reaches zero. */ -int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, - unsigned fd_index); - -/* Ref s and return s. */ -grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s); - -/* shutdown_starting is called when ref count has reached zero and the server is - about to be destroyed. The server will be deleted after it returns. Calling - grpc_tcp_server_ref() from it has no effect. */ -void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, - grpc_closure *shutdown_starting); - -/* If the refcount drops to zero, delete s, and call (exec_ctx==NULL) or enqueue - a call (exec_ctx!=NULL) to shutdown_complete. */ -void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */ diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c deleted file mode 100644 index 5e07f8261c..0000000000 --- a/src/core/iomgr/tcp_server_posix.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/tcp_server.h" - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <stdio.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/un.h> -#include <unistd.h> - -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/iomgr/resolve_address.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/socket_utils_posix.h" -#include "src/core/iomgr/tcp_posix.h" -#include "src/core/support/string.h" -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/sync.h> -#include <grpc/support/time.h> - -#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 - -static gpr_once s_init_max_accept_queue_size; -static int s_max_accept_queue_size; - -/* one listening port */ -typedef struct grpc_tcp_listener grpc_tcp_listener; -struct grpc_tcp_listener { - int fd; - grpc_fd *emfd; - grpc_tcp_server *server; - union { - uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE]; - struct sockaddr sockaddr; - struct sockaddr_un un; - } addr; - size_t addr_len; - int port; - unsigned port_index; - unsigned fd_index; - grpc_closure read_closure; - grpc_closure destroyed_closure; - struct grpc_tcp_listener *next; - /* When we add a listener, more than one can be created, mainly because of - IPv6. A sibling will still be in the normal list, but will be flagged - as such. Any action, such as ref or unref, will affect all of the - siblings in the list. */ - struct grpc_tcp_listener *sibling; - int is_sibling; -}; - -static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) { - struct stat st; - - if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) { - unlink(un->sun_path); - } -} - -/* the overall server */ -struct grpc_tcp_server { - gpr_refcount refs; - /* Called whenever accept() succeeds on a server port. */ - grpc_tcp_server_cb on_accept_cb; - void *on_accept_cb_arg; - - gpr_mu mu; - - /* active port count: how many ports are actually still listening */ - size_t active_ports; - /* destroyed port count: how many ports are completely destroyed */ - size_t destroyed_ports; - - /* is this server shutting down? (boolean) */ - int shutdown; - - /* linked list of server ports */ - grpc_tcp_listener *head; - grpc_tcp_listener *tail; - unsigned nports; - - /* List of closures passed to shutdown_starting_add(). */ - grpc_closure_list shutdown_starting; - - /* shutdown callback */ - grpc_closure *shutdown_complete; - - /* all pollsets interested in new connections */ - grpc_pollset **pollsets; - /* number of pollsets in the pollsets array */ - size_t pollset_count; -}; - -grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) { - grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); - gpr_ref_init(&s->refs, 1); - gpr_mu_init(&s->mu); - s->active_ports = 0; - s->destroyed_ports = 0; - s->shutdown = 0; - s->shutdown_starting.head = NULL; - s->shutdown_starting.tail = NULL; - s->shutdown_complete = shutdown_complete; - s->on_accept_cb = NULL; - s->on_accept_cb_arg = NULL; - s->head = NULL; - s->tail = NULL; - s->nports = 0; - return s; -} - -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - if (s->shutdown_complete != NULL) { - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL); - } - - gpr_mu_destroy(&s->mu); - - while (s->head) { - grpc_tcp_listener *sp = s->head; - s->head = sp->next; - gpr_free(sp); - } - - gpr_free(s); -} - -static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, - bool success) { - grpc_tcp_server *s = server; - gpr_mu_lock(&s->mu); - s->destroyed_ports++; - if (s->destroyed_ports == s->nports) { - gpr_mu_unlock(&s->mu); - finish_shutdown(exec_ctx, s); - } else { - GPR_ASSERT(s->destroyed_ports < s->nports); - gpr_mu_unlock(&s->mu); - } -} - -/* called when all listening endpoints have been shutdown, so no further - events will be received on them - at this point it's safe to destroy - things */ -static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - /* delete ALL the things */ - gpr_mu_lock(&s->mu); - - if (!s->shutdown) { - gpr_mu_unlock(&s->mu); - return; - } - - if (s->head) { - grpc_tcp_listener *sp; - for (sp = s->head; sp; sp = sp->next) { - if (sp->addr.sockaddr.sa_family == AF_UNIX) { - unlink_if_unix_domain_socket(&sp->addr.un); - } - sp->destroyed_closure.cb = destroyed_port; - sp->destroyed_closure.cb_arg = s; - grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, - "tcp_listener_shutdown"); - } - gpr_mu_unlock(&s->mu); - } else { - gpr_mu_unlock(&s->mu); - finish_shutdown(exec_ctx, s); - } -} - -static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - gpr_mu_lock(&s->mu); - - GPR_ASSERT(!s->shutdown); - s->shutdown = 1; - - /* shutdown all fd's */ - if (s->active_ports) { - grpc_tcp_listener *sp; - for (sp = s->head; sp; sp = sp->next) { - grpc_fd_shutdown(exec_ctx, sp->emfd); - } - gpr_mu_unlock(&s->mu); - } else { - gpr_mu_unlock(&s->mu); - deactivated_all_ports(exec_ctx, s); - } -} - -/* get max listen queue size on linux */ -static void init_max_accept_queue_size(void) { - int n = SOMAXCONN; - char buf[64]; - FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); - if (fp == NULL) { - /* 2.4 kernel. */ - s_max_accept_queue_size = SOMAXCONN; - return; - } - if (fgets(buf, sizeof buf, fp)) { - char *end; - long i = strtol(buf, &end, 10); - if (i > 0 && i <= INT_MAX && end && *end == 0) { - n = (int)i; - } - } - fclose(fp); - s_max_accept_queue_size = n; - - if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { - gpr_log(GPR_INFO, - "Suspiciously small accept queue (%d) will probably lead to " - "connection drops", - s_max_accept_queue_size); - } -} - -static int get_max_accept_queue_size(void) { - gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); - return s_max_accept_queue_size; -} - -/* Prepare a recently-created socket for listening. */ -static int prepare_socket(int fd, const struct sockaddr *addr, - size_t addr_len) { - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - - if (fd < 0) { - goto error; - } - - if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) || - (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) || - !grpc_set_socket_reuse_addr(fd, 1))) || - !grpc_set_socket_no_sigpipe_if_possible(fd)) { - gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd, - strerror(errno)); - goto error; - } - - GPR_ASSERT(addr_len < ~(socklen_t)0); - if (bind(fd, addr, (socklen_t)addr_len) < 0) { - char *addr_str; - grpc_sockaddr_to_string(&addr_str, addr, 0); - gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno)); - gpr_free(addr_str); - goto error; - } - - if (listen(fd, get_max_accept_queue_size()) < 0) { - gpr_log(GPR_ERROR, "listen: %s", strerror(errno)); - goto error; - } - - sockname_len = sizeof(sockname_temp); - if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) { - goto error; - } - - return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - -error: - if (fd >= 0) { - close(fd); - } - return -1; -} - -/* event manager callback when reads are ready */ -static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - grpc_tcp_listener *sp = arg; - grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, - sp->fd_index}; - grpc_fd *fdobj; - size_t i; - - if (!success) { - goto error; - } - - /* loop until accept4 returns EAGAIN, and then re-arm notification */ - for (;;) { - struct sockaddr_storage addr; - socklen_t addrlen = sizeof(addr); - char *addr_str; - char *name; - /* Note: If we ever decide to return this address to the user, remember to - strip off the ::ffff:0.0.0.0/96 prefix first. */ - int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1); - if (fd < 0) { - switch (errno) { - case EINTR: - continue; - case EAGAIN: - grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); - return; - default: - gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); - goto error; - } - } - - grpc_set_socket_no_sigpipe_if_possible(fd); - - addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr); - gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); - - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str); - } - - fdobj = grpc_fd_create(fd, name); - /* TODO(ctiller): revise this when we have server-side sharding - of channels -- we certainly should not be automatically adding every - incoming channel to every pollset owned by the server */ - for (i = 0; i < sp->server->pollset_count; i++) { - grpc_pollset_add_fd(exec_ctx, sp->server->pollsets[i], fdobj); - } - sp->server->on_accept_cb( - exec_ctx, sp->server->on_accept_cb_arg, - grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str), - &acceptor); - - gpr_free(name); - gpr_free(addr_str); - } - - GPR_UNREACHABLE_CODE(return ); - -error: - gpr_mu_lock(&sp->server->mu); - if (0 == --sp->server->active_ports) { - gpr_mu_unlock(&sp->server->mu); - deactivated_all_ports(exec_ctx, sp->server); - } else { - gpr_mu_unlock(&sp->server->mu); - } -} - -static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd, - const struct sockaddr *addr, - size_t addr_len, - unsigned port_index, - unsigned fd_index) { - grpc_tcp_listener *sp = NULL; - int port; - char *addr_str; - char *name; - - port = prepare_socket(fd, addr, addr_len); - if (port >= 0) { - grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); - gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); - gpr_mu_lock(&s->mu); - s->nports++; - GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - sp = gpr_malloc(sizeof(grpc_tcp_listener)); - sp->next = NULL; - if (s->head == NULL) { - s->head = sp; - } else { - s->tail->next = sp; - } - s->tail = sp; - sp->server = s; - sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); - memcpy(sp->addr.untyped, addr, addr_len); - sp->addr_len = addr_len; - sp->port = port; - sp->port_index = port_index; - sp->fd_index = fd_index; - sp->is_sibling = 0; - sp->sibling = NULL; - GPR_ASSERT(sp->emfd); - gpr_mu_unlock(&s->mu); - gpr_free(addr_str); - gpr_free(name); - } - - return sp; -} - -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len) { - grpc_tcp_listener *sp; - grpc_tcp_listener *sp2 = NULL; - int fd; - grpc_dualstack_mode dsmode; - struct sockaddr_in6 addr6_v4mapped; - struct sockaddr_in wild4; - struct sockaddr_in6 wild6; - struct sockaddr_in addr4_copy; - struct sockaddr *allocated_addr = NULL; - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - int port; - unsigned port_index = 0; - unsigned fd_index = 0; - if (s->tail != NULL) { - port_index = s->tail->port_index + 1; - } - if (((struct sockaddr *)addr)->sa_family == AF_UNIX) { - unlink_if_unix_domain_socket(addr); - } - - /* Check if this is a wildcard port, and if so, try to keep the port the same - as some previously created listener. */ - if (grpc_sockaddr_get_port(addr) == 0) { - for (sp = s->head; sp; sp = sp->next) { - sockname_len = sizeof(sockname_temp); - if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp, - &sockname_len)) { - port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - if (port > 0) { - allocated_addr = malloc(addr_len); - memcpy(allocated_addr, addr, addr_len); - grpc_sockaddr_set_port(allocated_addr, port); - addr = allocated_addr; - break; - } - } - } - } - - sp = NULL; - - if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { - addr = (const struct sockaddr *)&addr6_v4mapped; - addr_len = sizeof(addr6_v4mapped); - } - - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ - if (grpc_sockaddr_is_wildcard(addr, &port)) { - grpc_sockaddr_make_wildcards(port, &wild4, &wild6); - - /* Try listening on IPv6 first. */ - addr = (struct sockaddr *)&wild6; - addr_len = sizeof(wild6); - fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode); - sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index); - if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { - goto done; - } - if (sp != NULL) { - ++fd_index; - } - /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */ - if (port == 0 && sp != NULL) { - grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port); - sp2 = sp; - } - addr = (struct sockaddr *)&wild4; - addr_len = sizeof(wild4); - } - - fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode); - if (fd < 0) { - gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); - } - if (dsmode == GRPC_DSMODE_IPV4 && - grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { - addr = (struct sockaddr *)&addr4_copy; - addr_len = sizeof(addr4_copy); - } - sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index); - if (sp2 != NULL && sp != NULL) { - sp2->sibling = sp; - sp->is_sibling = 1; - } - -done: - gpr_free(allocated_addr); - if (sp != NULL) { - return sp->port; - } else { - return -1; - } -} - -unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, - unsigned port_index) { - unsigned num_fds = 0; - grpc_tcp_listener *sp; - for (sp = s->head; sp && port_index != 0; sp = sp->next) { - if (!sp->is_sibling) { - --port_index; - } - } - for (; sp; sp = sp->sibling, ++num_fds) - ; - return num_fds; -} - -int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, - unsigned fd_index) { - grpc_tcp_listener *sp; - for (sp = s->head; sp && port_index != 0; sp = sp->next) { - if (!sp->is_sibling) { - --port_index; - } - } - for (; sp && fd_index != 0; sp = sp->sibling, --fd_index) - ; - if (sp) { - return sp->fd; - } else { - return -1; - } -} - -void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, - grpc_pollset **pollsets, size_t pollset_count, - grpc_tcp_server_cb on_accept_cb, - void *on_accept_cb_arg) { - size_t i; - grpc_tcp_listener *sp; - GPR_ASSERT(on_accept_cb); - gpr_mu_lock(&s->mu); - GPR_ASSERT(!s->on_accept_cb); - GPR_ASSERT(s->active_ports == 0); - s->on_accept_cb = on_accept_cb; - s->on_accept_cb_arg = on_accept_cb_arg; - s->pollsets = pollsets; - s->pollset_count = pollset_count; - for (sp = s->head; sp; sp = sp->next) { - for (i = 0; i < pollset_count; i++) { - grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); - } - sp->read_closure.cb = on_read; - sp->read_closure.cb_arg = sp; - grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); - s->active_ports++; - } - gpr_mu_unlock(&s->mu); -} - -grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { - gpr_ref(&s->refs); - return s; -} - -void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, - grpc_closure *shutdown_starting) { - gpr_mu_lock(&s->mu); - grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1); - gpr_mu_unlock(&s->mu); -} - -void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - if (gpr_unref(&s->refs)) { - /* Complete shutdown_starting work before destroying. */ - grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_mu_lock(&s->mu); - grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL); - gpr_mu_unlock(&s->mu); - if (exec_ctx == NULL) { - grpc_exec_ctx_flush(&local_exec_ctx); - tcp_server_destroy(&local_exec_ctx, s); - grpc_exec_ctx_finish(&local_exec_ctx); - } else { - grpc_exec_ctx_finish(&local_exec_ctx); - tcp_server_destroy(exec_ctx, s); - } - } -} - -#endif diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c deleted file mode 100644 index a4abc5b974..0000000000 --- a/src/core/iomgr/tcp_server_windows.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include <io.h> - -#include "src/core/iomgr/sockaddr_utils.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/string_util.h> -#include <grpc/support/sync.h> -#include <grpc/support/time.h> - -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/pollset_windows.h" -#include "src/core/iomgr/socket_windows.h" -#include "src/core/iomgr/tcp_server.h" -#include "src/core/iomgr/tcp_windows.h" - -#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 - -/* one listening port */ -typedef struct grpc_tcp_listener grpc_tcp_listener; -struct grpc_tcp_listener { - /* This seemingly magic number comes from AcceptEx's documentation. each - address buffer needs to have at least 16 more bytes at their end. */ - uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2]; - /* This will hold the socket for the next accept. */ - SOCKET new_socket; - /* The listener winsocket. */ - grpc_winsocket *socket; - /* The actual TCP port number. */ - int port; - unsigned port_index; - grpc_tcp_server *server; - /* The cached AcceptEx for that port. */ - LPFN_ACCEPTEX AcceptEx; - int shutting_down; - /* closure for socket notification of accept being ready */ - grpc_closure on_accept; - /* linked list */ - struct grpc_tcp_listener *next; -}; - -/* the overall server */ -struct grpc_tcp_server { - gpr_refcount refs; - /* Called whenever accept() succeeds on a server port. */ - grpc_tcp_server_cb on_accept_cb; - void *on_accept_cb_arg; - - gpr_mu mu; - - /* active port count: how many ports are actually still listening */ - int active_ports; - - /* linked list of server ports */ - grpc_tcp_listener *head; - grpc_tcp_listener *tail; - - /* List of closures passed to shutdown_starting_add(). */ - grpc_closure_list shutdown_starting; - - /* shutdown callback */ - grpc_closure *shutdown_complete; -}; - -/* Public function. Allocates the proper data structures to hold a - grpc_tcp_server. */ -grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) { - grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); - gpr_ref_init(&s->refs, 1); - gpr_mu_init(&s->mu); - s->active_ports = 0; - s->on_accept_cb = NULL; - s->on_accept_cb_arg = NULL; - s->head = NULL; - s->tail = NULL; - s->shutdown_starting.head = NULL; - s->shutdown_starting.tail = NULL; - s->shutdown_complete = shutdown_complete; - return s; -} - -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - if (s->shutdown_complete != NULL) { - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL); - } - - /* Now that the accepts have been aborted, we can destroy the sockets. - The IOCP won't get notified on these, so we can flag them as already - closed by the system. */ - while (s->head) { - grpc_tcp_listener *sp = s->head; - s->head = sp->next; - sp->next = NULL; - grpc_winsocket_destroy(sp->socket); - gpr_free(sp); - } - gpr_free(s); -} - -grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { - gpr_ref(&s->refs); - return s; -} - -void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, - grpc_closure *shutdown_starting) { - gpr_mu_lock(&s->mu); - grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1); - gpr_mu_unlock(&s->mu); -} - -static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - int immediately_done = 0; - grpc_tcp_listener *sp; - gpr_mu_lock(&s->mu); - - /* First, shutdown all fd's. This will queue abortion calls for all - of the pending accepts due to the normal operation mechanism. */ - if (s->active_ports == 0) { - immediately_done = 1; - } - for (sp = s->head; sp; sp = sp->next) { - sp->shutting_down = 1; - grpc_winsocket_shutdown(sp->socket); - } - gpr_mu_unlock(&s->mu); - - if (immediately_done) { - finish_shutdown(exec_ctx, s); - } -} - -void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - if (gpr_unref(&s->refs)) { - /* Complete shutdown_starting work before destroying. */ - grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_mu_lock(&s->mu); - grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL); - gpr_mu_unlock(&s->mu); - if (exec_ctx == NULL) { - grpc_exec_ctx_flush(&local_exec_ctx); - tcp_server_destroy(&local_exec_ctx, s); - grpc_exec_ctx_finish(&local_exec_ctx); - } else { - grpc_exec_ctx_finish(&local_exec_ctx); - tcp_server_destroy(exec_ctx, s); - } - } -} - -/* Prepare (bind) a recently-created socket for listening. */ -static int prepare_socket(SOCKET sock, const struct sockaddr *addr, - size_t addr_len) { - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - - if (sock == INVALID_SOCKET) goto error; - - if (!grpc_tcp_prepare_socket(sock)) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message); - gpr_free(utf8_message); - goto error; - } - - if (bind(sock, addr, (int)addr_len) == SOCKET_ERROR) { - char *addr_str; - char *utf8_message = gpr_format_message(WSAGetLastError()); - grpc_sockaddr_to_string(&addr_str, addr, 0); - gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message); - gpr_free(utf8_message); - gpr_free(addr_str); - goto error; - } - - if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "listen: %s", utf8_message); - gpr_free(utf8_message); - goto error; - } - - sockname_len = sizeof(sockname_temp); - if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) == - SOCKET_ERROR) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "getsockname: %s", utf8_message); - gpr_free(utf8_message); - goto error; - } - - return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - -error: - if (sock != INVALID_SOCKET) closesocket(sock); - return -1; -} - -static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx, - grpc_tcp_listener *sp) { - int notify = 0; - sp->shutting_down = 0; - gpr_mu_lock(&sp->server->mu); - GPR_ASSERT(sp->server->active_ports > 0); - if (0 == --sp->server->active_ports) { - notify = 1; - } - gpr_mu_unlock(&sp->server->mu); - if (notify) { - finish_shutdown(exec_ctx, sp->server); - } -} - -/* In order to do an async accept, we need to create a socket first which - will be the one assigned to the new incoming connection. */ -static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) { - SOCKET sock = INVALID_SOCKET; - char *message; - char *utf8_message; - BOOL success; - DWORD addrlen = sizeof(struct sockaddr_in6) + 16; - DWORD bytes_received = 0; - - sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, - WSA_FLAG_OVERLAPPED); - - if (sock == INVALID_SOCKET) { - message = "Unable to create socket: %s"; - goto failure; - } - - if (!grpc_tcp_prepare_socket(sock)) { - message = "Unable to prepare socket: %s"; - goto failure; - } - - /* Start the "accept" asynchronously. */ - success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0, - addrlen, addrlen, &bytes_received, - &port->socket->read_info.overlapped); - - /* It is possible to get an accept immediately without delay. However, we - will still get an IOCP notification for it. So let's just ignore it. */ - if (!success) { - int error = WSAGetLastError(); - if (error != ERROR_IO_PENDING) { - message = "AcceptEx failed: %s"; - goto failure; - } - } - - /* We're ready to do the accept. Calling grpc_socket_notify_on_read may - immediately process an accept that happened in the meantime. */ - port->new_socket = sock; - grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept); - return; - -failure: - if (port->shutting_down) { - /* We are abandoning the listener port, take that into account to prevent - occasional hangs on shutdown. The hang happens when sp->shutting_down - change is not seen by on_accept and we proceed to trying new accept, - but we fail there because the listening port has been closed in the - meantime. */ - decrement_active_ports_and_notify(exec_ctx, port); - return; - } - utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, message, utf8_message); - gpr_free(utf8_message); - if (sock != INVALID_SOCKET) closesocket(sock); -} - -/* Event manager callback when reads are ready. */ -static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, bool from_iocp) { - grpc_tcp_listener *sp = arg; - grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0}; - SOCKET sock = sp->new_socket; - grpc_winsocket_callback_info *info = &sp->socket->read_info; - grpc_endpoint *ep = NULL; - struct sockaddr_storage peer_name; - char *peer_name_string; - char *fd_name; - int peer_name_len = sizeof(peer_name); - DWORD transfered_bytes; - DWORD flags; - BOOL wsa_success; - int err; - - /* The general mechanism for shutting down is to queue abortion calls. While - this is necessary in the read/write case, it's useless for the accept - case. We only need to adjust the pending callback count */ - if (!from_iocp) { - return; - } - - /* The IOCP notified us of a completed operation. Let's grab the results, - and act accordingly. */ - transfered_bytes = 0; - wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, - &transfered_bytes, FALSE, &flags); - if (!wsa_success) { - if (sp->shutting_down) { - /* During the shutdown case, we ARE expecting an error. So that's well, - and we can wake up the shutdown thread. */ - decrement_active_ports_and_notify(exec_ctx, sp); - return; - } else { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message); - gpr_free(utf8_message); - closesocket(sock); - } - } else { - if (!sp->shutting_down) { - peer_name_string = NULL; - err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, - (char *)&sp->socket->socket, sizeof(sp->socket->socket)); - if (err) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message); - gpr_free(utf8_message); - } - err = getpeername(sock, (struct sockaddr *)&peer_name, &peer_name_len); - if (!err) { - peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name); - } else { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message); - gpr_free(utf8_message); - } - gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string); - ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name), - peer_name_string); - gpr_free(fd_name); - gpr_free(peer_name_string); - } else { - closesocket(sock); - } - } - - /* The only time we should call our callback, is where we successfully - managed to accept a connection, and created an endpoint. */ - if (ep) - sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, - &acceptor); - /* As we were notified from the IOCP of one and exactly one accept, - the former socked we created has now either been destroy or assigned - to the new connection. We need to create a new one for the next - connection. */ - start_accept(exec_ctx, sp); -} - -static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, - const struct sockaddr *addr, - size_t addr_len, - unsigned port_index) { - grpc_tcp_listener *sp = NULL; - int port; - int status; - GUID guid = WSAID_ACCEPTEX; - DWORD ioctl_num_bytes; - LPFN_ACCEPTEX AcceptEx; - - if (sock == INVALID_SOCKET) return NULL; - - /* We need to grab the AcceptEx pointer for that port, as it may be - interface-dependent. We'll cache it to avoid doing that again. */ - status = - WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), - &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL); - - if (status != 0) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); - gpr_free(utf8_message); - closesocket(sock); - return NULL; - } - - port = prepare_socket(sock, addr, addr_len); - if (port >= 0) { - gpr_mu_lock(&s->mu); - GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - sp = gpr_malloc(sizeof(grpc_tcp_listener)); - sp->next = NULL; - if (s->head == NULL) { - s->head = sp; - } else { - s->tail->next = sp; - } - s->tail = sp; - sp->server = s; - sp->socket = grpc_winsocket_create(sock, "listener"); - sp->shutting_down = 0; - sp->AcceptEx = AcceptEx; - sp->new_socket = INVALID_SOCKET; - sp->port = port; - sp->port_index = port_index; - grpc_closure_init(&sp->on_accept, on_accept, sp); - GPR_ASSERT(sp->socket); - gpr_mu_unlock(&s->mu); - } - - return sp; -} - -int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, - size_t addr_len) { - grpc_tcp_listener *sp; - SOCKET sock; - struct sockaddr_in6 addr6_v4mapped; - struct sockaddr_in6 wildcard; - struct sockaddr *allocated_addr = NULL; - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - int port; - unsigned port_index = 0; - if (s->tail != NULL) { - port_index = s->tail->port_index + 1; - } - - /* Check if this is a wildcard port, and if so, try to keep the port the same - as some previously created listener. */ - if (grpc_sockaddr_get_port(addr) == 0) { - for (sp = s->head; sp; sp = sp->next) { - sockname_len = sizeof(sockname_temp); - if (0 == getsockname(sp->socket->socket, - (struct sockaddr *)&sockname_temp, &sockname_len)) { - port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - if (port > 0) { - allocated_addr = malloc(addr_len); - memcpy(allocated_addr, addr, addr_len); - grpc_sockaddr_set_port(allocated_addr, port); - addr = allocated_addr; - break; - } - } - } - } - - if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { - addr = (const struct sockaddr *)&addr6_v4mapped; - addr_len = sizeof(addr6_v4mapped); - } - - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ - if (grpc_sockaddr_is_wildcard(addr, &port)) { - grpc_sockaddr_make_wildcard6(port, &wildcard); - - addr = (struct sockaddr *)&wildcard; - addr_len = sizeof(wildcard); - } - - sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, - WSA_FLAG_OVERLAPPED); - if (sock == INVALID_SOCKET) { - char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "unable to create socket: %s", utf8_message); - gpr_free(utf8_message); - } - - sp = add_socket_to_server(s, sock, addr, addr_len, port_index); - gpr_free(allocated_addr); - - if (sp) { - return sp->port; - } else { - return -1; - } -} - -unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, - unsigned port_index) { - grpc_tcp_listener *sp; - for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index) - ; - if (sp) { - return 1; - } else { - return 0; - } -} - -int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, - unsigned fd_index) { - grpc_tcp_listener *sp; - if (fd_index != 0) { - /* Windows implementation has only one fd per port_index. */ - return -1; - } - for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index) - ; - if (sp) { - return _open_osfhandle((intptr_t)sp->socket->socket, 0); - } else { - return -1; - } -} - -void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, - grpc_pollset **pollset, size_t pollset_count, - grpc_tcp_server_cb on_accept_cb, - void *on_accept_cb_arg) { - grpc_tcp_listener *sp; - GPR_ASSERT(on_accept_cb); - gpr_mu_lock(&s->mu); - GPR_ASSERT(!s->on_accept_cb); - GPR_ASSERT(s->active_ports == 0); - s->on_accept_cb = on_accept_cb; - s->on_accept_cb_arg = on_accept_cb_arg; - for (sp = s->head; sp; sp = sp->next) { - start_accept(exec_ctx, sp); - s->active_ports++; - } - gpr_mu_unlock(&s->mu); -} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c deleted file mode 100644 index 038e4158c8..0000000000 --- a/src/core/iomgr/tcp_windows.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINSOCK_SOCKET - -#include "src/core/iomgr/sockaddr_win32.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/log_win32.h> -#include <grpc/support/slice_buffer.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/timer.h" -#include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/sockaddr.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/socket_windows.h" -#include "src/core/iomgr/tcp_client.h" - -static int set_non_block(SOCKET sock) { - int status; - unsigned long param = 1; - DWORD ret; - status = - WSAIoctl(sock, FIONBIO, ¶m, sizeof(param), NULL, 0, &ret, NULL, NULL); - return status == 0; -} - -static int set_dualstack(SOCKET sock) { - int status; - unsigned long param = 0; - status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)¶m, - sizeof(param)); - return status == 0; -} - -int grpc_tcp_prepare_socket(SOCKET sock) { - if (!set_non_block(sock)) return 0; - if (!set_dualstack(sock)) return 0; - return 1; -} - -typedef struct grpc_tcp { - /* This is our C++ class derivation emulation. */ - grpc_endpoint base; - /* The one socket this endpoint is using. */ - grpc_winsocket *socket; - /* Refcounting how many operations are in progress. */ - gpr_refcount refcount; - - grpc_closure on_read; - grpc_closure on_write; - - grpc_closure *read_cb; - grpc_closure *write_cb; - gpr_slice read_slice; - gpr_slice_buffer *write_slices; - gpr_slice_buffer *read_slices; - - /* The IO Completion Port runs from another thread. We need some mechanism - to protect ourselves when requesting a shutdown. */ - gpr_mu mu; - int shutting_down; - - char *peer_string; -} grpc_tcp; - -static void tcp_free(grpc_tcp *tcp) { - grpc_winsocket_destroy(tcp->socket); - gpr_mu_destroy(&tcp->mu); - gpr_free(tcp->peer_string); - gpr_free(tcp); -} - -/*#define GRPC_TCP_REFCOUNT_DEBUG*/ -#ifdef GRPC_TCP_REFCOUNT_DEBUG -#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) -#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) -static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count - 1); - if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); - } -} - -static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count + 1); - gpr_ref(&tcp->refcount); -} -#else -#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) -#define TCP_REF(tcp, reason) tcp_ref((tcp)) -static void tcp_unref(grpc_tcp *tcp) { - if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); - } -} - -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } -#endif - -/* Asynchronous callback from the IOCP, or the background thread. */ -static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) { - grpc_tcp *tcp = tcpp; - grpc_closure *cb = tcp->read_cb; - grpc_winsocket *socket = tcp->socket; - gpr_slice sub; - grpc_winsocket_callback_info *info = &socket->read_info; - - if (success) { - if (socket->read_info.wsa_error != 0 && !tcp->shutting_down) { - if (socket->read_info.wsa_error != WSAECONNRESET) { - char *utf8_message = gpr_format_message(info->wsa_error); - gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); - gpr_free(utf8_message); - } - success = 0; - gpr_slice_unref(tcp->read_slice); - } else { - if (info->bytes_transfered != 0 && !tcp->shutting_down) { - sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - gpr_slice_buffer_add(tcp->read_slices, sub); - success = 1; - } else { - gpr_slice_unref(tcp->read_slice); - success = 0; - } - } - } - - tcp->read_cb = NULL; - TCP_UNREF(tcp, "read"); - if (cb) { - cb->cb(exec_ctx, cb->cb_arg, success); - } -} - -static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *read_slices, grpc_closure *cb) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_winsocket *handle = tcp->socket; - grpc_winsocket_callback_info *info = &handle->read_info; - int status; - DWORD bytes_read = 0; - DWORD flags = 0; - WSABUF buffer; - - if (tcp->shutting_down) { - grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL); - return; - } - - tcp->read_cb = cb; - tcp->read_slices = read_slices; - gpr_slice_buffer_reset_and_unref(read_slices); - - tcp->read_slice = gpr_slice_malloc(8192); - - buffer.len = (ULONG)GPR_SLICE_LENGTH( - tcp->read_slice); // we know slice size fits in 32bit. - buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice); - - TCP_REF(tcp, "read"); - - /* First let's try a synchronous, non-blocking read. */ - status = - WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL); - info->wsa_error = status == 0 ? 0 : WSAGetLastError(); - - /* Did we get data immediately ? Yay. */ - if (info->wsa_error != WSAEWOULDBLOCK) { - info->bytes_transfered = bytes_read; - grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, true, NULL); - return; - } - - /* Otherwise, let's retry, by queuing a read. */ - memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, - &info->overlapped, NULL); - - if (status != 0) { - int wsa_error = WSAGetLastError(); - if (wsa_error != WSA_IO_PENDING) { - info->wsa_error = wsa_error; - grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, false, NULL); - return; - } - } - - grpc_socket_notify_on_read(exec_ctx, tcp->socket, &tcp->on_read); -} - -/* Asynchronous callback from the IOCP, or the background thread. */ -static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) { - grpc_tcp *tcp = (grpc_tcp *)tcpp; - grpc_winsocket *handle = tcp->socket; - grpc_winsocket_callback_info *info = &handle->write_info; - grpc_closure *cb; - - gpr_mu_lock(&tcp->mu); - cb = tcp->write_cb; - tcp->write_cb = NULL; - gpr_mu_unlock(&tcp->mu); - - if (success) { - if (info->wsa_error != 0) { - if (info->wsa_error != WSAECONNRESET) { - char *utf8_message = gpr_format_message(info->wsa_error); - gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); - gpr_free(utf8_message); - } - success = 0; - } else { - GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); - } - } - - TCP_UNREF(tcp, "write"); - cb->cb(exec_ctx, cb->cb_arg, success); -} - -/* Initiates a write. */ -static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - gpr_slice_buffer *slices, grpc_closure *cb) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_winsocket *socket = tcp->socket; - grpc_winsocket_callback_info *info = &socket->write_info; - unsigned i; - DWORD bytes_sent; - int status; - WSABUF local_buffers[16]; - WSABUF *allocated = NULL; - WSABUF *buffers = local_buffers; - size_t len; - - if (tcp->shutting_down) { - grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL); - return; - } - - tcp->write_cb = cb; - tcp->write_slices = slices; - GPR_ASSERT(tcp->write_slices->count <= UINT_MAX); - if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { - buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); - allocated = buffers; - } - - for (i = 0; i < tcp->write_slices->count; i++) { - len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]); - GPR_ASSERT(len <= ULONG_MAX); - buffers[i].len = (ULONG)len; - buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]); - } - - /* First, let's try a synchronous, non-blocking write. */ - status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, - &bytes_sent, 0, NULL, NULL); - info->wsa_error = status == 0 ? 0 : WSAGetLastError(); - - /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy - connection that has its send queue filled up. But if we don't, then we can - avoid doing an async write operation at all. */ - if (info->wsa_error != WSAEWOULDBLOCK) { - bool ok = false; - if (status == 0) { - ok = true; - GPR_ASSERT(bytes_sent == tcp->write_slices->length); - } else { - if (socket->read_info.wsa_error != WSAECONNRESET) { - char *utf8_message = gpr_format_message(info->wsa_error); - gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message); - gpr_free(utf8_message); - } - } - if (allocated) gpr_free(allocated); - grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL); - return; - } - - TCP_REF(tcp, "write"); - - /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same - operation, this time asynchronously. */ - memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, - &bytes_sent, 0, &socket->write_info.overlapped, NULL); - if (allocated) gpr_free(allocated); - - if (status != 0) { - int wsa_error = WSAGetLastError(); - if (wsa_error != WSA_IO_PENDING) { - TCP_UNREF(tcp, "write"); - grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL); - return; - } - } - - /* As all is now setup, we can now ask for the IOCP notification. It may - trigger the callback immediately however, but no matter. */ - grpc_socket_notify_on_write(exec_ctx, socket, &tcp->on_write); -} - -static void win_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *ps) { - grpc_tcp *tcp; - (void)ps; - tcp = (grpc_tcp *)ep; - grpc_iocp_add_socket(tcp->socket); -} - -static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pss) { - grpc_tcp *tcp; - (void)pss; - tcp = (grpc_tcp *)ep; - grpc_iocp_add_socket(tcp->socket); -} - -/* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks - for the potential read and write operations. It is up to the caller to - guarantee this isn't called in parallel to a read or write request, so - we're not going to protect against these. However the IO Completion Port - callback will happen from another thread, so we need to protect against - concurrent access of the data structure in that regard. */ -static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - gpr_mu_lock(&tcp->mu); - /* At that point, what may happen is that we're already inside the IOCP - callback. See the comments in on_read and on_write. */ - tcp->shutting_down = 1; - grpc_winsocket_shutdown(tcp->socket); - gpr_mu_unlock(&tcp->mu); -} - -static void win_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - TCP_UNREF(tcp, "destroy"); -} - -static char *win_get_peer(grpc_endpoint *ep) { - grpc_tcp *tcp = (grpc_tcp *)ep; - return gpr_strdup(tcp->peer_string); -} - -static grpc_endpoint_vtable vtable = {win_read, win_write, win_add_to_pollset, - win_add_to_pollset_set, win_shutdown, - win_destroy, win_get_peer}; - -grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { - grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); - memset(tcp, 0, sizeof(grpc_tcp)); - tcp->base.vtable = &vtable; - tcp->socket = socket; - gpr_mu_init(&tcp->mu); - gpr_ref_init(&tcp->refcount, 1); - grpc_closure_init(&tcp->on_read, on_read, tcp); - grpc_closure_init(&tcp->on_write, on_write, tcp); - tcp->peer_string = gpr_strdup(peer_string); - return &tcp->base; -} - -#endif /* GPR_WINSOCK_SOCKET */ diff --git a/src/core/iomgr/tcp_windows.h b/src/core/iomgr/tcp_windows.h deleted file mode 100644 index deb3e48293..0000000000 --- a/src/core/iomgr/tcp_windows.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TCP_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_TCP_WINDOWS_H -/* - Low level TCP "bottom half" implementation, for use by transports built on - top of a TCP connection. - - Note that this file does not (yet) include APIs for creating the socket in - the first place. - - All calls passing slice transfer ownership of a slice refcount unless - otherwise specified. -*/ - -#include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/socket_windows.h" - -/* Create a tcp endpoint given a winsock handle. - * Takes ownership of the handle. - */ -grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string); - -int grpc_tcp_prepare_socket(SOCKET sock); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_WINDOWS_H */ diff --git a/src/core/iomgr/time_averaged_stats.c b/src/core/iomgr/time_averaged_stats.c deleted file mode 100644 index e075db4373..0000000000 --- a/src/core/iomgr/time_averaged_stats.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/time_averaged_stats.h" - -void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats, - double init_avg, double regress_weight, - double persistence_factor) { - stats->init_avg = init_avg; - stats->regress_weight = regress_weight; - stats->persistence_factor = persistence_factor; - stats->batch_total_value = 0; - stats->batch_num_samples = 0; - stats->aggregate_total_weight = 0; - stats->aggregate_weighted_avg = init_avg; -} - -void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats, - double value) { - stats->batch_total_value += value; - ++stats->batch_num_samples; -} - -double grpc_time_averaged_stats_update_average( - grpc_time_averaged_stats* stats) { - /* Start with the current batch: */ - double weighted_sum = stats->batch_total_value; - double total_weight = stats->batch_num_samples; - if (stats->regress_weight > 0) { - /* Add in the regression towards init_avg_: */ - weighted_sum += stats->regress_weight * stats->init_avg; - total_weight += stats->regress_weight; - } - if (stats->persistence_factor > 0) { - /* Add in the persistence: */ - const double prev_sample_weight = - stats->persistence_factor * stats->aggregate_total_weight; - weighted_sum += prev_sample_weight * stats->aggregate_weighted_avg; - total_weight += prev_sample_weight; - } - stats->aggregate_weighted_avg = - (total_weight > 0) ? (weighted_sum / total_weight) : stats->init_avg; - stats->aggregate_total_weight = total_weight; - stats->batch_num_samples = 0; - stats->batch_total_value = 0; - return stats->aggregate_weighted_avg; -} diff --git a/src/core/iomgr/time_averaged_stats.h b/src/core/iomgr/time_averaged_stats.h deleted file mode 100644 index 4e9e3956c2..0000000000 --- a/src/core/iomgr/time_averaged_stats.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TIME_AVERAGED_STATS_H -#define GRPC_INTERNAL_CORE_IOMGR_TIME_AVERAGED_STATS_H - -/* This tracks a time-decaying weighted average. It works by collecting - batches of samples and then mixing their average into a time-decaying - weighted mean. It is designed for batch operations where we do many adds - before updating the average. */ - -typedef struct { - /* The initial average value. This is the reported average until the first - grpc_time_averaged_stats_update_average call. If a positive regress_weight - is used, we also regress towards this value on each update. */ - double init_avg; - /* The sample weight of "init_avg" that is mixed in with each call to - grpc_time_averaged_stats_update_average. If the calls to - grpc_time_averaged_stats_add_sample stop, this will cause the average to - regress back to the mean. This should be non-negative. Set it to 0 to - disable the bias. A value of 1 has the effect of adding in 1 bonus sample - with value init_avg to each sample period. */ - double regress_weight; - /* This determines the rate of decay of the time-averaging from one period - to the next by scaling the aggregate_total_weight of samples from prior - periods when combining with the latest period. It should be in the range - [0,1]. A higher value adapts more slowly. With a value of 0.5, if the - batches each have k samples, the samples_in_avg_ will grow to 2 k, so the - weighting of the time average will eventually be 1/3 new batch and 2/3 - old average. */ - double persistence_factor; - - /* The total value of samples since the last UpdateAverage(). */ - double batch_total_value; - /* The number of samples since the last UpdateAverage(). */ - double batch_num_samples; - /* The time-decayed sum of batch_num_samples_ over previous batches. This is - the "weight" of the old aggregate_weighted_avg_ when updating the - average. */ - double aggregate_total_weight; - /* A time-decayed average of the (batch_total_value_ / batch_num_samples_), - computed by decaying the samples_in_avg_ weight in the weighted average. */ - double aggregate_weighted_avg; -} grpc_time_averaged_stats; - -/* See the comments on the members above for an explanation of init_avg, - regress_weight, and persistence_factor. */ -void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats, - double init_avg, double regress_weight, - double persistence_factor); -/* Add a sample to the current batch. */ -void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats, - double value); -/* Complete a batch and compute the new estimate of the average sample - value. */ -double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats* stats); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TIME_AVERAGED_STATS_H */ diff --git a/src/core/iomgr/timer.c b/src/core/iomgr/timer.c deleted file mode 100644 index f444643428..0000000000 --- a/src/core/iomgr/timer.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/timer.h" - -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpc/support/useful.h> -#include "src/core/iomgr/time_averaged_stats.h" -#include "src/core/iomgr/timer_heap.h" - -#define INVALID_HEAP_INDEX 0xffffffffu - -#define LOG2_NUM_SHARDS 5 -#define NUM_SHARDS (1 << LOG2_NUM_SHARDS) -#define ADD_DEADLINE_SCALE 0.33 -#define MIN_QUEUE_WINDOW_DURATION 0.01 -#define MAX_QUEUE_WINDOW_DURATION 1 - -typedef struct { - gpr_mu mu; - grpc_time_averaged_stats stats; - /* All and only timers with deadlines <= this will be in the heap. */ - gpr_timespec queue_deadline_cap; - gpr_timespec min_deadline; - /* Index in the g_shard_queue */ - uint32_t shard_queue_index; - /* This holds all timers with deadlines < queue_deadline_cap. Timers in this - list have the top bit of their deadline set to 0. */ - grpc_timer_heap heap; - /* This holds timers whose deadline is >= queue_deadline_cap. */ - grpc_timer list; -} shard_type; - -/* Protects g_shard_queue */ -static gpr_mu g_mu; -/* Allow only one run_some_expired_timers at once */ -static gpr_mu g_checker_mu; -static gpr_clock_type g_clock_type; -static shard_type g_shards[NUM_SHARDS]; -/* Protected by g_mu */ -static shard_type *g_shard_queue[NUM_SHARDS]; - -static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now, - gpr_timespec *next, int success); - -static gpr_timespec compute_min_deadline(shard_type *shard) { - return grpc_timer_heap_is_empty(&shard->heap) - ? shard->queue_deadline_cap - : grpc_timer_heap_top(&shard->heap)->deadline; -} - -void grpc_timer_list_init(gpr_timespec now) { - uint32_t i; - - gpr_mu_init(&g_mu); - gpr_mu_init(&g_checker_mu); - g_clock_type = now.clock_type; - - for (i = 0; i < NUM_SHARDS; i++) { - shard_type *shard = &g_shards[i]; - gpr_mu_init(&shard->mu); - grpc_time_averaged_stats_init(&shard->stats, 1.0 / ADD_DEADLINE_SCALE, 0.1, - 0.5); - shard->queue_deadline_cap = now; - shard->shard_queue_index = i; - grpc_timer_heap_init(&shard->heap); - shard->list.next = shard->list.prev = &shard->list; - shard->min_deadline = compute_min_deadline(shard); - g_shard_queue[i] = shard; - } -} - -void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) { - int i; - run_some_expired_timers(exec_ctx, gpr_inf_future(g_clock_type), NULL, 0); - for (i = 0; i < NUM_SHARDS; i++) { - shard_type *shard = &g_shards[i]; - gpr_mu_destroy(&shard->mu); - grpc_timer_heap_destroy(&shard->heap); - } - gpr_mu_destroy(&g_mu); - gpr_mu_destroy(&g_checker_mu); -} - -/* This is a cheap, but good enough, pointer hash for sharding the tasks: */ -static size_t shard_idx(const grpc_timer *info) { - size_t x = (size_t)info; - return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1); -} - -static double ts_to_dbl(gpr_timespec ts) { - return (double)ts.tv_sec + 1e-9 * ts.tv_nsec; -} - -static gpr_timespec dbl_to_ts(double d) { - gpr_timespec ts; - ts.tv_sec = (int64_t)d; - ts.tv_nsec = (int32_t)(1e9 * (d - (double)ts.tv_sec)); - ts.clock_type = GPR_TIMESPAN; - return ts; -} - -static void list_join(grpc_timer *head, grpc_timer *timer) { - timer->next = head; - timer->prev = head->prev; - timer->next->prev = timer->prev->next = timer; -} - -static void list_remove(grpc_timer *timer) { - timer->next->prev = timer->prev; - timer->prev->next = timer->next; -} - -static void swap_adjacent_shards_in_queue(uint32_t first_shard_queue_index) { - shard_type *temp; - temp = g_shard_queue[first_shard_queue_index]; - g_shard_queue[first_shard_queue_index] = - g_shard_queue[first_shard_queue_index + 1]; - g_shard_queue[first_shard_queue_index + 1] = temp; - g_shard_queue[first_shard_queue_index]->shard_queue_index = - first_shard_queue_index; - g_shard_queue[first_shard_queue_index + 1]->shard_queue_index = - first_shard_queue_index + 1; -} - -static void note_deadline_change(shard_type *shard) { - while (shard->shard_queue_index > 0 && - gpr_time_cmp( - shard->min_deadline, - g_shard_queue[shard->shard_queue_index - 1]->min_deadline) < 0) { - swap_adjacent_shards_in_queue(shard->shard_queue_index - 1); - } - while (shard->shard_queue_index < NUM_SHARDS - 1 && - gpr_time_cmp( - shard->min_deadline, - g_shard_queue[shard->shard_queue_index + 1]->min_deadline) > 0) { - swap_adjacent_shards_in_queue(shard->shard_queue_index); - } -} - -void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, - gpr_timespec deadline, grpc_iomgr_cb_func timer_cb, - void *timer_cb_arg, gpr_timespec now) { - int is_first_timer = 0; - shard_type *shard = &g_shards[shard_idx(timer)]; - GPR_ASSERT(deadline.clock_type == g_clock_type); - GPR_ASSERT(now.clock_type == g_clock_type); - grpc_closure_init(&timer->closure, timer_cb, timer_cb_arg); - timer->deadline = deadline; - timer->triggered = 0; - - /* TODO(ctiller): check deadline expired */ - - gpr_mu_lock(&shard->mu); - grpc_time_averaged_stats_add_sample(&shard->stats, - ts_to_dbl(gpr_time_sub(deadline, now))); - if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) { - is_first_timer = grpc_timer_heap_add(&shard->heap, timer); - } else { - timer->heap_index = INVALID_HEAP_INDEX; - list_join(&shard->list, timer); - } - gpr_mu_unlock(&shard->mu); - - /* Deadline may have decreased, we need to adjust the master queue. Note - that there is a potential racy unlocked region here. There could be a - reordering of multiple grpc_timer_init calls, at this point, but the < test - below should ensure that we err on the side of caution. There could - also be a race with grpc_timer_check, which might beat us to the lock. In - that case, it is possible that the timer that we added will have already - run by the time we hold the lock, but that too is a safe error. - Finally, it's possible that the grpc_timer_check that intervened failed to - trigger the new timer because the min_deadline hadn't yet been reduced. - In that case, the timer will simply have to wait for the next - grpc_timer_check. */ - if (is_first_timer) { - gpr_mu_lock(&g_mu); - if (gpr_time_cmp(deadline, shard->min_deadline) < 0) { - gpr_timespec old_min_deadline = g_shard_queue[0]->min_deadline; - shard->min_deadline = deadline; - note_deadline_change(shard); - if (shard->shard_queue_index == 0 && - gpr_time_cmp(deadline, old_min_deadline) < 0) { - grpc_kick_poller(); - } - } - gpr_mu_unlock(&g_mu); - } -} - -void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { - shard_type *shard = &g_shards[shard_idx(timer)]; - gpr_mu_lock(&shard->mu); - if (!timer->triggered) { - grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL); - timer->triggered = 1; - if (timer->heap_index == INVALID_HEAP_INDEX) { - list_remove(timer); - } else { - grpc_timer_heap_remove(&shard->heap, timer); - } - } - gpr_mu_unlock(&shard->mu); -} - -/* This is called when the queue is empty and "now" has reached the - queue_deadline_cap. We compute a new queue deadline and then scan the map - for timers that fall at or under it. Returns true if the queue is no - longer empty. - REQUIRES: shard->mu locked */ -static int refill_queue(shard_type *shard, gpr_timespec now) { - /* Compute the new queue window width and bound by the limits: */ - double computed_deadline_delta = - grpc_time_averaged_stats_update_average(&shard->stats) * - ADD_DEADLINE_SCALE; - double deadline_delta = - GPR_CLAMP(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION, - MAX_QUEUE_WINDOW_DURATION); - grpc_timer *timer, *next; - - /* Compute the new cap and put all timers under it into the queue: */ - shard->queue_deadline_cap = gpr_time_add( - gpr_time_max(now, shard->queue_deadline_cap), dbl_to_ts(deadline_delta)); - for (timer = shard->list.next; timer != &shard->list; timer = next) { - next = timer->next; - - if (gpr_time_cmp(timer->deadline, shard->queue_deadline_cap) < 0) { - list_remove(timer); - grpc_timer_heap_add(&shard->heap, timer); - } - } - return !grpc_timer_heap_is_empty(&shard->heap); -} - -/* This pops the next non-cancelled timer with deadline <= now from the queue, - or returns NULL if there isn't one. - REQUIRES: shard->mu locked */ -static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) { - grpc_timer *timer; - for (;;) { - if (grpc_timer_heap_is_empty(&shard->heap)) { - if (gpr_time_cmp(now, shard->queue_deadline_cap) < 0) return NULL; - if (!refill_queue(shard, now)) return NULL; - } - timer = grpc_timer_heap_top(&shard->heap); - if (gpr_time_cmp(timer->deadline, now) > 0) return NULL; - timer->triggered = 1; - grpc_timer_heap_pop(&shard->heap); - return timer; - } -} - -/* REQUIRES: shard->mu unlocked */ -static size_t pop_timers(grpc_exec_ctx *exec_ctx, shard_type *shard, - gpr_timespec now, gpr_timespec *new_min_deadline, - int success) { - size_t n = 0; - grpc_timer *timer; - gpr_mu_lock(&shard->mu); - while ((timer = pop_one(shard, now))) { - grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, success, NULL); - n++; - } - *new_min_deadline = compute_min_deadline(shard); - gpr_mu_unlock(&shard->mu); - return n; -} - -static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now, - gpr_timespec *next, int success) { - size_t n = 0; - - /* TODO(ctiller): verify that there are any timers (atomically) here */ - - if (gpr_mu_trylock(&g_checker_mu)) { - gpr_mu_lock(&g_mu); - - while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) { - gpr_timespec new_min_deadline; - - /* For efficiency, we pop as many available timers as we can from the - shard. This may violate perfect timer deadline ordering, but that - shouldn't be a big deal because we don't make ordering guarantees. */ - n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline, - success); - - /* An grpc_timer_init() on the shard could intervene here, adding a new - timer that is earlier than new_min_deadline. However, - grpc_timer_init() will block on the master_lock before it can call - set_min_deadline, so this one will complete first and then the Addtimer - will reduce the min_deadline (perhaps unnecessarily). */ - g_shard_queue[0]->min_deadline = new_min_deadline; - note_deadline_change(g_shard_queue[0]); - } - - if (next) { - *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline); - } - - gpr_mu_unlock(&g_mu); - gpr_mu_unlock(&g_checker_mu); - } else if (next != NULL) { - /* TODO(ctiller): this forces calling code to do an short poll, and - then retry the timer check (because this time through the timer list was - contended). - - We could reduce the cost here dramatically by keeping a count of how many - currently active pollers got through the uncontended case above - successfully, and waking up other pollers IFF that count drops to zero. - - Once that count is in place, this entire else branch could disappear. */ - *next = gpr_time_min( - *next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN))); - } - - return (int)n; -} - -bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, - gpr_timespec *next) { - GPR_ASSERT(now.clock_type == g_clock_type); - return run_some_expired_timers( - exec_ctx, now, next, - gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0); -} diff --git a/src/core/iomgr/timer.h b/src/core/iomgr/timer.h deleted file mode 100644 index e239e884e7..0000000000 --- a/src/core/iomgr/timer.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TIMER_H -#define GRPC_INTERNAL_CORE_IOMGR_TIMER_H - -#include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/exec_ctx.h" -#include <grpc/support/port_platform.h> -#include <grpc/support/time.h> - -typedef struct grpc_timer { - gpr_timespec deadline; - uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */ - int triggered; - struct grpc_timer *next; - struct grpc_timer *prev; - grpc_closure closure; -} grpc_timer; - -/* Initialize *timer. When expired or canceled, timer_cb will be called with - *timer_cb_arg and status to indicate if it expired (SUCCESS) or was - canceled (CANCELLED). timer_cb is guaranteed to be called exactly once, - and application code should check the status to determine how it was - invoked. The application callback is also responsible for maintaining - information about when to free up any user-level state. */ -void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, - gpr_timespec deadline, grpc_iomgr_cb_func timer_cb, - void *timer_cb_arg, gpr_timespec now); - -/* Note that there is no timer destroy function. This is because the - timer is a one-time occurrence with a guarantee that the callback will - be called exactly once, either at expiration or cancellation. Thus, all - the internal timer event management state is destroyed just before - that callback is invoked. If the user has additional state associated with - the timer, the user is responsible for determining when it is safe to - destroy that state. */ - -/* Cancel an *timer. - There are three cases: - 1. We normally cancel the timer - 2. The timer has already run - 3. We can't cancel the timer because it is "in flight". - - In all of these cases, the cancellation is still considered successful. - They are essentially distinguished in that the timer_cb will be run - exactly once from either the cancellation (with status CANCELLED) - or from the activation (with status SUCCESS) - - Note carefully that the callback function MAY occur in the same callstack - as grpc_timer_cancel. It's expected that most timers will be cancelled (their - primary use is to implement deadlines), and so this code is optimized such - that cancellation costs as little as possible. Making callbacks run inline - matches this aim. - - Requires: cancel() must happen after add() on a given timer */ -void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer); - -/* iomgr internal api for dealing with timers */ - -/* Check for timers to be run, and run them. - Return true if timer callbacks were executed. - Drops drop_mu if it is non-null before executing callbacks. - If next is non-null, TRY to update *next with the next running timer - IF that timer occurs before *next current value. - *next is never guaranteed to be updated on any given execution; however, - with high probability at least one thread in the system will see an update - at any time slice. */ -bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, - gpr_timespec *next); -void grpc_timer_list_init(gpr_timespec now); -void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx); - -/* the following must be implemented by each iomgr implementation */ - -void grpc_kick_poller(void); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TIMER_H */ diff --git a/src/core/iomgr/timer_heap.c b/src/core/iomgr/timer_heap.c deleted file mode 100644 index b5df566c45..0000000000 --- a/src/core/iomgr/timer_heap.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/timer_heap.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/useful.h> - -/* Adjusts a heap so as to move a hole at position i closer to the root, - until a suitable position is found for element t. Then, copies t into that - position. This functor is called each time immediately after modifying a - value in the underlying container, with the offset of the modified element as - its argument. */ -static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) { - while (i > 0) { - uint32_t parent = (uint32_t)(((int)i - 1) / 2); - if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break; - first[i] = first[parent]; - first[i]->heap_index = i; - i = parent; - } - first[i] = t; - t->heap_index = i; -} - -/* Adjusts a heap so as to move a hole at position i farther away from the root, - until a suitable position is found for element t. Then, copies t into that - position. */ -static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length, - grpc_timer *t) { - for (;;) { - uint32_t left_child = 1u + 2u * i; - if (left_child >= length) break; - uint32_t right_child = left_child + 1; - uint32_t next_i = right_child < length && - gpr_time_cmp(first[left_child]->deadline, - first[right_child]->deadline) > 0 - ? right_child - : left_child; - if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break; - first[i] = first[next_i]; - first[i]->heap_index = i; - i = next_i; - } - first[i] = t; - t->heap_index = i; -} - -#define SHRINK_MIN_ELEMS 8 -#define SHRINK_FULLNESS_FACTOR 2 - -static void maybe_shrink(grpc_timer_heap *heap) { - if (heap->timer_count >= 8 && - heap->timer_count <= heap->timer_capacity / SHRINK_FULLNESS_FACTOR / 2) { - heap->timer_capacity = heap->timer_count * SHRINK_FULLNESS_FACTOR; - heap->timers = - gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *)); - } -} - -static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) { - uint32_t i = timer->heap_index; - uint32_t parent = (uint32_t)(((int)i - 1) / 2); - if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) { - adjust_upwards(heap->timers, i, timer); - } else { - adjust_downwards(heap->timers, i, heap->timer_count, timer); - } -} - -void grpc_timer_heap_init(grpc_timer_heap *heap) { - memset(heap, 0, sizeof(*heap)); -} - -void grpc_timer_heap_destroy(grpc_timer_heap *heap) { gpr_free(heap->timers); } - -int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer) { - if (heap->timer_count == heap->timer_capacity) { - heap->timer_capacity = - GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2); - heap->timers = - gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *)); - } - timer->heap_index = heap->timer_count; - adjust_upwards(heap->timers, heap->timer_count, timer); - heap->timer_count++; - return timer->heap_index == 0; -} - -void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer) { - uint32_t i = timer->heap_index; - if (i == heap->timer_count - 1) { - heap->timer_count--; - maybe_shrink(heap); - return; - } - heap->timers[i] = heap->timers[heap->timer_count - 1]; - heap->timers[i]->heap_index = i; - heap->timer_count--; - maybe_shrink(heap); - note_changed_priority(heap, heap->timers[i]); -} - -int grpc_timer_heap_is_empty(grpc_timer_heap *heap) { - return heap->timer_count == 0; -} - -grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap) { - return heap->timers[0]; -} - -void grpc_timer_heap_pop(grpc_timer_heap *heap) { - grpc_timer_heap_remove(heap, grpc_timer_heap_top(heap)); -} diff --git a/src/core/iomgr/timer_heap.h b/src/core/iomgr/timer_heap.h deleted file mode 100644 index 2d220f1677..0000000000 --- a/src/core/iomgr/timer_heap.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_TIMER_HEAP_H -#define GRPC_INTERNAL_CORE_IOMGR_TIMER_HEAP_H - -#include "src/core/iomgr/timer.h" - -typedef struct { - grpc_timer **timers; - uint32_t timer_count; - uint32_t timer_capacity; -} grpc_timer_heap; - -/* return 1 if the new timer is the first timer in the heap */ -int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer); - -void grpc_timer_heap_init(grpc_timer_heap *heap); -void grpc_timer_heap_destroy(grpc_timer_heap *heap); - -void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer); -grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap); -void grpc_timer_heap_pop(grpc_timer_heap *heap); - -int grpc_timer_heap_is_empty(grpc_timer_heap *heap); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_TIMER_HEAP_H */ diff --git a/src/core/iomgr/udp_server.c b/src/core/iomgr/udp_server.c deleted file mode 100644 index ef548cfe4d..0000000000 --- a/src/core/iomgr/udp_server.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <grpc/support/port_platform.h> - -#ifdef GRPC_NEED_UDP -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/udp_server.h" - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/un.h> -#include <unistd.h> - -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/pollset_posix.h" -#include "src/core/iomgr/resolve_address.h" -#include "src/core/iomgr/sockaddr_utils.h" -#include "src/core/iomgr/socket_utils_posix.h" -#include "src/core/support/string.h" -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/sync.h> -#include <grpc/support/string_util.h> -#include <grpc/support/time.h> - -#define INIT_PORT_CAP 2 - -/* one listening port */ -typedef struct { - int fd; - grpc_fd *emfd; - grpc_udp_server *server; - union { - uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE]; - struct sockaddr sockaddr; - struct sockaddr_un un; - } addr; - size_t addr_len; - grpc_closure read_closure; - grpc_closure destroyed_closure; - grpc_udp_server_read_cb read_cb; -} server_port; - -static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) { - struct stat st; - - if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) { - unlink(un->sun_path); - } -} - -/* the overall server */ -struct grpc_udp_server { - gpr_mu mu; - gpr_cv cv; - - /* active port count: how many ports are actually still listening */ - size_t active_ports; - /* destroyed port count: how many ports are completely destroyed */ - size_t destroyed_ports; - - /* is this server shutting down? (boolean) */ - int shutdown; - - /* all listening ports */ - server_port *ports; - size_t nports; - size_t port_capacity; - - /* shutdown callback */ - grpc_closure *shutdown_complete; - - /* all pollsets interested in new connections */ - grpc_pollset **pollsets; - /* number of pollsets in the pollsets array */ - size_t pollset_count; - /* The parent grpc server */ - grpc_server *grpc_server; -}; - -grpc_udp_server *grpc_udp_server_create(void) { - grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server)); - gpr_mu_init(&s->mu); - gpr_cv_init(&s->cv); - s->active_ports = 0; - s->destroyed_ports = 0; - s->shutdown = 0; - s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); - s->nports = 0; - s->port_capacity = INIT_PORT_CAP; - - return s; -} - -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL); - - gpr_mu_destroy(&s->mu); - gpr_cv_destroy(&s->cv); - - gpr_free(s->ports); - gpr_free(s); -} - -static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, - bool success) { - grpc_udp_server *s = server; - gpr_mu_lock(&s->mu); - s->destroyed_ports++; - if (s->destroyed_ports == s->nports) { - gpr_mu_unlock(&s->mu); - finish_shutdown(exec_ctx, s); - } else { - gpr_mu_unlock(&s->mu); - } -} - -/* called when all listening endpoints have been shutdown, so no further - events will be received on them - at this point it's safe to destroy - things */ -static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { - size_t i; - - /* delete ALL the things */ - gpr_mu_lock(&s->mu); - - if (!s->shutdown) { - gpr_mu_unlock(&s->mu); - return; - } - - if (s->nports) { - for (i = 0; i < s->nports; i++) { - server_port *sp = &s->ports[i]; - if (sp->addr.sockaddr.sa_family == AF_UNIX) { - unlink_if_unix_domain_socket(&sp->addr.un); - } - sp->destroyed_closure.cb = destroyed_port; - sp->destroyed_closure.cb_arg = s; - grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, - "udp_listener_shutdown"); - } - gpr_mu_unlock(&s->mu); - } else { - gpr_mu_unlock(&s->mu); - finish_shutdown(exec_ctx, s); - } -} - -void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, - grpc_closure *on_done) { - size_t i; - gpr_mu_lock(&s->mu); - - GPR_ASSERT(!s->shutdown); - s->shutdown = 1; - - s->shutdown_complete = on_done; - - /* shutdown all fd's */ - if (s->active_ports) { - for (i = 0; i < s->nports; i++) { - grpc_fd_shutdown(exec_ctx, s->ports[i].emfd); - } - gpr_mu_unlock(&s->mu); - } else { - gpr_mu_unlock(&s->mu); - deactivated_all_ports(exec_ctx, s); - } -} - -/* Prepare a recently-created socket for listening. */ -static int prepare_socket(int fd, const struct sockaddr *addr, - size_t addr_len) { - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - int get_local_ip; - int rc; - - if (fd < 0) { - goto error; - } - - if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) { - gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd, - strerror(errno)); - } - - get_local_ip = 1; - rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, - sizeof(get_local_ip)); - if (rc == 0 && addr->sa_family == AF_INET6) { -#if !defined(__APPLE__) - rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, - sizeof(get_local_ip)); -#endif - } - - GPR_ASSERT(addr_len < ~(socklen_t)0); - if (bind(fd, addr, (socklen_t)addr_len) < 0) { - char *addr_str; - grpc_sockaddr_to_string(&addr_str, addr, 0); - gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno)); - gpr_free(addr_str); - goto error; - } - - sockname_len = sizeof(sockname_temp); - if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) { - goto error; - } - - return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - -error: - if (fd >= 0) { - close(fd); - } - return -1; -} - -/* event manager callback when reads are ready */ -static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - server_port *sp = arg; - - if (!success) { - gpr_mu_lock(&sp->server->mu); - if (0 == --sp->server->active_ports) { - gpr_mu_unlock(&sp->server->mu); - deactivated_all_ports(exec_ctx, sp->server); - } else { - gpr_mu_unlock(&sp->server->mu); - } - return; - } - - /* Tell the registered callback that data is available to read. */ - GPR_ASSERT(sp->read_cb); - sp->read_cb(exec_ctx, sp->emfd, sp->server->grpc_server); - - /* Re-arm the notification event so we get another chance to read. */ - grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); -} - -static int add_socket_to_server(grpc_udp_server *s, int fd, - const struct sockaddr *addr, size_t addr_len, - grpc_udp_server_read_cb read_cb) { - server_port *sp; - int port; - char *addr_str; - char *name; - - port = prepare_socket(fd, addr, addr_len); - if (port >= 0) { - grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); - gpr_asprintf(&name, "udp-server-listener:%s", addr_str); - gpr_free(addr_str); - gpr_mu_lock(&s->mu); - /* append it to the list under a lock */ - if (s->nports == s->port_capacity) { - s->port_capacity *= 2; - s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity); - } - sp = &s->ports[s->nports++]; - sp->server = s; - sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); - memcpy(sp->addr.untyped, addr, addr_len); - sp->addr_len = addr_len; - sp->read_cb = read_cb; - GPR_ASSERT(sp->emfd); - gpr_mu_unlock(&s->mu); - gpr_free(name); - } - - return port; -} - -int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, - size_t addr_len, grpc_udp_server_read_cb read_cb) { - int allocated_port1 = -1; - int allocated_port2 = -1; - unsigned i; - int fd; - grpc_dualstack_mode dsmode; - struct sockaddr_in6 addr6_v4mapped; - struct sockaddr_in wild4; - struct sockaddr_in6 wild6; - struct sockaddr_in addr4_copy; - struct sockaddr *allocated_addr = NULL; - struct sockaddr_storage sockname_temp; - socklen_t sockname_len; - int port; - - if (((struct sockaddr *)addr)->sa_family == AF_UNIX) { - unlink_if_unix_domain_socket(addr); - } - - /* Check if this is a wildcard port, and if so, try to keep the port the same - as some previously created listener. */ - if (grpc_sockaddr_get_port(addr) == 0) { - for (i = 0; i < s->nports; i++) { - sockname_len = sizeof(sockname_temp); - if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp, - &sockname_len)) { - port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp); - if (port > 0) { - allocated_addr = malloc(addr_len); - memcpy(allocated_addr, addr, addr_len); - grpc_sockaddr_set_port(allocated_addr, port); - addr = allocated_addr; - break; - } - } - } - } - - if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { - addr = (const struct sockaddr *)&addr6_v4mapped; - addr_len = sizeof(addr6_v4mapped); - } - - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ - if (grpc_sockaddr_is_wildcard(addr, &port)) { - grpc_sockaddr_make_wildcards(port, &wild4, &wild6); - - /* Try listening on IPv6 first. */ - addr = (struct sockaddr *)&wild6; - addr_len = sizeof(wild6); - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); - allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb); - if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { - goto done; - } - - /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */ - if (port == 0 && allocated_port1 > 0) { - grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1); - } - addr = (struct sockaddr *)&wild4; - addr_len = sizeof(wild4); - } - - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); - if (fd < 0) { - gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); - } - if (dsmode == GRPC_DSMODE_IPV4 && - grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { - addr = (struct sockaddr *)&addr4_copy; - addr_len = sizeof(addr4_copy); - } - allocated_port2 = add_socket_to_server(s, fd, addr, addr_len, read_cb); - -done: - gpr_free(allocated_addr); - return allocated_port1 >= 0 ? allocated_port1 : allocated_port2; -} - -int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) { - return (port_index < s->nports) ? s->ports[port_index].fd : -1; -} - -void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, - grpc_pollset **pollsets, size_t pollset_count, - grpc_server *server) { - size_t i, j; - gpr_mu_lock(&s->mu); - GPR_ASSERT(s->active_ports == 0); - s->pollsets = pollsets; - s->grpc_server = server; - for (i = 0; i < s->nports; i++) { - for (j = 0; j < pollset_count; j++) { - grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd); - } - s->ports[i].read_closure.cb = on_read; - s->ports[i].read_closure.cb_arg = &s->ports[i]; - grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd, - &s->ports[i].read_closure); - s->active_ports++; - } - gpr_mu_unlock(&s->mu); -} - -#endif -#endif diff --git a/src/core/iomgr/udp_server.h b/src/core/iomgr/udp_server.h deleted file mode 100644 index a9d0489edf..0000000000 --- a/src/core/iomgr/udp_server.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_UDP_SERVER_H -#define GRPC_INTERNAL_CORE_IOMGR_UDP_SERVER_H - -#include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/fd_posix.h" - -/* Forward decl of grpc_server */ -typedef struct grpc_server grpc_server; - -/* Forward decl of grpc_udp_server */ -typedef struct grpc_udp_server grpc_udp_server; - -/* Called when data is available to read from the socket. */ -typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, - grpc_server *server); - -/* Create a server, initially not bound to any ports */ -grpc_udp_server *grpc_udp_server_create(void); - -/* Start listening to bound ports */ -void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server, - grpc_pollset **pollsets, size_t pollset_count, - grpc_server *server); - -int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index); - -/* Add a port to the server, returning port number on success, or negative - on failure. - - The :: and 0.0.0.0 wildcard addresses are treated identically, accepting - both IPv4 and IPv6 connections, but :: is the preferred style. This usually - creates one socket, but possibly two on systems which support IPv6, - but not dualstack sockets. */ - -/* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle - all of the multiple socket port matching logic in one place */ -int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, - size_t addr_len, grpc_udp_server_read_cb read_cb); - -void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server, - grpc_closure *on_done); - -#endif /* GRPC_INTERNAL_CORE_IOMGR_UDP_SERVER_H */ diff --git a/src/core/iomgr/wakeup_fd_eventfd.c b/src/core/iomgr/wakeup_fd_eventfd.c deleted file mode 100644 index f67379e4fc..0000000000 --- a/src/core/iomgr/wakeup_fd_eventfd.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_LINUX_EVENTFD - -#include <errno.h> -#include <sys/eventfd.h> -#include <unistd.h> - -#include <grpc/support/log.h> - -#include "src/core/iomgr/wakeup_fd_posix.h" -#include "src/core/profiling/timers.h" - -static void eventfd_create(grpc_wakeup_fd* fd_info) { - int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - /* TODO(klempner): Handle failure more gracefully */ - GPR_ASSERT(efd >= 0); - fd_info->read_fd = efd; - fd_info->write_fd = -1; -} - -static void eventfd_consume(grpc_wakeup_fd* fd_info) { - eventfd_t value; - int err; - do { - err = eventfd_read(fd_info->read_fd, &value); - } while (err < 0 && errno == EINTR); -} - -static void eventfd_wakeup(grpc_wakeup_fd* fd_info) { - int err; - GPR_TIMER_BEGIN("eventfd_wakeup", 0); - do { - err = eventfd_write(fd_info->read_fd, 1); - } while (err < 0 && errno == EINTR); - GPR_TIMER_END("eventfd_wakeup", 0); -} - -static void eventfd_destroy(grpc_wakeup_fd* fd_info) { - if (fd_info->read_fd != 0) close(fd_info->read_fd); -} - -static int eventfd_check_availability(void) { - /* TODO(klempner): Actually check if eventfd is available */ - return 1; -} - -const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = { - eventfd_create, eventfd_consume, eventfd_wakeup, eventfd_destroy, - eventfd_check_availability}; - -#endif /* GPR_LINUX_EVENTFD */ diff --git a/src/core/iomgr/wakeup_fd_nospecial.c b/src/core/iomgr/wakeup_fd_nospecial.c deleted file mode 100644 index 78d763c103..0000000000 --- a/src/core/iomgr/wakeup_fd_nospecial.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* - * This is a dummy file to provide an invalid specialized_wakeup_fd_vtable on - * systems without anything better than pipe. - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_NO_SPECIAL_WAKEUP_FD - -#include "src/core/iomgr/wakeup_fd_posix.h" -#include <stddef.h> - -static int check_availability_invalid(void) { return 0; } - -const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = { - NULL, NULL, NULL, NULL, check_availability_invalid}; - -#endif /* GPR_POSIX_NO_SPECIAL_WAKEUP_FD */ diff --git a/src/core/iomgr/wakeup_fd_pipe.c b/src/core/iomgr/wakeup_fd_pipe.c deleted file mode 100644 index 80de181d9d..0000000000 --- a/src/core/iomgr/wakeup_fd_pipe.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_WAKEUP_FD - -#include "src/core/iomgr/wakeup_fd_posix.h" - -#include <errno.h> -#include <string.h> -#include <unistd.h> - -#include "src/core/iomgr/socket_utils_posix.h" -#include <grpc/support/log.h> - -static void pipe_init(grpc_wakeup_fd* fd_info) { - int pipefd[2]; - /* TODO(klempner): Make this nonfatal */ - GPR_ASSERT(0 == pipe(pipefd)); - GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1)); - GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1)); - fd_info->read_fd = pipefd[0]; - fd_info->write_fd = pipefd[1]; -} - -static void pipe_consume(grpc_wakeup_fd* fd_info) { - char buf[128]; - ssize_t r; - - for (;;) { - r = read(fd_info->read_fd, buf, sizeof(buf)); - if (r > 0) continue; - if (r == 0) return; - switch (errno) { - case EAGAIN: - return; - case EINTR: - continue; - default: - gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno)); - return; - } - } -} - -static void pipe_wakeup(grpc_wakeup_fd* fd_info) { - char c = 0; - while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR) - ; -} - -static void pipe_destroy(grpc_wakeup_fd* fd_info) { - if (fd_info->read_fd != 0) close(fd_info->read_fd); - if (fd_info->write_fd != 0) close(fd_info->write_fd); -} - -static int pipe_check_availability(void) { - /* Assume that pipes are always available. */ - return 1; -} - -const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = { - pipe_init, pipe_consume, pipe_wakeup, pipe_destroy, - pipe_check_availability}; - -#endif /* GPR_POSIX_WAKUP_FD */ diff --git a/src/core/iomgr/wakeup_fd_pipe.h b/src/core/iomgr/wakeup_fd_pipe.h deleted file mode 100644 index 01a13a97c0..0000000000 --- a/src/core/iomgr/wakeup_fd_pipe.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_PIPE_H -#define GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_PIPE_H - -#include "src/core/iomgr/wakeup_fd_posix.h" - -extern grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_PIPE_H */ diff --git a/src/core/iomgr/wakeup_fd_posix.c b/src/core/iomgr/wakeup_fd_posix.c deleted file mode 100644 index f40be081b0..0000000000 --- a/src/core/iomgr/wakeup_fd_posix.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_WAKEUP_FD - -#include "src/core/iomgr/wakeup_fd_posix.h" -#include "src/core/iomgr/wakeup_fd_pipe.h" -#include <stddef.h> - -static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; -int grpc_allow_specialized_wakeup_fd = 1; - -void grpc_wakeup_fd_global_init(void) { - if (grpc_allow_specialized_wakeup_fd && - grpc_specialized_wakeup_fd_vtable.check_availability()) { - wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable; - } else { - wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; - } -} - -void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } - -void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { - wakeup_fd_vtable->init(fd_info); -} - -void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) { - wakeup_fd_vtable->consume(fd_info); -} - -void grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) { - wakeup_fd_vtable->wakeup(fd_info); -} - -void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) { - wakeup_fd_vtable->destroy(fd_info); -} - -#endif /* GPR_POSIX_WAKEUP_FD */ diff --git a/src/core/iomgr/wakeup_fd_posix.h b/src/core/iomgr/wakeup_fd_posix.h deleted file mode 100644 index ffd60d1d4e..0000000000 --- a/src/core/iomgr/wakeup_fd_posix.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* - * wakeup_fd abstracts the concept of a file descriptor for the purpose of - * waking up a thread in select()/poll()/epoll_wait()/etc. - - * The poll() family of system calls provide a way for a thread to block until - * there is activity on one (or more) of a set of file descriptors. An - * application may wish to wake up this thread to do non file related work. The - * typical way to do this is to add a pipe to the set of file descriptors, then - * write to the pipe to wake up the thread in poll(). - * - * Linux has a lighter weight eventfd specifically designed for this purpose. - * wakeup_fd abstracts the difference between the two. - * - * Setup: - * 1. Before calling anything, call global_init() at least once. - * 1. Call grpc_wakeup_fd_create() to get a wakeup_fd. - * 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file - * descriptors for the poll() style API you are using. Monitor the file - * descriptor for readability. - * 3. To tear down, call grpc_wakeup_fd_destroy(). This closes the underlying - * file descriptor. - * - * Usage: - * 1. To wake up a polling thread, call grpc_wakeup_fd_wakeup() on a wakeup_fd - * it is monitoring. - * 2. If the polling thread was awakened by a wakeup_fd event, call - * grpc_wakeup_fd_consume_wakeup() on it. - */ -#ifndef GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_POSIX_H - -void grpc_wakeup_fd_global_init(void); -void grpc_wakeup_fd_global_destroy(void); - -/* Force using the fallback implementation. This is intended for testing - * purposes only.*/ -void grpc_wakeup_fd_global_init_force_fallback(void); - -typedef struct grpc_wakeup_fd grpc_wakeup_fd; - -typedef struct grpc_wakeup_fd_vtable { - void (*init)(grpc_wakeup_fd* fd_info); - void (*consume)(grpc_wakeup_fd* fd_info); - void (*wakeup)(grpc_wakeup_fd* fd_info); - void (*destroy)(grpc_wakeup_fd* fd_info); - /* Must be called before calling any other functions */ - int (*check_availability)(void); -} grpc_wakeup_fd_vtable; - -struct grpc_wakeup_fd { - int read_fd; - int write_fd; -}; - -extern int grpc_allow_specialized_wakeup_fd; - -#define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) - -void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info); -void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info); -void grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info); -void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info); - -/* Defined in some specialized implementation's .c file, or by - * wakeup_fd_nospecial.c if no such implementation exists. */ -extern const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_WAKEUP_FD_POSIX_H */ diff --git a/src/core/iomgr/workqueue.h b/src/core/iomgr/workqueue.h deleted file mode 100644 index 36dd133468..0000000000 --- a/src/core/iomgr/workqueue.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_H -#define GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_H - -#include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/pollset.h" -#include "src/core/iomgr/closure.h" -#include "src/core/iomgr/exec_ctx.h" - -#ifdef GPR_POSIX_SOCKET -#include "src/core/iomgr/workqueue_posix.h" -#endif - -#ifdef GPR_WIN32 -#include "src/core/iomgr/workqueue_windows.h" -#endif - -/* grpc_workqueue is forward declared in exec_ctx.h */ - -/** Create a work queue */ -grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx); - -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); - -#define GRPC_WORKQUEUE_REFCOUNT_DEBUG -#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG -#define GRPC_WORKQUEUE_REF(p, r) \ - grpc_workqueue_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_WORKQUEUE_UNREF(cl, p, r) \ - grpc_workqueue_unref((cl), (p), __FILE__, __LINE__, (r)) -void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, - const char *reason); -void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, - const char *file, int line, const char *reason); -#else -#define GRPC_WORKQUEUE_REF(p, r) grpc_workqueue_ref((p)) -#define GRPC_WORKQUEUE_UNREF(cl, p, r) grpc_workqueue_unref((cl), (p)) -void grpc_workqueue_ref(grpc_workqueue *workqueue); -void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); -#endif - -/** Bind this workqueue to a pollset */ -void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue, - grpc_pollset *pollset); - -/** Add a work item to a workqueue */ -void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure, - int success); - -#endif diff --git a/src/core/iomgr/workqueue_posix.c b/src/core/iomgr/workqueue_posix.c deleted file mode 100644 index 2b42e6d4fb..0000000000 --- a/src/core/iomgr/workqueue_posix.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/iomgr/workqueue.h" - -#include <stdio.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/pollset_posix.h" - -static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success); - -grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx) { - char name[32]; - grpc_workqueue *workqueue = gpr_malloc(sizeof(grpc_workqueue)); - gpr_ref_init(&workqueue->refs, 1); - gpr_mu_init(&workqueue->mu); - workqueue->closure_list.head = workqueue->closure_list.tail = NULL; - grpc_wakeup_fd_init(&workqueue->wakeup_fd); - sprintf(name, "workqueue:%p", (void *)workqueue); - workqueue->wakeup_read_fd = - grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&workqueue->wakeup_fd), name); - grpc_closure_init(&workqueue->read_closure, on_readable, workqueue); - grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, - &workqueue->read_closure); - return workqueue; -} - -static void workqueue_destroy(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue) { - GPR_ASSERT(grpc_closure_list_empty(workqueue->closure_list)); - grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd); -} - -#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG -void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, - const char *reason) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p ref %d -> %d %s", - workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1, - reason); -#else -void grpc_workqueue_ref(grpc_workqueue *workqueue) { -#endif - gpr_ref(&workqueue->refs); -} - -#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG -void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, - const char *file, int line, const char *reason) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s", - workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1, - reason); -#else -void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { -#endif - if (gpr_unref(&workqueue->refs)) { - workqueue_destroy(exec_ctx, workqueue); - } -} - -void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue, - grpc_pollset *pollset) { - grpc_pollset_add_fd(exec_ctx, pollset, workqueue->wakeup_read_fd); -} - -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - gpr_mu_lock(&workqueue->mu); - if (grpc_closure_list_empty(workqueue->closure_list)) { - grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); - } - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); - gpr_mu_unlock(&workqueue->mu); -} - -static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - grpc_workqueue *workqueue = arg; - - if (!success) { - gpr_mu_destroy(&workqueue->mu); - /* HACK: let wakeup_fd code know that we stole the fd */ - workqueue->wakeup_fd.read_fd = 0; - grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); - grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); - gpr_free(workqueue); - } else { - gpr_mu_lock(&workqueue->mu); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); - grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); - gpr_mu_unlock(&workqueue->mu); - grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, - &workqueue->read_closure); - } -} - -void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure, - int success) { - gpr_mu_lock(&workqueue->mu); - if (grpc_closure_list_empty(workqueue->closure_list)) { - grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); - } - grpc_closure_list_add(&workqueue->closure_list, closure, success); - gpr_mu_unlock(&workqueue->mu); -} - -#endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/iomgr/workqueue_posix.h b/src/core/iomgr/workqueue_posix.h deleted file mode 100644 index 68f195ee0d..0000000000 --- a/src/core/iomgr/workqueue_posix.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2015-2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_POSIX_H -#define GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_POSIX_H - -#include "src/core/iomgr/wakeup_fd_posix.h" - -struct grpc_fd; - -struct grpc_workqueue { - gpr_refcount refs; - - gpr_mu mu; - grpc_closure_list closure_list; - - grpc_wakeup_fd wakeup_fd; - struct grpc_fd *wakeup_read_fd; - - grpc_closure read_closure; -}; - -#endif /* GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_POSIX_H */ diff --git a/src/core/iomgr/workqueue_windows.c b/src/core/iomgr/workqueue_windows.c deleted file mode 100644 index f9ca57557b..0000000000 --- a/src/core/iomgr/workqueue_windows.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WIN32 - -#include "src/core/iomgr/workqueue.h" - -#endif /* GPR_WIN32 */ diff --git a/src/core/iomgr/workqueue_windows.h b/src/core/iomgr/workqueue_windows.h deleted file mode 100644 index 941f195f51..0000000000 --- a/src/core/iomgr/workqueue_windows.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_WINDOWS_H -#define GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_WINDOWS_H - -#endif /* GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_WINDOWS_H */ |