Blame libevent/event-internal.h

Packit e9ba0d
/*
Packit e9ba0d
 * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
Packit e9ba0d
 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
Packit e9ba0d
 *
Packit e9ba0d
 * Redistribution and use in source and binary forms, with or without
Packit e9ba0d
 * modification, are permitted provided that the following conditions
Packit e9ba0d
 * are met:
Packit e9ba0d
 * 1. Redistributions of source code must retain the above copyright
Packit e9ba0d
 *    notice, this list of conditions and the following disclaimer.
Packit e9ba0d
 * 2. Redistributions in binary form must reproduce the above copyright
Packit e9ba0d
 *    notice, this list of conditions and the following disclaimer in the
Packit e9ba0d
 *    documentation and/or other materials provided with the distribution.
Packit e9ba0d
 * 3. The name of the author may not be used to endorse or promote products
Packit e9ba0d
 *    derived from this software without specific prior written permission.
Packit e9ba0d
 *
Packit e9ba0d
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Packit e9ba0d
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit e9ba0d
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit e9ba0d
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit e9ba0d
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit e9ba0d
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit e9ba0d
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit e9ba0d
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit e9ba0d
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit e9ba0d
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit e9ba0d
 */
Packit e9ba0d
#ifndef _EVENT_INTERNAL_H_
Packit e9ba0d
#define _EVENT_INTERNAL_H_
Packit e9ba0d
Packit e9ba0d
#ifdef __cplusplus
Packit e9ba0d
extern "C" {
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#include "event2/event-config.h"
Packit e9ba0d
#include <time.h>
Packit e9ba0d
#include <sys/queue.h>
Packit e9ba0d
#include "event2/event_struct.h"
Packit e9ba0d
#include "minheap-internal.h"
Packit e9ba0d
#include "evsignal-internal.h"
Packit e9ba0d
#include "mm-internal.h"
Packit e9ba0d
#include "defer-internal.h"
Packit e9ba0d
Packit e9ba0d
/* map union members back */
Packit e9ba0d
Packit e9ba0d
/* mutually exclusive */
Packit e9ba0d
#define ev_signal_next	_ev.ev_signal.ev_signal_next
Packit e9ba0d
#define ev_io_next	_ev.ev_io.ev_io_next
Packit e9ba0d
#define ev_io_timeout	_ev.ev_io.ev_timeout
Packit e9ba0d
Packit e9ba0d
/* used only by signals */
Packit e9ba0d
#define ev_ncalls	_ev.ev_signal.ev_ncalls
Packit e9ba0d
#define ev_pncalls	_ev.ev_signal.ev_pncalls
Packit e9ba0d
Packit e9ba0d
/* Possible values for ev_closure in struct event. */
Packit e9ba0d
#define EV_CLOSURE_NONE 0
Packit e9ba0d
#define EV_CLOSURE_SIGNAL 1
Packit e9ba0d
#define EV_CLOSURE_PERSIST 2
Packit e9ba0d
Packit e9ba0d
/** Structure to define the backend of a given event_base. */
Packit e9ba0d
struct eventop {
Packit e9ba0d
	/** The name of this backend. */
Packit e9ba0d
	const char *name;
Packit e9ba0d
	/** Function to set up an event_base to use this backend.  It should
Packit e9ba0d
	 * create a new structure holding whatever information is needed to
Packit e9ba0d
	 * run the backend, and return it.  The returned pointer will get
Packit e9ba0d
	 * stored by event_init into the event_base.evbase field.  On failure,
Packit e9ba0d
	 * this function should return NULL. */
Packit e9ba0d
	void *(*init)(struct event_base *);
Packit e9ba0d
	/** Enable reading/writing on a given fd or signal.  'events' will be
Packit e9ba0d
	 * the events that we're trying to enable: one or more of EV_READ,
Packit e9ba0d
	 * EV_WRITE, EV_SIGNAL, and EV_ET.  'old' will be those events that
Packit e9ba0d
	 * were enabled on this fd previously.  'fdinfo' will be a structure
Packit e9ba0d
	 * associated with the fd by the evmap; its size is defined by the
Packit e9ba0d
	 * fdinfo field below.  It will be set to 0 the first time the fd is
Packit e9ba0d
	 * added.  The function should return 0 on success and -1 on error.
Packit e9ba0d
	 */
Packit e9ba0d
	int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
Packit e9ba0d
	/** As "add", except 'events' contains the events we mean to disable. */
Packit e9ba0d
	int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
Packit e9ba0d
	/** Function to implement the core of an event loop.  It must see which
Packit e9ba0d
	    added events are ready, and cause event_active to be called for each
Packit e9ba0d
	    active event (usually via event_io_active or such).  It should
Packit e9ba0d
	    return 0 on success and -1 on error.
Packit e9ba0d
	 */
Packit e9ba0d
	int (*dispatch)(struct event_base *, struct timeval *);
Packit e9ba0d
	/** Function to clean up and free our data from the event_base. */
Packit e9ba0d
	void (*dealloc)(struct event_base *);
Packit e9ba0d
	/** Flag: set if we need to reinitialize the event base after we fork.
Packit e9ba0d
	 */
Packit e9ba0d
	int need_reinit;
Packit e9ba0d
	/** Bit-array of supported event_method_features that this backend can
Packit e9ba0d
	 * provide. */
Packit e9ba0d
	enum event_method_feature features;
Packit e9ba0d
	/** Length of the extra information we should record for each fd that
Packit e9ba0d
	    has one or more active events.  This information is recorded
Packit e9ba0d
	    as part of the evmap entry for each fd, and passed as an argument
Packit e9ba0d
	    to the add and del functions above.
Packit e9ba0d
	 */
Packit e9ba0d
	size_t fdinfo_len;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
/* If we're on win32, then file descriptors are not nice low densely packed
Packit e9ba0d
   integers.  Instead, they are pointer-like windows handles, and we want to
Packit e9ba0d
   use a hashtable instead of an array to map fds to events.
Packit e9ba0d
*/
Packit e9ba0d
#define EVMAP_USE_HT
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/* #define HT_CACHE_HASH_VALS */
Packit e9ba0d
Packit e9ba0d
#ifdef EVMAP_USE_HT
Packit e9ba0d
#include "ht-internal.h"
Packit e9ba0d
struct event_map_entry;
Packit e9ba0d
HT_HEAD(event_io_map, event_map_entry);
Packit e9ba0d
#else
Packit e9ba0d
#define event_io_map event_signal_map
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/* Used to map signal numbers to a list of events.  If EVMAP_USE_HT is not
Packit e9ba0d
   defined, this structure is also used as event_io_map, which maps fds to a
Packit e9ba0d
   list of events.
Packit e9ba0d
*/
Packit e9ba0d
struct event_signal_map {
Packit e9ba0d
	/* An array of evmap_io * or of evmap_signal *; empty entries are
Packit e9ba0d
	 * set to NULL. */
Packit e9ba0d
	void **entries;
Packit e9ba0d
	/* The number of entries available in entries */
Packit e9ba0d
	int nentries;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
/* A list of events waiting on a given 'common' timeout value.  Ordinarily,
Packit e9ba0d
 * events waiting for a timeout wait on a minheap.  Sometimes, however, a
Packit e9ba0d
 * queue can be faster.
Packit e9ba0d
 **/
Packit e9ba0d
struct common_timeout_list {
Packit e9ba0d
	/* List of events currently waiting in the queue. */
Packit e9ba0d
	struct event_list events;
Packit e9ba0d
	/* 'magic' timeval used to indicate the duration of events in this
Packit e9ba0d
	 * queue. */
Packit e9ba0d
	struct timeval duration;
Packit e9ba0d
	/* Event that triggers whenever one of the events in the queue is
Packit e9ba0d
	 * ready to activate */
Packit e9ba0d
	struct event timeout_event;
Packit e9ba0d
	/* The event_base that this timeout list is part of */
Packit e9ba0d
	struct event_base *base;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
/** Mask used to get the real tv_usec value from a common timeout. */
Packit e9ba0d
#define COMMON_TIMEOUT_MICROSECONDS_MASK       0x000fffff
Packit e9ba0d
Packit e9ba0d
struct event_change;
Packit e9ba0d
Packit e9ba0d
/* List of 'changes' since the last call to eventop.dispatch.  Only maintained
Packit e9ba0d
 * if the backend is using changesets. */
Packit e9ba0d
struct event_changelist {
Packit e9ba0d
	struct event_change *changes;
Packit e9ba0d
	int n_changes;
Packit e9ba0d
	int changes_size;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
#ifndef _EVENT_DISABLE_DEBUG_MODE
Packit e9ba0d
/* Global internal flag: set to one if debug mode is on. */
Packit e9ba0d
extern int _event_debug_mode_on;
Packit e9ba0d
#define EVENT_DEBUG_MODE_IS_ON() (_event_debug_mode_on)
Packit e9ba0d
#else
Packit e9ba0d
#define EVENT_DEBUG_MODE_IS_ON() (0)
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
struct event_base {
Packit e9ba0d
	/** Function pointers and other data to describe this event_base's
Packit e9ba0d
	 * backend. */
Packit e9ba0d
	const struct eventop *evsel;
Packit e9ba0d
	/** Pointer to backend-specific data. */
Packit e9ba0d
	void *evbase;
Packit e9ba0d
Packit e9ba0d
	/** List of changes to tell backend about at next dispatch.  Only used
Packit e9ba0d
	 * by the O(1) backends. */
Packit e9ba0d
	struct event_changelist changelist;
Packit e9ba0d
Packit e9ba0d
	/** Function pointers used to describe the backend that this event_base
Packit e9ba0d
	 * uses for signals */
Packit e9ba0d
	const struct eventop *evsigsel;
Packit e9ba0d
	/** Data to implement the common signal handelr code. */
Packit e9ba0d
	struct evsig_info sig;
Packit e9ba0d
Packit e9ba0d
	/** Number of virtual events */
Packit e9ba0d
	int virtual_event_count;
Packit e9ba0d
	/** Number of total events added to this event_base */
Packit e9ba0d
	int event_count;
Packit e9ba0d
	/** Number of total events active in this event_base */
Packit e9ba0d
	int event_count_active;
Packit e9ba0d
Packit e9ba0d
	/** Set if we should terminate the loop once we're done processing
Packit e9ba0d
	 * events. */
Packit e9ba0d
	int event_gotterm;
Packit e9ba0d
	/** Set if we should terminate the loop immediately */
Packit e9ba0d
	int event_break;
Packit e9ba0d
	/** Set if we should start a new instance of the loop immediately. */
Packit e9ba0d
	int event_continue;
Packit e9ba0d
Packit e9ba0d
	/** The currently running priority of events */
Packit e9ba0d
	int event_running_priority;
Packit e9ba0d
Packit e9ba0d
	/** Set if we're running the event_base_loop function, to prevent
Packit e9ba0d
	 * reentrant invocation. */
Packit e9ba0d
	int running_loop;
Packit e9ba0d
Packit e9ba0d
	/* Active event management. */
Packit e9ba0d
	/** An array of nactivequeues queues for active events (ones that
Packit e9ba0d
	 * have triggered, and whose callbacks need to be called).  Low
Packit e9ba0d
	 * priority numbers are more important, and stall higher ones.
Packit e9ba0d
	 */
Packit e9ba0d
	struct event_list *activequeues;
Packit e9ba0d
	/** The length of the activequeues array */
Packit e9ba0d
	int nactivequeues;
Packit e9ba0d
Packit e9ba0d
	/* common timeout logic */
Packit e9ba0d
Packit e9ba0d
	/** An array of common_timeout_list* for all of the common timeout
Packit e9ba0d
	 * values we know. */
Packit e9ba0d
	struct common_timeout_list **common_timeout_queues;
Packit e9ba0d
	/** The number of entries used in common_timeout_queues */
Packit e9ba0d
	int n_common_timeouts;
Packit e9ba0d
	/** The total size of common_timeout_queues. */
Packit e9ba0d
	int n_common_timeouts_allocated;
Packit e9ba0d
Packit e9ba0d
	/** List of defered_cb that are active.  We run these after the active
Packit e9ba0d
	 * events. */
Packit e9ba0d
	struct deferred_cb_queue defer_queue;
Packit e9ba0d
Packit e9ba0d
	/** Mapping from file descriptors to enabled (added) events */
Packit e9ba0d
	struct event_io_map io;
Packit e9ba0d
Packit e9ba0d
	/** Mapping from signal numbers to enabled (added) events. */
Packit e9ba0d
	struct event_signal_map sigmap;
Packit e9ba0d
Packit e9ba0d
	/** All events that have been enabled (added) in this event_base */
Packit e9ba0d
	struct event_list eventqueue;
Packit e9ba0d
Packit e9ba0d
	/** Stored timeval; used to detect when time is running backwards. */
Packit e9ba0d
	struct timeval event_tv;
Packit e9ba0d
Packit e9ba0d
	/** Priority queue of events with timeouts. */
Packit e9ba0d
	struct min_heap timeheap;
Packit e9ba0d
Packit e9ba0d
	/** Stored timeval: used to avoid calling gettimeofday/clock_gettime
Packit e9ba0d
	 * too often. */
Packit e9ba0d
	struct timeval tv_cache;
Packit e9ba0d
Packit e9ba0d
#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
Packit e9ba0d
	/** Difference between internal time (maybe from clock_gettime) and
Packit e9ba0d
	 * gettimeofday. */
Packit e9ba0d
	struct timeval tv_clock_diff;
Packit e9ba0d
	/** Second in which we last updated tv_clock_diff, in monotonic time. */
Packit e9ba0d
	time_t last_updated_clock_diff;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
Packit e9ba0d
	/* threading support */
Packit e9ba0d
	/** The thread currently running the event_loop for this base */
Packit e9ba0d
	unsigned long th_owner_id;
Packit e9ba0d
	/** A lock to prevent conflicting accesses to this event_base */
Packit e9ba0d
	void *th_base_lock;
Packit e9ba0d
	/** The event whose callback is executing right now */
Packit e9ba0d
	struct event *current_event;
Packit e9ba0d
	/** A condition that gets signalled when we're done processing an
Packit e9ba0d
	 * event with waiters on it. */
Packit e9ba0d
	void *current_event_cond;
Packit e9ba0d
	/** Number of threads blocking on current_event_cond. */
Packit e9ba0d
	int current_event_waiters;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
	/** IOCP support structure, if IOCP is enabled. */
Packit e9ba0d
	struct event_iocp_port *iocp;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	/** Flags that this base was configured with */
Packit e9ba0d
	enum event_base_config_flag flags;
Packit e9ba0d
Packit e9ba0d
	/* Notify main thread to wake up break, etc. */
Packit e9ba0d
	/** True if the base already has a pending notify, and we don't need
Packit e9ba0d
	 * to add any more. */
Packit e9ba0d
	int is_notify_pending;
Packit e9ba0d
	/** A socketpair used by some th_notify functions to wake up the main
Packit e9ba0d
	 * thread. */
Packit e9ba0d
	evutil_socket_t th_notify_fd[2];
Packit e9ba0d
	/** An event used by some th_notify functions to wake up the main
Packit e9ba0d
	 * thread. */
Packit e9ba0d
	struct event th_notify;
Packit e9ba0d
	/** A function used to wake up the main thread from another thread. */
Packit e9ba0d
	int (*th_notify_fn)(struct event_base *base);
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
struct event_config_entry {
Packit e9ba0d
	TAILQ_ENTRY(event_config_entry) next;
Packit e9ba0d
Packit e9ba0d
	const char *avoid_method;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
/** Internal structure: describes the configuration we want for an event_base
Packit e9ba0d
 * that we're about to allocate. */
Packit e9ba0d
struct event_config {
Packit e9ba0d
	TAILQ_HEAD(event_configq, event_config_entry) entries;
Packit e9ba0d
Packit e9ba0d
	int n_cpus_hint;
Packit e9ba0d
	enum event_method_feature require_features;
Packit e9ba0d
	enum event_base_config_flag flags;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
/* Internal use only: Functions that might be missing from <sys/queue.h> */
Packit e9ba0d
#if defined(_EVENT_HAVE_SYS_QUEUE_H) && !defined(_EVENT_HAVE_TAILQFOREACH)
Packit e9ba0d
#ifndef TAILQ_FIRST
Packit e9ba0d
#define	TAILQ_FIRST(head)		((head)->tqh_first)
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef TAILQ_END
Packit e9ba0d
#define	TAILQ_END(head)			NULL
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef TAILQ_NEXT
Packit e9ba0d
#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef TAILQ_FOREACH
Packit e9ba0d
#define TAILQ_FOREACH(var, head, field)					\
Packit e9ba0d
	for ((var) = TAILQ_FIRST(head);					\
Packit e9ba0d
	     (var) != TAILQ_END(head);					\
Packit e9ba0d
	     (var) = TAILQ_NEXT(var, field))
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef TAILQ_INSERT_BEFORE
Packit e9ba0d
#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
Packit e9ba0d
	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
Packit e9ba0d
	(elm)->field.tqe_next = (listelm);				\
Packit e9ba0d
	*(listelm)->field.tqe_prev = (elm);				\
Packit e9ba0d
	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
Packit e9ba0d
} while (0)
Packit e9ba0d
#endif
Packit e9ba0d
#endif /* TAILQ_FOREACH */
Packit e9ba0d
Packit e9ba0d
#define N_ACTIVE_CALLBACKS(base)					\
Packit e9ba0d
	((base)->event_count_active + (base)->defer_queue.active_count)
Packit e9ba0d
Packit e9ba0d
int _evsig_set_handler(struct event_base *base, int evsignal,
Packit e9ba0d
			  void (*fn)(int));
Packit e9ba0d
int _evsig_restore_handler(struct event_base *base, int evsignal);
Packit e9ba0d
Packit e9ba0d
Packit e9ba0d
void event_active_nolock(struct event *ev, int res, short count);
Packit e9ba0d
Packit e9ba0d
/* FIXME document. */
Packit e9ba0d
void event_base_add_virtual(struct event_base *base);
Packit e9ba0d
void event_base_del_virtual(struct event_base *base);
Packit e9ba0d
Packit e9ba0d
/** For debugging: unless assertions are disabled, verify the referential
Packit e9ba0d
    integrity of the internal data structures of 'base'.  This operation can
Packit e9ba0d
    be expensive.
Packit e9ba0d
Packit e9ba0d
    Returns on success; aborts on failure.
Packit e9ba0d
*/
Packit e9ba0d
void event_base_assert_ok(struct event_base *base);
Packit e9ba0d
Packit e9ba0d
#ifdef __cplusplus
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#endif /* _EVENT_INTERNAL_H_ */
Packit e9ba0d