xref: /freebsd/contrib/ntp/sntp/libevent/iocp-internal.h (revision a466cc55373fc3cf86837f09da729535b57e69a1)
12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
32b15cb3dSCy Schubert  *
42b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
52b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
62b15cb3dSCy Schubert  * are met:
72b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
82b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
92b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
102b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
112b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
122b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
132b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
142b15cb3dSCy Schubert  *
152b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
172b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
182b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
192b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
212b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
242b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252b15cb3dSCy Schubert  */
262b15cb3dSCy Schubert 
272b15cb3dSCy Schubert #ifndef IOCP_INTERNAL_H_INCLUDED_
282b15cb3dSCy Schubert #define IOCP_INTERNAL_H_INCLUDED_
292b15cb3dSCy Schubert 
302b15cb3dSCy Schubert #ifdef __cplusplus
312b15cb3dSCy Schubert extern "C" {
322b15cb3dSCy Schubert #endif
332b15cb3dSCy Schubert 
342b15cb3dSCy Schubert struct event_overlapped;
352b15cb3dSCy Schubert struct event_iocp_port;
362b15cb3dSCy Schubert struct evbuffer;
372b15cb3dSCy Schubert typedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success);
382b15cb3dSCy Schubert 
392b15cb3dSCy Schubert /* This whole file is actually win32 only. We wrap the structures in a win32
402b15cb3dSCy Schubert  * ifdef so that we can test-compile code that uses these interfaces on
412b15cb3dSCy Schubert  * non-win32 platforms. */
422b15cb3dSCy Schubert #ifdef _WIN32
432b15cb3dSCy Schubert 
442b15cb3dSCy Schubert /**
452b15cb3dSCy Schubert    Internal use only.  Wraps an OVERLAPPED that we're using for libevent
462b15cb3dSCy Schubert    functionality.  Whenever an event_iocp_port gets an event for a given
472b15cb3dSCy Schubert    OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the
482b15cb3dSCy Schubert    iocp_callback function with the event_overlapped, the iocp key, and the
492b15cb3dSCy Schubert    number of bytes transferred as arguments.
502b15cb3dSCy Schubert  */
512b15cb3dSCy Schubert struct event_overlapped {
522b15cb3dSCy Schubert 	OVERLAPPED overlapped;
532b15cb3dSCy Schubert 	iocp_callback cb;
542b15cb3dSCy Schubert };
552b15cb3dSCy Schubert 
562b15cb3dSCy Schubert /* Mingw's headers don't define LPFN_ACCEPTEX. */
572b15cb3dSCy Schubert 
582b15cb3dSCy Schubert typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
592b15cb3dSCy Schubert typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED);
602b15cb3dSCy Schubert typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT);
612b15cb3dSCy Schubert 
622b15cb3dSCy Schubert /** Internal use only. Holds pointers to functions that only some versions of
632b15cb3dSCy Schubert     Windows provide.
642b15cb3dSCy Schubert  */
652b15cb3dSCy Schubert struct win32_extension_fns {
662b15cb3dSCy Schubert 	AcceptExPtr AcceptEx;
672b15cb3dSCy Schubert 	ConnectExPtr ConnectEx;
682b15cb3dSCy Schubert 	GetAcceptExSockaddrsPtr GetAcceptExSockaddrs;
692b15cb3dSCy Schubert };
702b15cb3dSCy Schubert 
712b15cb3dSCy Schubert /**
722b15cb3dSCy Schubert     Internal use only. Stores a Windows IO Completion port, along with
732b15cb3dSCy Schubert     related data.
742b15cb3dSCy Schubert  */
752b15cb3dSCy Schubert struct event_iocp_port {
762b15cb3dSCy Schubert 	/** The port itself */
772b15cb3dSCy Schubert 	HANDLE port;
782b15cb3dSCy Schubert 	/* A lock to cover internal structures. */
792b15cb3dSCy Schubert 	CRITICAL_SECTION lock;
802b15cb3dSCy Schubert 	/** Number of threads ever open on the port. */
812b15cb3dSCy Schubert 	short n_threads;
822b15cb3dSCy Schubert 	/** True iff we're shutting down all the threads on this port */
832b15cb3dSCy Schubert 	short shutdown;
842b15cb3dSCy Schubert 	/** How often the threads on this port check for shutdown and other
852b15cb3dSCy Schubert 	 * conditions */
862b15cb3dSCy Schubert 	long ms;
872b15cb3dSCy Schubert 	/* The threads that are waiting for events. */
882b15cb3dSCy Schubert 	HANDLE *threads;
892b15cb3dSCy Schubert 	/** Number of threads currently open on this port. */
902b15cb3dSCy Schubert 	short n_live_threads;
912b15cb3dSCy Schubert 	/** A semaphore to signal when we are done shutting down. */
922b15cb3dSCy Schubert 	HANDLE *shutdownSemaphore;
932b15cb3dSCy Schubert };
942b15cb3dSCy Schubert 
95*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
962b15cb3dSCy Schubert const struct win32_extension_fns *event_get_win32_extension_fns_(void);
972b15cb3dSCy Schubert #else
982b15cb3dSCy Schubert /* Dummy definition so we can test-compile more things on unix. */
992b15cb3dSCy Schubert struct event_overlapped {
1002b15cb3dSCy Schubert 	iocp_callback cb;
1012b15cb3dSCy Schubert };
1022b15cb3dSCy Schubert #endif
1032b15cb3dSCy Schubert 
1042b15cb3dSCy Schubert /** Initialize the fields in an event_overlapped.
1052b15cb3dSCy Schubert 
1062b15cb3dSCy Schubert     @param overlapped The struct event_overlapped to initialize
1072b15cb3dSCy Schubert     @param cb The callback that should be invoked once the IO operation has
1082b15cb3dSCy Schubert 	finished.
1092b15cb3dSCy Schubert  */
110*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1112b15cb3dSCy Schubert void event_overlapped_init_(struct event_overlapped *, iocp_callback cb);
1122b15cb3dSCy Schubert 
1132b15cb3dSCy Schubert /** Allocate and return a new evbuffer that supports overlapped IO on a given
1142b15cb3dSCy Schubert     socket.  The socket must be associated with an IO completion port using
1152b15cb3dSCy Schubert     event_iocp_port_associate_.
1162b15cb3dSCy Schubert */
117*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1182b15cb3dSCy Schubert struct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd);
1192b15cb3dSCy Schubert 
1202b15cb3dSCy Schubert /** XXXX Document (nickm) */
1212b15cb3dSCy Schubert evutil_socket_t evbuffer_overlapped_get_fd_(struct evbuffer *buf);
1222b15cb3dSCy Schubert 
1232b15cb3dSCy Schubert void evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd);
1242b15cb3dSCy Schubert 
1252b15cb3dSCy Schubert /** Start reading data onto the end of an overlapped evbuffer.
1262b15cb3dSCy Schubert 
1272b15cb3dSCy Schubert     An evbuffer can only have one read pending at a time.  While the read
1282b15cb3dSCy Schubert     is in progress, no other data may be added to the end of the buffer.
1292b15cb3dSCy Schubert     The buffer must be created with event_overlapped_init_().
1302b15cb3dSCy Schubert     evbuffer_commit_read_() must be called in the completion callback.
1312b15cb3dSCy Schubert 
1322b15cb3dSCy Schubert     @param buf The buffer to read onto
1332b15cb3dSCy Schubert     @param n The number of bytes to try to read.
1342b15cb3dSCy Schubert     @param ol Overlapped object with associated completion callback.
1352b15cb3dSCy Schubert     @return 0 on success, -1 on error.
1362b15cb3dSCy Schubert  */
137*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1382b15cb3dSCy Schubert int evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol);
1392b15cb3dSCy Schubert 
1402b15cb3dSCy Schubert /** Start writing data from the start of an evbuffer.
1412b15cb3dSCy Schubert 
1422b15cb3dSCy Schubert     An evbuffer can only have one write pending at a time.  While the write is
1432b15cb3dSCy Schubert     in progress, no other data may be removed from the front of the buffer.
1442b15cb3dSCy Schubert     The buffer must be created with event_overlapped_init_().
1452b15cb3dSCy Schubert     evbuffer_commit_write_() must be called in the completion callback.
1462b15cb3dSCy Schubert 
1472b15cb3dSCy Schubert     @param buf The buffer to read onto
1482b15cb3dSCy Schubert     @param n The number of bytes to try to read.
1492b15cb3dSCy Schubert     @param ol Overlapped object with associated completion callback.
1502b15cb3dSCy Schubert     @return 0 on success, -1 on error.
1512b15cb3dSCy Schubert  */
152*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1532b15cb3dSCy Schubert int evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol);
1542b15cb3dSCy Schubert 
1552b15cb3dSCy Schubert /** XXX document */
156*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1572b15cb3dSCy Schubert void evbuffer_commit_read_(struct evbuffer *, ev_ssize_t);
158*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1592b15cb3dSCy Schubert void evbuffer_commit_write_(struct evbuffer *, ev_ssize_t);
1602b15cb3dSCy Schubert 
1612b15cb3dSCy Schubert /** Create an IOCP, and launch its worker threads.  Internal use only.
1622b15cb3dSCy Schubert 
1632b15cb3dSCy Schubert     This interface is unstable, and will change.
1642b15cb3dSCy Schubert  */
165*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1662b15cb3dSCy Schubert struct event_iocp_port *event_iocp_port_launch_(int n_cpus);
1672b15cb3dSCy Schubert 
1682b15cb3dSCy Schubert /** Associate a file descriptor with an iocp, such that overlapped IO on the
1692b15cb3dSCy Schubert     fd will happen on one of the iocp's worker threads.
1702b15cb3dSCy Schubert */
171*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1722b15cb3dSCy Schubert int event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd,
1732b15cb3dSCy Schubert     ev_uintptr_t key);
1742b15cb3dSCy Schubert 
1752b15cb3dSCy Schubert /** Tell all threads serving an iocp to stop.  Wait for up to waitMsec for all
1762b15cb3dSCy Schubert     the threads to finish whatever they're doing.  If waitMsec is -1, wait
1772b15cb3dSCy Schubert     as long as required.  If all the threads are done, free the port and return
1782b15cb3dSCy Schubert     0. Otherwise, return -1.  If you get a -1 return value, it is safe to call
1792b15cb3dSCy Schubert     this function again.
1802b15cb3dSCy Schubert */
181*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1822b15cb3dSCy Schubert int event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec);
1832b15cb3dSCy Schubert 
1842b15cb3dSCy Schubert /* FIXME document. */
185*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1862b15cb3dSCy Schubert int event_iocp_activate_overlapped_(struct event_iocp_port *port,
1872b15cb3dSCy Schubert     struct event_overlapped *o,
1882b15cb3dSCy Schubert     ev_uintptr_t key, ev_uint32_t n_bytes);
1892b15cb3dSCy Schubert 
1902b15cb3dSCy Schubert struct event_base;
1912b15cb3dSCy Schubert /* FIXME document. */
192*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1932b15cb3dSCy Schubert struct event_iocp_port *event_base_get_iocp_(struct event_base *base);
1942b15cb3dSCy Schubert 
1952b15cb3dSCy Schubert /* FIXME document. */
196*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
1972b15cb3dSCy Schubert int event_base_start_iocp_(struct event_base *base, int n_cpus);
1982b15cb3dSCy Schubert void event_base_stop_iocp_(struct event_base *base);
1992b15cb3dSCy Schubert 
2002b15cb3dSCy Schubert /* FIXME document. */
201*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL
2022b15cb3dSCy Schubert struct bufferevent *bufferevent_async_new_(struct event_base *base,
2032b15cb3dSCy Schubert     evutil_socket_t fd, int options);
2042b15cb3dSCy Schubert 
2052b15cb3dSCy Schubert /* FIXME document. */
2062b15cb3dSCy Schubert void bufferevent_async_set_connected_(struct bufferevent *bev);
2072b15cb3dSCy Schubert int bufferevent_async_can_connect_(struct bufferevent *bev);
2082b15cb3dSCy Schubert int bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd,
2092b15cb3dSCy Schubert 	const struct sockaddr *sa, int socklen);
2102b15cb3dSCy Schubert 
2112b15cb3dSCy Schubert #ifdef __cplusplus
2122b15cb3dSCy Schubert }
2132b15cb3dSCy Schubert #endif
2142b15cb3dSCy Schubert 
2152b15cb3dSCy Schubert #endif
216