2 * libwebsockets - lws alloc chunk
4 * Copyright (C) 2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-lib-core.h"
23 #include "private-lib-misc-lwsac.h"
26 lws_list_ptr_insert(lws_list_ptr *head, lws_list_ptr *add,
27 lws_list_ptr_sort_func_t sort_func)
29 while (sort_func && *head) {
30 if (sort_func(add, *head) <= 0)
41 lwsac_align(size_t length)
43 size_t align = sizeof(int *);
45 if (length & (align - 1))
46 length += align - (length & (align - 1));
54 return sizeof(struct lwsac);
58 lwsac_get_tail_pos(struct lwsac *lac)
64 lwsac_get_next(struct lwsac *lac)
70 lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size)
75 /* ensure there's a chunk and enough space in it for this name */
77 if (!*head || (*head)->curr->alloc_size - (*head)->curr->ofs < ensure) {
80 alloc = LWSAC_CHUNK_SIZE + sizeof(*chunk);
82 alloc = chunk_size + sizeof(*chunk);
85 * If we get asked for something outside our expectation,
89 if (ensure >= alloc - sizeof(*chunk))
90 alloc = ensure + sizeof(*chunk);
92 chunk = malloc(alloc);
94 lwsl_err("%s: OOM trying to alloc %llud\n", __func__,
95 (unsigned long long)alloc);
101 chunk->total_alloc_size = 0;
102 chunk->total_blocks = 0;
105 (*head)->curr->next = chunk;
107 (*head)->curr = chunk;
108 (*head)->curr->head = *head;
111 chunk->alloc_size = alloc;
115 (*head)->total_alloc_size += alloc;
116 (*head)->total_blocks++;
119 * belabouring the point... ofs is aligned to the platform's
120 * generic struct alignment at the start then
122 (*head)->curr->ofs = sizeof(*chunk);
125 ofs = (*head)->curr->ofs;
127 (*head)->curr->ofs += lwsac_align(ensure);
128 if ((*head)->curr->ofs >= (*head)->curr->alloc_size)
129 (*head)->curr->ofs = (*head)->curr->alloc_size;
131 return (char *)(*head)->curr + ofs;
135 lwsac_use_zero(struct lwsac **head, size_t ensure, size_t chunk_size)
137 void *p = lwsac_use(head, ensure, chunk_size);
140 memset(p, 0, ensure);
146 lwsac_use_zeroed(struct lwsac **head, size_t ensure, size_t chunk_size)
148 void *r = lwsac_use(head, ensure, chunk_size);
151 memset(r, 0, ensure);
157 lwsac_free(struct lwsac **head)
159 struct lwsac *it = *head;
162 lwsl_debug("%s: head %p\n", __func__, *head);
165 struct lwsac *tmp = it->next;
173 lwsac_info(struct lwsac *head)
176 lwsl_debug("%s: empty\n", __func__);
178 lwsl_debug("%s: lac %p: %dKiB in %d blocks\n", __func__, head,
179 (int)(head->total_alloc_size >> 10), head->total_blocks);
183 lwsac_total_alloc(struct lwsac *head)
185 return head->total_alloc_size;
189 lwsac_reference(struct lwsac *head)
192 lwsl_debug("%s: head %p: (det %d) refcount -> %d\n",
193 __func__, head, head->detached, head->refcount);
197 lwsac_unreference(struct lwsac **head)
202 if (!(*head)->refcount)
203 lwsl_warn("%s: refcount going below zero\n", __func__);
207 lwsl_debug("%s: head %p: (det %d) refcount -> %d\n",
208 __func__, *head, (*head)->detached, (*head)->refcount);
210 if ((*head)->detached && !(*head)->refcount) {
211 lwsl_debug("%s: head %p: FREED\n", __func__, *head);
217 lwsac_detach(struct lwsac **head)
219 (*head)->detached = 1;
220 if (!(*head)->refcount) {
221 lwsl_debug("%s: head %p: FREED\n", __func__, *head);
224 lwsl_debug("%s: head %p: refcount %d: Marked as detached\n",
225 __func__, *head, (*head)->refcount);