ipc/chromium/src/third_party/libevent/event_iocp.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson
     3  *
     4  * Redistribution and use in source and binary forms, with or without
     5  * modification, are permitted provided that the following conditions
     6  * are met:
     7  * 1. Redistributions of source code must retain the above copyright
     8  *    notice, this list of conditions and the following disclaimer.
     9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  * 3. The name of the author may not be used to endorse or promote products
    13  *    derived from this software without specific prior written permission.
    14  *
    15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    25  */
    27 #ifndef _WIN32_WINNT
    28 /* Minimum required for InitializeCriticalSectionAndSpinCount */
    29 #define _WIN32_WINNT 0x0403
    30 #endif
    31 #include <winsock2.h>
    32 #include <windows.h>
    33 #include <process.h>
    34 #include <stdio.h>
    35 #include <mswsock.h>
    37 #include "event2/util.h"
    38 #include "util-internal.h"
    39 #include "iocp-internal.h"
    40 #include "log-internal.h"
    41 #include "mm-internal.h"
    42 #include "event-internal.h"
    43 #include "evthread-internal.h"
    45 #define NOTIFICATION_KEY ((ULONG_PTR)-1)
    47 void
    48 event_overlapped_init(struct event_overlapped *o, iocp_callback cb)
    49 {
    50 	memset(o, 0, sizeof(struct event_overlapped));
    51 	o->cb = cb;
    52 }
    54 static void
    55 handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
    56 {
    57 	struct event_overlapped *eo =
    58 	    EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
    59 	eo->cb(eo, completion_key, nBytes, ok);
    60 }
    62 static void
    63 loop(void *_port)
    64 {
    65 	struct event_iocp_port *port = _port;
    66 	long ms = port->ms;
    67 	HANDLE p = port->port;
    69 	if (ms <= 0)
    70 		ms = INFINITE;
    72 	while (1) {
    73 		OVERLAPPED *overlapped=NULL;
    74 		ULONG_PTR key=0;
    75 		DWORD bytes=0;
    76 		int ok = GetQueuedCompletionStatus(p, &bytes, &key,
    77 			&overlapped, ms);
    78 		EnterCriticalSection(&port->lock);
    79 		if (port->shutdown) {
    80 			if (--port->n_live_threads == 0)
    81 				ReleaseSemaphore(port->shutdownSemaphore, 1,
    82 						NULL);
    83 			LeaveCriticalSection(&port->lock);
    84 			return;
    85 		}
    86 		LeaveCriticalSection(&port->lock);
    88 		if (key != NOTIFICATION_KEY && overlapped)
    89 			handle_entry(overlapped, key, bytes, ok);
    90 		else if (!overlapped)
    91 			break;
    92 	}
    93 	event_warnx("GetQueuedCompletionStatus exited with no event.");
    94 	EnterCriticalSection(&port->lock);
    95 	if (--port->n_live_threads == 0)
    96 		ReleaseSemaphore(port->shutdownSemaphore, 1, NULL);
    97 	LeaveCriticalSection(&port->lock);
    98 }
   100 int
   101 event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd,
   102     ev_uintptr_t key)
   103 {
   104 	HANDLE h;
   105 	h = CreateIoCompletionPort((HANDLE)fd, port->port, key, port->n_threads);
   106 	if (!h)
   107 		return -1;
   108 	return 0;
   109 }
   111 static void *
   112 get_extension_function(SOCKET s, const GUID *which_fn)
   113 {
   114 	void *ptr = NULL;
   115 	DWORD bytes=0;
   116 	WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
   117 	    (GUID*)which_fn, sizeof(*which_fn),
   118 	    &ptr, sizeof(ptr),
   119 	    &bytes, NULL, NULL);
   121 	/* No need to detect errors here: if ptr is set, then we have a good
   122 	   function pointer.  Otherwise, we should behave as if we had no
   123 	   function pointer.
   124 	*/
   125 	return ptr;
   126 }
   128 /* Mingw doesn't have these in its mswsock.h.  The values are copied from
   129    wine.h.   Perhaps if we copy them exactly, the cargo will come again.
   130 */
   131 #ifndef WSAID_ACCEPTEX
   132 #define WSAID_ACCEPTEX \
   133 	{0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
   134 #endif
   135 #ifndef WSAID_CONNECTEX
   136 #define WSAID_CONNECTEX \
   137 	{0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
   138 #endif
   139 #ifndef WSAID_GETACCEPTEXSOCKADDRS
   140 #define WSAID_GETACCEPTEXSOCKADDRS \
   141 	{0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
   142 #endif
   144 static void
   145 init_extension_functions(struct win32_extension_fns *ext)
   146 {
   147 	const GUID acceptex = WSAID_ACCEPTEX;
   148 	const GUID connectex = WSAID_CONNECTEX;
   149 	const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
   150 	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
   151 	if (s == INVALID_SOCKET)
   152 		return;
   153 	ext->AcceptEx = get_extension_function(s, &acceptex);
   154 	ext->ConnectEx = get_extension_function(s, &connectex);
   155 	ext->GetAcceptExSockaddrs = get_extension_function(s,
   156 	    &getacceptexsockaddrs);
   157 	closesocket(s);
   158 }
   160 static struct win32_extension_fns the_extension_fns;
   161 static int extension_fns_initialized = 0;
   163 const struct win32_extension_fns *
   164 event_get_win32_extension_fns(void)
   165 {
   166 	return &the_extension_fns;
   167 }
   169 #define N_CPUS_DEFAULT 2
   171 struct event_iocp_port *
   172 event_iocp_port_launch(int n_cpus)
   173 {
   174 	struct event_iocp_port *port;
   175 	int i;
   177 	if (!extension_fns_initialized)
   178 		init_extension_functions(&the_extension_fns);
   180 	if (!(port = mm_calloc(1, sizeof(struct event_iocp_port))))
   181 		return NULL;
   183 	if (n_cpus <= 0)
   184 		n_cpus = N_CPUS_DEFAULT;
   185 	port->n_threads = n_cpus * 2;
   186 	port->threads = mm_calloc(port->n_threads, sizeof(HANDLE));
   187 	if (!port->threads)
   188 		goto err;
   190 	port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
   191 			n_cpus);
   192 	port->ms = -1;
   193 	if (!port->port)
   194 		goto err;
   196 	port->shutdownSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
   197 	if (!port->shutdownSemaphore)
   198 		goto err;
   200 	for (i=0; i<port->n_threads; ++i) {
   201 		ev_uintptr_t th = _beginthread(loop, 0, port);
   202 		if (th == (ev_uintptr_t)-1)
   203 			goto err;
   204 		port->threads[i] = (HANDLE)th;
   205 		++port->n_live_threads;
   206 	}
   208 	InitializeCriticalSectionAndSpinCount(&port->lock, 1000);
   210 	return port;
   211 err:
   212 	if (port->port)
   213 		CloseHandle(port->port);
   214 	if (port->threads)
   215 		mm_free(port->threads);
   216 	if (port->shutdownSemaphore)
   217 		CloseHandle(port->shutdownSemaphore);
   218 	mm_free(port);
   219 	return NULL;
   220 }
   222 static void
   223 _event_iocp_port_unlock_and_free(struct event_iocp_port *port)
   224 {
   225 	DeleteCriticalSection(&port->lock);
   226 	CloseHandle(port->port);
   227 	CloseHandle(port->shutdownSemaphore);
   228 	mm_free(port->threads);
   229 	mm_free(port);
   230 }
   232 static int
   233 event_iocp_notify_all(struct event_iocp_port *port)
   234 {
   235 	int i, r, ok=1;
   236 	for (i=0; i<port->n_threads; ++i) {
   237 		r = PostQueuedCompletionStatus(port->port, 0, NOTIFICATION_KEY,
   238 		    NULL);
   239 		if (!r)
   240 			ok = 0;
   241 	}
   242 	return ok ? 0 : -1;
   243 }
   245 int
   246 event_iocp_shutdown(struct event_iocp_port *port, long waitMsec)
   247 {
   248 	DWORD ms = INFINITE;
   249 	int n;
   251 	EnterCriticalSection(&port->lock);
   252 	port->shutdown = 1;
   253 	LeaveCriticalSection(&port->lock);
   254 	event_iocp_notify_all(port);
   256 	if (waitMsec >= 0)
   257 		ms = waitMsec;
   259 	WaitForSingleObject(port->shutdownSemaphore, ms);
   260 	EnterCriticalSection(&port->lock);
   261 	n = port->n_live_threads;
   262 	LeaveCriticalSection(&port->lock);
   263 	if (n == 0) {
   264 		_event_iocp_port_unlock_and_free(port);
   265 		return 0;
   266 	} else {
   267 		return -1;
   268 	}
   269 }
   271 int
   272 event_iocp_activate_overlapped(
   273     struct event_iocp_port *port, struct event_overlapped *o,
   274     ev_uintptr_t key, ev_uint32_t n)
   275 {
   276 	BOOL r;
   278 	r = PostQueuedCompletionStatus(port->port, n, key, &o->overlapped);
   279 	return (r==0) ? -1 : 0;
   280 }
   282 struct event_iocp_port *
   283 event_base_get_iocp(struct event_base *base)
   284 {
   285 #ifdef WIN32
   286 	return base->iocp;
   287 #else
   288 	return NULL;
   289 #endif
   290 }

mercurial