/*
* Copyright ( c ) 2009 - 2012 Niels Provos , Nick Mathewson
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1 . Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2 . 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 .
* 3 . The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` 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 AUTHOR 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 "evconfig-private.h"
#ifndef _WIN32_WINNT
/* Minimum required for InitializeCriticalSectionAndSpinCount */
#define _WIN32_WINNT 0 x0403
#endif
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <mswsock.h>
#include "event2/util.h"
#include "util-internal.h"
#include "iocp-internal.h"
#include "log-internal.h"
#include "mm-internal.h"
#include "event-internal.h"
#include "evthread-internal.h"
#define NOTIFICATION_KEY ((ULONG_PTR)-1 )
void
event_overlapped_init_(struct event_overlapped *o, iocp_callback cb)
{
memset(o, 0 , sizeof (struct event_overlapped));
o->cb = cb;
}
static void
handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
{
struct event_overlapped *eo =
EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
eo->cb(eo, completion_key, nBytes, ok);
}
static void
loop(void *port_)
{
struct event_iocp_port *port = port_;
long ms = port->ms;
HANDLE p = port->port;
if (ms <= 0 )
ms = INFINITE;
while (1 ) {
OVERLAPPED *overlapped=NULL;
ULONG_PTR key=0 ;
DWORD bytes=0 ;
int ok = GetQueuedCompletionStatus(p, &bytes, &key,
&overlapped, ms);
EnterCriticalSection(&port->lock);
if (port->shutdown) {
if (--port->n_live_threads == 0 )
ReleaseSemaphore(port->shutdownSemaphore, 1 ,
NULL);
LeaveCriticalSection(&port->lock);
return ;
}
LeaveCriticalSection(&port->lock);
if (key != NOTIFICATION_KEY && overlapped)
handle_entry(overlapped, key, bytes, ok);
else if (!overlapped)
break ;
}
event_warnx("GetQueuedCompletionStatus exited with no event." );
EnterCriticalSection(&port->lock);
if (--port->n_live_threads == 0 )
ReleaseSemaphore(port->shutdownSemaphore, 1 , NULL);
LeaveCriticalSection(&port->lock);
}
int
event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd,
ev_uintptr_t key)
{
HANDLE h;
h = CreateIoCompletionPort((HANDLE)fd, port->port, key, port->n_threads);
if (!h)
return -1 ;
return 0 ;
}
static void *
get_extension_function(SOCKET s, const GUID *which_fn)
{
void *ptr = NULL;
DWORD bytes=0 ;
WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
(GUID*)which_fn, sizeof (*which_fn),
&ptr, sizeof (ptr),
&bytes, NULL, NULL);
/* No need to detect errors here: if ptr is set, then we have a good
function pointer . Otherwise , we should behave as if we had no
function pointer .
*/
return ptr;
}
/* Mingw doesn't have these in its mswsock.h. The values are copied from
wine . h . Perhaps if we copy them exactly , the cargo will come again .
*/
#ifndef WSAID_ACCEPTEX
#define WSAID_ACCEPTEX \
{0 xb5367df1,0 xcbac,0 x11cf,{0 x95,0 xca,0 x00,0 x80,0 x5f,0 x48,0 xa1,0 x92}}
#endif
#ifndef WSAID_CONNECTEX
#define WSAID_CONNECTEX \
{0 x25a207b9,0 xddf3,0 x4660,{0 x8e,0 xe9,0 x76,0 xe5,0 x8c,0 x74,0 x06,0 x3e}}
#endif
#ifndef WSAID_GETACCEPTEXSOCKADDRS
#define WSAID_GETACCEPTEXSOCKADDRS \
{0 xb5367df2,0 xcbac,0 x11cf,{0 x95,0 xca,0 x00,0 x80,0 x5f,0 x48,0 xa1,0 x92}}
#endif
static int extension_fns_initialized = 0 ;
static void
init_extension_functions(struct win32_extension_fns *ext)
{
const GUID acceptex = WSAID_ACCEPTEX;
const GUID connectex = WSAID_CONNECTEX;
const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0 );
if (s == EVUTIL_INVALID_SOCKET)
return ;
ext->AcceptEx = get_extension_function(s, &acceptex);
ext->ConnectEx = get_extension_function(s, &connectex);
ext->GetAcceptExSockaddrs = get_extension_function(s,
&getacceptexsockaddrs);
closesocket(s);
extension_fns_initialized = 1 ;
}
static struct win32_extension_fns the_extension_fns;
const struct win32_extension_fns *
event_get_win32_extension_fns_(void )
{
return &the_extension_fns;
}
#define N_CPUS_DEFAULT 2
struct event_iocp_port *
event_iocp_port_launch_(int n_cpus)
{
struct event_iocp_port *port;
int i;
if (!extension_fns_initialized)
init_extension_functions(&the_extension_fns);
if (!(port = mm_calloc(1 , sizeof (struct event_iocp_port))))
return NULL;
if (n_cpus <= 0 )
n_cpus = N_CPUS_DEFAULT;
port->n_threads = n_cpus * 2 ;
port->threads = mm_calloc(port->n_threads, sizeof (HANDLE));
if (!port->threads)
goto err;
port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0 ,
n_cpus);
port->ms = -1 ;
if (!port->port)
goto err;
port->shutdownSemaphore = CreateSemaphore(NULL, 0 , 1 , NULL);
if (!port->shutdownSemaphore)
goto err;
for (i=0 ; i<port->n_threads; ++i) {
ev_uintptr_t th = _beginthread(loop, 0 , port);
if (th == (ev_uintptr_t)-1 )
goto err;
port->threads[i] = (HANDLE)th;
++port->n_live_threads;
}
InitializeCriticalSectionAndSpinCount(&port->lock, 1000 );
return port;
err:
if (port->port)
CloseHandle(port->port);
if (port->threads)
mm_free(port->threads);
if (port->shutdownSemaphore)
CloseHandle(port->shutdownSemaphore);
mm_free(port);
return NULL;
}
static void
event_iocp_port_unlock_and_free_(struct event_iocp_port *port)
{
DeleteCriticalSection(&port->lock);
CloseHandle(port->port);
CloseHandle(port->shutdownSemaphore);
mm_free(port->threads);
mm_free(port);
}
static int
event_iocp_notify_all(struct event_iocp_port *port)
{
int i, r, ok=1 ;
for (i=0 ; i<port->n_threads; ++i) {
r = PostQueuedCompletionStatus(port->port, 0 , NOTIFICATION_KEY,
NULL);
if (!r)
ok = 0 ;
}
return ok ? 0 : -1 ;
}
int
event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec)
{
DWORD ms = INFINITE;
int n;
EnterCriticalSection(&port->lock);
port->shutdown = 1 ;
LeaveCriticalSection(&port->lock);
event_iocp_notify_all(port);
if (waitMsec >= 0 )
ms = waitMsec;
WaitForSingleObject(port->shutdownSemaphore, ms);
EnterCriticalSection(&port->lock);
n = port->n_live_threads;
LeaveCriticalSection(&port->lock);
if (n == 0 ) {
event_iocp_port_unlock_and_free_(port);
return 0 ;
} else {
return -1 ;
}
}
int
event_iocp_activate_overlapped_(
struct event_iocp_port *port, struct event_overlapped *o,
ev_uintptr_t key, ev_uint32_t n)
{
BOOL r;
r = PostQueuedCompletionStatus(port->port, n, key, &o->overlapped);
return (r==0 ) ? -1 : 0 ;
}
struct event_iocp_port *
event_base_get_iocp_(struct event_base *base)
{
#ifdef _WIN32
return base->iocp;
#else
return NULL;
#endif
}
Messung V0.5 in Prozent C=96 H=97 G=96
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-08-27)
¤
*© Formatika GbR, Deutschland