ipc/chromium/src/third_party/libevent/evbuffer-internal.h

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.

michael@0 1 /*
michael@0 2 * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
michael@0 3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
michael@0 4 *
michael@0 5 * Redistribution and use in source and binary forms, with or without
michael@0 6 * modification, are permitted provided that the following conditions
michael@0 7 * are met:
michael@0 8 * 1. Redistributions of source code must retain the above copyright
michael@0 9 * notice, this list of conditions and the following disclaimer.
michael@0 10 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 11 * notice, this list of conditions and the following disclaimer in the
michael@0 12 * documentation and/or other materials provided with the distribution.
michael@0 13 * 3. The name of the author may not be used to endorse or promote products
michael@0 14 * derived from this software without specific prior written permission.
michael@0 15 *
michael@0 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
michael@0 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
michael@0 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@0 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
michael@0 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
michael@0 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
michael@0 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 26 */
michael@0 27 #ifndef _EVBUFFER_INTERNAL_H_
michael@0 28 #define _EVBUFFER_INTERNAL_H_
michael@0 29
michael@0 30 #ifdef __cplusplus
michael@0 31 extern "C" {
michael@0 32 #endif
michael@0 33
michael@0 34 #include "event2/event-config.h"
michael@0 35 #include "event2/util.h"
michael@0 36 #include "util-internal.h"
michael@0 37 #include "defer-internal.h"
michael@0 38
michael@0 39 /* Experimental cb flag: "never deferred." Implementation note:
michael@0 40 * these callbacks may get an inaccurate view of n_del/n_added in their
michael@0 41 * arguments. */
michael@0 42 #define EVBUFFER_CB_NODEFER 2
michael@0 43
michael@0 44 #ifdef WIN32
michael@0 45 #include <winsock2.h>
michael@0 46 #endif
michael@0 47 #include <sys/queue.h>
michael@0 48
michael@0 49 /* Minimum allocation for a chain. We define this so that we're burning no
michael@0 50 * more than 5% of each allocation on overhead. It would be nice to lose even
michael@0 51 * less space, though. */
michael@0 52 #if _EVENT_SIZEOF_VOID_P < 8
michael@0 53 #define MIN_BUFFER_SIZE 512
michael@0 54 #else
michael@0 55 #define MIN_BUFFER_SIZE 1024
michael@0 56 #endif
michael@0 57
michael@0 58 /** A single evbuffer callback for an evbuffer. This function will be invoked
michael@0 59 * when bytes are added to or removed from the evbuffer. */
michael@0 60 struct evbuffer_cb_entry {
michael@0 61 /** Structures to implement a doubly-linked queue of callbacks */
michael@0 62 TAILQ_ENTRY(evbuffer_cb_entry) next;
michael@0 63 /** The callback function to invoke when this callback is called.
michael@0 64 If EVBUFFER_CB_OBSOLETE is set in flags, the cb_obsolete field is
michael@0 65 valid; otherwise, cb_func is valid. */
michael@0 66 union {
michael@0 67 evbuffer_cb_func cb_func;
michael@0 68 evbuffer_cb cb_obsolete;
michael@0 69 } cb;
michael@0 70 /** Argument to pass to cb. */
michael@0 71 void *cbarg;
michael@0 72 /** Currently set flags on this callback. */
michael@0 73 ev_uint32_t flags;
michael@0 74 };
michael@0 75
michael@0 76 struct bufferevent;
michael@0 77 struct evbuffer_chain;
michael@0 78 struct evbuffer {
michael@0 79 /** The first chain in this buffer's linked list of chains. */
michael@0 80 struct evbuffer_chain *first;
michael@0 81 /** The last chain in this buffer's linked list of chains. */
michael@0 82 struct evbuffer_chain *last;
michael@0 83
michael@0 84 /** Pointer to the next pointer pointing at the 'last_with_data' chain.
michael@0 85 *
michael@0 86 * To unpack:
michael@0 87 *
michael@0 88 * The last_with_data chain is the last chain that has any data in it.
michael@0 89 * If all chains in the buffer are empty, it is the first chain.
michael@0 90 * If the buffer has no chains, it is NULL.
michael@0 91 *
michael@0 92 * The last_with_datap pointer points at _whatever 'next' pointer_
michael@0 93 * points at the last_with_datap chain. If the last_with_data chain
michael@0 94 * is the first chain, or it is NULL, then the last_with_datap pointer
michael@0 95 * is &buf->first.
michael@0 96 */
michael@0 97 struct evbuffer_chain **last_with_datap;
michael@0 98
michael@0 99 /** Total amount of bytes stored in all chains.*/
michael@0 100 size_t total_len;
michael@0 101
michael@0 102 /** Number of bytes we have added to the buffer since we last tried to
michael@0 103 * invoke callbacks. */
michael@0 104 size_t n_add_for_cb;
michael@0 105 /** Number of bytes we have removed from the buffer since we last
michael@0 106 * tried to invoke callbacks. */
michael@0 107 size_t n_del_for_cb;
michael@0 108
michael@0 109 #ifndef _EVENT_DISABLE_THREAD_SUPPORT
michael@0 110 /** A lock used to mediate access to this buffer. */
michael@0 111 void *lock;
michael@0 112 #endif
michael@0 113 /** True iff we should free the lock field when we free this
michael@0 114 * evbuffer. */
michael@0 115 unsigned own_lock : 1;
michael@0 116 /** True iff we should not allow changes to the front of the buffer
michael@0 117 * (drains or prepends). */
michael@0 118 unsigned freeze_start : 1;
michael@0 119 /** True iff we should not allow changes to the end of the buffer
michael@0 120 * (appends) */
michael@0 121 unsigned freeze_end : 1;
michael@0 122 /** True iff this evbuffer's callbacks are not invoked immediately
michael@0 123 * upon a change in the buffer, but instead are deferred to be invoked
michael@0 124 * from the event_base's loop. Useful for preventing enormous stack
michael@0 125 * overflows when we have mutually recursive callbacks, and for
michael@0 126 * serializing callbacks in a single thread. */
michael@0 127 unsigned deferred_cbs : 1;
michael@0 128 #ifdef WIN32
michael@0 129 /** True iff this buffer is set up for overlapped IO. */
michael@0 130 unsigned is_overlapped : 1;
michael@0 131 #endif
michael@0 132 /** Zero or more EVBUFFER_FLAG_* bits */
michael@0 133 ev_uint32_t flags;
michael@0 134
michael@0 135 /** Used to implement deferred callbacks. */
michael@0 136 struct deferred_cb_queue *cb_queue;
michael@0 137
michael@0 138 /** A reference count on this evbuffer. When the reference count
michael@0 139 * reaches 0, the buffer is destroyed. Manipulated with
michael@0 140 * evbuffer_incref and evbuffer_decref_and_unlock and
michael@0 141 * evbuffer_free. */
michael@0 142 int refcnt;
michael@0 143
michael@0 144 /** A deferred_cb handle to make all of this buffer's callbacks
michael@0 145 * invoked from the event loop. */
michael@0 146 struct deferred_cb deferred;
michael@0 147
michael@0 148 /** A doubly-linked-list of callback functions */
michael@0 149 TAILQ_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;
michael@0 150
michael@0 151 /** The parent bufferevent object this evbuffer belongs to.
michael@0 152 * NULL if the evbuffer stands alone. */
michael@0 153 struct bufferevent *parent;
michael@0 154 };
michael@0 155
michael@0 156 /** A single item in an evbuffer. */
michael@0 157 struct evbuffer_chain {
michael@0 158 /** points to next buffer in the chain */
michael@0 159 struct evbuffer_chain *next;
michael@0 160
michael@0 161 /** total allocation available in the buffer field. */
michael@0 162 size_t buffer_len;
michael@0 163
michael@0 164 /** unused space at the beginning of buffer or an offset into a
michael@0 165 * file for sendfile buffers. */
michael@0 166 ev_off_t misalign;
michael@0 167
michael@0 168 /** Offset into buffer + misalign at which to start writing.
michael@0 169 * In other words, the total number of bytes actually stored
michael@0 170 * in buffer. */
michael@0 171 size_t off;
michael@0 172
michael@0 173 /** Set if special handling is required for this chain */
michael@0 174 unsigned flags;
michael@0 175 #define EVBUFFER_MMAP 0x0001 /**< memory in buffer is mmaped */
michael@0 176 #define EVBUFFER_SENDFILE 0x0002 /**< a chain used for sendfile */
michael@0 177 #define EVBUFFER_REFERENCE 0x0004 /**< a chain with a mem reference */
michael@0 178 #define EVBUFFER_IMMUTABLE 0x0008 /**< read-only chain */
michael@0 179 /** a chain that mustn't be reallocated or freed, or have its contents
michael@0 180 * memmoved, until the chain is un-pinned. */
michael@0 181 #define EVBUFFER_MEM_PINNED_R 0x0010
michael@0 182 #define EVBUFFER_MEM_PINNED_W 0x0020
michael@0 183 #define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W)
michael@0 184 /** a chain that should be freed, but can't be freed until it is
michael@0 185 * un-pinned. */
michael@0 186 #define EVBUFFER_DANGLING 0x0040
michael@0 187
michael@0 188 /** Usually points to the read-write memory belonging to this
michael@0 189 * buffer allocated as part of the evbuffer_chain allocation.
michael@0 190 * For mmap, this can be a read-only buffer and
michael@0 191 * EVBUFFER_IMMUTABLE will be set in flags. For sendfile, it
michael@0 192 * may point to NULL.
michael@0 193 */
michael@0 194 unsigned char *buffer;
michael@0 195 };
michael@0 196
michael@0 197 /* this is currently used by both mmap and sendfile */
michael@0 198 /* TODO(niels): something strange needs to happen for Windows here, I am not
michael@0 199 * sure what that is, but it needs to get looked into.
michael@0 200 */
michael@0 201 struct evbuffer_chain_fd {
michael@0 202 int fd; /**< the fd associated with this chain */
michael@0 203 };
michael@0 204
michael@0 205 /** callback for a reference buffer; lets us know what to do with it when
michael@0 206 * we're done with it. */
michael@0 207 struct evbuffer_chain_reference {
michael@0 208 evbuffer_ref_cleanup_cb cleanupfn;
michael@0 209 void *extra;
michael@0 210 };
michael@0 211
michael@0 212 #define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)
michael@0 213 /** Return a pointer to extra data allocated along with an evbuffer. */
michael@0 214 #define EVBUFFER_CHAIN_EXTRA(t, c) (t *)((struct evbuffer_chain *)(c) + 1)
michael@0 215
michael@0 216 /** Assert that we are holding the lock on an evbuffer */
michael@0 217 #define ASSERT_EVBUFFER_LOCKED(buffer) \
michael@0 218 EVLOCK_ASSERT_LOCKED((buffer)->lock)
michael@0 219
michael@0 220 #define EVBUFFER_LOCK(buffer) \
michael@0 221 do { \
michael@0 222 EVLOCK_LOCK((buffer)->lock, 0); \
michael@0 223 } while (0)
michael@0 224 #define EVBUFFER_UNLOCK(buffer) \
michael@0 225 do { \
michael@0 226 EVLOCK_UNLOCK((buffer)->lock, 0); \
michael@0 227 } while (0)
michael@0 228 #define EVBUFFER_LOCK2(buffer1, buffer2) \
michael@0 229 do { \
michael@0 230 EVLOCK_LOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
michael@0 231 } while (0)
michael@0 232 #define EVBUFFER_UNLOCK2(buffer1, buffer2) \
michael@0 233 do { \
michael@0 234 EVLOCK_UNLOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
michael@0 235 } while (0)
michael@0 236
michael@0 237 /** Increase the reference count of buf by one. */
michael@0 238 void _evbuffer_incref(struct evbuffer *buf);
michael@0 239 /** Increase the reference count of buf by one and acquire the lock. */
michael@0 240 void _evbuffer_incref_and_lock(struct evbuffer *buf);
michael@0 241 /** Pin a single buffer chain using a given flag. A pinned chunk may not be
michael@0 242 * moved or freed until it is unpinned. */
michael@0 243 void _evbuffer_chain_pin(struct evbuffer_chain *chain, unsigned flag);
michael@0 244 /** Unpin a single buffer chain using a given flag. */
michael@0 245 void _evbuffer_chain_unpin(struct evbuffer_chain *chain, unsigned flag);
michael@0 246 /** As evbuffer_free, but requires that we hold a lock on the buffer, and
michael@0 247 * releases the lock before freeing it and the buffer. */
michael@0 248 void _evbuffer_decref_and_unlock(struct evbuffer *buffer);
michael@0 249
michael@0 250 /** As evbuffer_expand, but does not guarantee that the newly allocated memory
michael@0 251 * is contiguous. Instead, it may be split across two or more chunks. */
michael@0 252 int _evbuffer_expand_fast(struct evbuffer *, size_t, int);
michael@0 253
michael@0 254 /** Helper: prepares for a readv/WSARecv call by expanding the buffer to
michael@0 255 * hold enough memory to read 'howmuch' bytes in possibly noncontiguous memory.
michael@0 256 * Sets up the one or two iovecs in 'vecs' to point to the free memory and its
michael@0 257 * extent, and *chainp to point to the first chain that we'll try to read into.
michael@0 258 * Returns the number of vecs used.
michael@0 259 */
michael@0 260 int _evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch,
michael@0 261 struct evbuffer_iovec *vecs, int n_vecs, struct evbuffer_chain ***chainp,
michael@0 262 int exact);
michael@0 263
michael@0 264 /* Helper macro: copies an evbuffer_iovec in ei to a win32 WSABUF in i. */
michael@0 265 #define WSABUF_FROM_EVBUFFER_IOV(i,ei) do { \
michael@0 266 (i)->buf = (ei)->iov_base; \
michael@0 267 (i)->len = (unsigned long)(ei)->iov_len; \
michael@0 268 } while (0)
michael@0 269 /* XXXX the cast above is safe for now, but not if we allow mmaps on win64.
michael@0 270 * See note in buffer_iocp's launch_write function */
michael@0 271
michael@0 272 /** Set the parent bufferevent object for buf to bev */
michael@0 273 void evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev);
michael@0 274
michael@0 275 void evbuffer_invoke_callbacks(struct evbuffer *buf);
michael@0 276
michael@0 277 #ifdef __cplusplus
michael@0 278 }
michael@0 279 #endif
michael@0 280
michael@0 281 #endif /* _EVBUFFER_INTERNAL_H_ */

mercurial