1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25 /* 26 * lws_dsh (Disordered Shared Heap) is an opaque abstraction supporting a single 27 * linear buffer (overallocated at end of the lws_dsh_t) which may contain 28 * multiple kinds of packets that are retired out of order, and tracked by kind. 29 * 30 * Each kind of packet has an lws_dll2 list of its kind of packets and acts as 31 * a FIFO; packets of a particular type are always retired in order. But there 32 * is no requirement about the order types are retired matching the original 33 * order they arrived. 34 * 35 * Gaps are tracked as just another kind of "packet" list. 36 * 37 * "allocations" (including gaps) are prepended by an lws_dsh_object_t. 38 * 39 * dsh may themselves be on an lws_dll2_owner list, and under memory pressure 40 * allocate into other buffers on the list. 41 * 42 * All management structures exist inside the allocated buffer. 43 */ 44 45 /** 46 * lws_dsh_create() - Allocate a DSH buffer 47 * 48 * \param owner: the owning list this dsh belongs on, or NULL if standalone 49 * \param buffer_size: the allocation in bytes 50 * \param count_kinds: how many separately-tracked fifos use the buffer 51 * 52 * This makes a single heap allocation that includes internal tracking objects 53 * in the buffer. Sub-allocated objects are bound to a "kind" index and 54 * managed via a FIFO for each kind. 55 * 56 * Every "kind" of allocation shares the same buffer space. 57 * 58 * Multiple buffers may be bound together in an lws_dll2 list, and if an 59 * allocation cannot be satisfied by the local buffer, space can be borrowed 60 * from other dsh in the same list (the local dsh FIFO tracks these "foreign" 61 * allocations as if they were local). 62 * 63 * Returns an opaque pointer to the dsh, or NULL if allocation failed. 64 */ 65 LWS_VISIBLE LWS_EXTERN struct lws_dsh * 66 lws_dsh_create(lws_dll2_owner_t *owner, size_t buffer_size, int count_kinds); 67 68 /** 69 * lws_dsh_destroy() - Destroy a DSH buffer 70 * 71 * \param pdsh: pointer to the dsh pointer 72 * 73 * Deallocates the DSH and sets *pdsh to NULL. 74 * 75 * Before destruction, any foreign buffer usage on the part of this dsh are 76 * individually freed. All dsh on the same list are walked and checked if they 77 * have their own foreign allocations on the dsh buffer being destroyed. If so, 78 * it attempts to migrate the allocation to a dsh that is not currently being 79 * destroyed. If all else fails (basically the buffer memory is being shrunk) 80 * unmigratable objects are cleanly destroyed. 81 */ 82 LWS_VISIBLE LWS_EXTERN void 83 lws_dsh_destroy(struct lws_dsh **pdsh); 84 85 /** 86 * lws_dsh_alloc_tail() - make a suballocation inside a dsh 87 * 88 * \param dsh: the dsh tracking the allocation 89 * \param kind: the kind of allocation 90 * \param src1: the first source data to copy 91 * \param size1: the size of the first source data 92 * \param src2: the second source data to copy (after the first), or NULL 93 * \param size2: the size of the second source data 94 * 95 * Allocates size1 + size2 bytes in a dsh (it prefers the given dsh but will 96 * borrow space from other dsh on the same list if necessary) and copies size1 97 * bytes into it from src1, followed by size2 bytes from src2 if src2 isn't 98 * NULL. The actual suballocation is a bit larger because of alignment and a 99 * prepended management header. 100 * 101 * The suballocation is added to the kind-specific FIFO at the tail. 102 */ 103 LWS_VISIBLE LWS_EXTERN int 104 lws_dsh_alloc_tail(struct lws_dsh *dsh, int kind, const void *src1, 105 size_t size1, const void *src2, size_t size2); 106 107 /** 108 * lws_dsh_free() - free a suballocation from the dsh 109 * 110 * \param obj: a pointer to a void * that pointed to the allocated payload 111 * 112 * This returns the space used by \p obj in the dsh buffer to the free list 113 * of the dsh the allocation came from. 114 */ 115 LWS_VISIBLE LWS_EXTERN void 116 lws_dsh_free(void **obj); 117 118 LWS_VISIBLE LWS_EXTERN size_t 119 lws_dsh_get_size(struct lws_dsh *dsh, int kind); 120 121 /** 122 * lws_dsh_get_head() - get the head allocation inside the dsh 123 * 124 * \param dsh: the dsh tracking the allocation 125 * \param kind: the kind of allocation 126 * \param obj: pointer to a void * to be set to the payload 127 * \param size: set to the size of the allocation 128 * 129 * This gets the "next" object in the kind FIFO for the dsh, and returns 0 if 130 * any. If none, returns nonzero. 131 * 132 * This is nondestructive of the fifo or the payload. Use lws_dsh_free on 133 * obj to remove the entry from the kind fifo and return the payload to the 134 * free list. 135 */ 136 LWS_VISIBLE LWS_EXTERN int 137 lws_dsh_get_head(struct lws_dsh *dsh, int kind, void **obj, size_t *size); 138 139 /** 140 * lws_dsh_describe() - DEBUG BUILDS ONLY dump the dsh to the logs 141 * 142 * \param dsh: the dsh to dump 143 * \param desc: text that appears at the top of the dump 144 * 145 * Useful information for debugging lws_dsh 146 */ 147 LWS_VISIBLE LWS_EXTERN void 148 lws_dsh_describe(struct lws_dsh *dsh, const char *desc); 149