1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_cistruct lws_dsh_search { 28d4afb5ceSopenharmony_ci size_t required; 29d4afb5ceSopenharmony_ci int kind; 30d4afb5ceSopenharmony_ci lws_dsh_obj_t *best; 31d4afb5ceSopenharmony_ci lws_dsh_t *dsh; 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_ci lws_dsh_t *already_checked; 34d4afb5ceSopenharmony_ci lws_dsh_t *this_dsh; 35d4afb5ceSopenharmony_ci}; 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_cistatic int 38d4afb5ceSopenharmony_ci_lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, 39d4afb5ceSopenharmony_ci const void *src2, size_t size2, lws_dll2_t *replace); 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_cistatic size_t 42d4afb5ceSopenharmony_cilws_dsh_align(size_t length) 43d4afb5ceSopenharmony_ci{ 44d4afb5ceSopenharmony_ci size_t align = sizeof(int *); 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci if (length & (align - 1)) 47d4afb5ceSopenharmony_ci length += align - (length & (align - 1)); 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci return length; 50d4afb5ceSopenharmony_ci} 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_cilws_dsh_t * 53d4afb5ceSopenharmony_cilws_dsh_create(lws_dll2_owner_t *owner, size_t buf_len, int count_kinds) 54d4afb5ceSopenharmony_ci{ 55d4afb5ceSopenharmony_ci size_t oha_len = sizeof(lws_dsh_obj_head_t) * (unsigned int)(++count_kinds); 56d4afb5ceSopenharmony_ci lws_dsh_obj_t *obj; 57d4afb5ceSopenharmony_ci lws_dsh_t *dsh; 58d4afb5ceSopenharmony_ci int n; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci assert(buf_len); 61d4afb5ceSopenharmony_ci assert(count_kinds > 1); 62d4afb5ceSopenharmony_ci assert(buf_len > sizeof(lws_dsh_t) + oha_len); 63d4afb5ceSopenharmony_ci buf_len += 64; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci dsh = lws_malloc(sizeof(lws_dsh_t) + buf_len + oha_len, __func__); 66d4afb5ceSopenharmony_ci if (!dsh) 67d4afb5ceSopenharmony_ci return NULL; 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci /* set convenience pointers to the overallocated parts */ 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci dsh->oha = (lws_dsh_obj_head_t *)&dsh[1]; 72d4afb5ceSopenharmony_ci dsh->buf = ((uint8_t *)dsh->oha) + oha_len; 73d4afb5ceSopenharmony_ci dsh->count_kinds = count_kinds; 74d4afb5ceSopenharmony_ci dsh->buffer_size = buf_len; 75d4afb5ceSopenharmony_ci dsh->being_destroyed = 0; 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ci /* clear down the obj heads array */ 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci memset(dsh->oha, 0, oha_len); 80d4afb5ceSopenharmony_ci for (n = 0; n < count_kinds; n++) { 81d4afb5ceSopenharmony_ci dsh->oha[n].kind = n; 82d4afb5ceSopenharmony_ci dsh->oha[n].total_size = 0; 83d4afb5ceSopenharmony_ci } 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci /* initially the whole buffer is on the free kind (0) list */ 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci obj = (lws_dsh_obj_t *)dsh->buf; 88d4afb5ceSopenharmony_ci memset(obj, 0, sizeof(*obj)); 89d4afb5ceSopenharmony_ci obj->asize = buf_len - sizeof(*obj); 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci lws_dll2_add_head(&obj->list, &dsh->oha[0].owner); 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci dsh->locally_free = obj->asize; 94d4afb5ceSopenharmony_ci dsh->locally_in_use = 0; 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci lws_dll2_clear(&dsh->list); 97d4afb5ceSopenharmony_ci if (owner) 98d4afb5ceSopenharmony_ci lws_dll2_add_head(&dsh->list, owner); 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci // lws_dsh_describe(dsh, "post-init"); 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci return dsh; 103d4afb5ceSopenharmony_ci} 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_cistatic int 106d4afb5ceSopenharmony_cisearch_best_free(struct lws_dll2 *d, void *user) 107d4afb5ceSopenharmony_ci{ 108d4afb5ceSopenharmony_ci struct lws_dsh_search *s = (struct lws_dsh_search *)user; 109d4afb5ceSopenharmony_ci lws_dsh_obj_t *obj = lws_container_of(d, lws_dsh_obj_t, list); 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_ci lwsl_debug("%s: obj %p, asize %zu (req %zu)\n", __func__, obj, 112d4afb5ceSopenharmony_ci obj->asize, s->required); 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci if (obj->asize >= s->required && 115d4afb5ceSopenharmony_ci (!s->best || obj->asize < s->best->asize)) { 116d4afb5ceSopenharmony_ci s->best = obj; 117d4afb5ceSopenharmony_ci s->dsh = s->this_dsh; 118d4afb5ceSopenharmony_ci } 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci return 0; 121d4afb5ceSopenharmony_ci} 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_civoid 124d4afb5ceSopenharmony_cilws_dsh_destroy(lws_dsh_t **pdsh) 125d4afb5ceSopenharmony_ci{ 126d4afb5ceSopenharmony_ci lws_dsh_t *dsh = *pdsh; 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci if (!dsh) 129d4afb5ceSopenharmony_ci return; 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci dsh->being_destroyed = 1; 132d4afb5ceSopenharmony_ci 133d4afb5ceSopenharmony_ci lws_dll2_remove(&dsh->list); 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci /* everything else is in one heap allocation */ 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci lws_free_set_NULL(*pdsh); 138d4afb5ceSopenharmony_ci} 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_cisize_t 141d4afb5ceSopenharmony_cilws_dsh_get_size(struct lws_dsh *dsh, int kind) 142d4afb5ceSopenharmony_ci{ 143d4afb5ceSopenharmony_ci kind++; 144d4afb5ceSopenharmony_ci assert(kind < dsh->count_kinds); 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci return dsh->oha[kind].total_size; 147d4afb5ceSopenharmony_ci} 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_cistatic int 150d4afb5ceSopenharmony_ci_lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, 151d4afb5ceSopenharmony_ci const void *src2, size_t size2, lws_dll2_t *replace) 152d4afb5ceSopenharmony_ci{ 153d4afb5ceSopenharmony_ci size_t asize = sizeof(lws_dsh_obj_t) + lws_dsh_align(size1 + size2); 154d4afb5ceSopenharmony_ci struct lws_dsh_search s; 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci assert(kind >= 0); 157d4afb5ceSopenharmony_ci kind++; 158d4afb5ceSopenharmony_ci assert(!dsh || kind < dsh->count_kinds); 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci /* 161d4afb5ceSopenharmony_ci * Search our free list looking for the smallest guy who will fit 162d4afb5ceSopenharmony_ci * what we want to allocate 163d4afb5ceSopenharmony_ci */ 164d4afb5ceSopenharmony_ci s.required = asize; 165d4afb5ceSopenharmony_ci s.kind = kind; 166d4afb5ceSopenharmony_ci s.best = NULL; 167d4afb5ceSopenharmony_ci s.already_checked = NULL; 168d4afb5ceSopenharmony_ci s.this_dsh = dsh; 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci if (dsh && !dsh->being_destroyed) 171d4afb5ceSopenharmony_ci lws_dll2_foreach_safe(&dsh->oha[0].owner, &s, search_best_free); 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci if (!s.best) { 174d4afb5ceSopenharmony_ci lwsl_notice("%s: no buffer has space\n", __func__); 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci return 1; 177d4afb5ceSopenharmony_ci } 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci /* anything coming out of here must be aligned */ 180d4afb5ceSopenharmony_ci assert(!(((unsigned long)s.best) & (sizeof(int *) - 1))); 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci if (s.best->asize < asize + (2 * sizeof(*s.best))) { 183d4afb5ceSopenharmony_ci /* 184d4afb5ceSopenharmony_ci * Exact fit, or close enough we can't / don't want to have to 185d4afb5ceSopenharmony_ci * track the little bit of free area that would be left. 186d4afb5ceSopenharmony_ci * 187d4afb5ceSopenharmony_ci * Move the object from the free list to the oha of the 188d4afb5ceSopenharmony_ci * desired kind 189d4afb5ceSopenharmony_ci */ 190d4afb5ceSopenharmony_ci lws_dll2_remove(&s.best->list); 191d4afb5ceSopenharmony_ci s.best->dsh = s.dsh; 192d4afb5ceSopenharmony_ci s.best->kind = kind; 193d4afb5ceSopenharmony_ci s.best->size = size1 + size2; 194d4afb5ceSopenharmony_ci memcpy(&s.best[1], src1, size1); 195d4afb5ceSopenharmony_ci if (src2) 196d4afb5ceSopenharmony_ci memcpy((uint8_t *)&s.best[1] + size1, src2, size2); 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci if (replace) { 199d4afb5ceSopenharmony_ci s.best->list.prev = replace->prev; 200d4afb5ceSopenharmony_ci s.best->list.next = replace->next; 201d4afb5ceSopenharmony_ci s.best->list.owner = replace->owner; 202d4afb5ceSopenharmony_ci if (replace->prev) 203d4afb5ceSopenharmony_ci replace->prev->next = &s.best->list; 204d4afb5ceSopenharmony_ci if (replace->next) 205d4afb5ceSopenharmony_ci replace->next->prev = &s.best->list; 206d4afb5ceSopenharmony_ci } else 207d4afb5ceSopenharmony_ci if (dsh) { 208d4afb5ceSopenharmony_ci assert(!(((unsigned long)(intptr_t)(s.best)) & (sizeof(int *) - 1))); 209d4afb5ceSopenharmony_ci lws_dll2_add_tail(&s.best->list, &dsh->oha[kind].owner); 210d4afb5ceSopenharmony_ci } 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci assert(s.dsh->locally_free >= s.best->asize); 213d4afb5ceSopenharmony_ci s.dsh->locally_free -= s.best->asize; 214d4afb5ceSopenharmony_ci s.dsh->locally_in_use += s.best->asize; 215d4afb5ceSopenharmony_ci dsh->oha[kind].total_size += s.best->asize; 216d4afb5ceSopenharmony_ci assert(s.dsh->locally_in_use <= s.dsh->buffer_size); 217d4afb5ceSopenharmony_ci } else { 218d4afb5ceSopenharmony_ci lws_dsh_obj_t *obj; 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci /* 221d4afb5ceSopenharmony_ci * Free area was oversize enough that we need to split it. 222d4afb5ceSopenharmony_ci * 223d4afb5ceSopenharmony_ci * Leave the first part of the free area where it is and 224d4afb5ceSopenharmony_ci * reduce its extent by our asize. Use the latter part of 225d4afb5ceSopenharmony_ci * the original free area as the allocation. 226d4afb5ceSopenharmony_ci */ 227d4afb5ceSopenharmony_ci lwsl_debug("%s: splitting... free reduce %zu -> %zu\n", 228d4afb5ceSopenharmony_ci __func__, s.best->asize, s.best->asize - asize); 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci s.best->asize -= asize; 231d4afb5ceSopenharmony_ci 232d4afb5ceSopenharmony_ci /* latter part becomes new object */ 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci obj = (lws_dsh_obj_t *)(((uint8_t *)s.best) + lws_dsh_align(s.best->asize)); 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci lws_dll2_clear(&obj->list); 237d4afb5ceSopenharmony_ci obj->dsh = s.dsh; 238d4afb5ceSopenharmony_ci obj->kind = kind; 239d4afb5ceSopenharmony_ci obj->size = size1 + size2; 240d4afb5ceSopenharmony_ci obj->asize = asize; 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci memcpy(&obj[1], src1, size1); 243d4afb5ceSopenharmony_ci if (src2) 244d4afb5ceSopenharmony_ci memcpy((uint8_t *)&obj[1] + size1, src2, size2); 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci if (replace) { 247d4afb5ceSopenharmony_ci s.best->list.prev = replace->prev; 248d4afb5ceSopenharmony_ci s.best->list.next = replace->next; 249d4afb5ceSopenharmony_ci s.best->list.owner = replace->owner; 250d4afb5ceSopenharmony_ci if (replace->prev) 251d4afb5ceSopenharmony_ci replace->prev->next = &s.best->list; 252d4afb5ceSopenharmony_ci if (replace->next) 253d4afb5ceSopenharmony_ci replace->next->prev = &s.best->list; 254d4afb5ceSopenharmony_ci } else 255d4afb5ceSopenharmony_ci if (dsh) { 256d4afb5ceSopenharmony_ci assert(!(((unsigned long)(intptr_t)(obj)) & (sizeof(int *) - 1))); 257d4afb5ceSopenharmony_ci lws_dll2_add_tail(&obj->list, &dsh->oha[kind].owner); 258d4afb5ceSopenharmony_ci } 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci assert(s.dsh->locally_free >= asize); 261d4afb5ceSopenharmony_ci s.dsh->locally_free -= asize; 262d4afb5ceSopenharmony_ci s.dsh->locally_in_use += asize; 263d4afb5ceSopenharmony_ci dsh->oha[kind].total_size += asize; 264d4afb5ceSopenharmony_ci assert(s.dsh->locally_in_use <= s.dsh->buffer_size); 265d4afb5ceSopenharmony_ci } 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci // lws_dsh_describe(dsh, "post-alloc"); 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci return 0; 270d4afb5ceSopenharmony_ci} 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ciint 273d4afb5ceSopenharmony_cilws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, 274d4afb5ceSopenharmony_ci const void *src2, size_t size2) 275d4afb5ceSopenharmony_ci{ 276d4afb5ceSopenharmony_ci return _lws_dsh_alloc_tail(dsh, kind, src1, size1, src2, size2, NULL); 277d4afb5ceSopenharmony_ci} 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_cistatic int 280d4afb5ceSopenharmony_cibuf_compare(const lws_dll2_t *d, const lws_dll2_t *i) 281d4afb5ceSopenharmony_ci{ 282d4afb5ceSopenharmony_ci return (int)lws_ptr_diff(d, i); 283d4afb5ceSopenharmony_ci} 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_civoid 286d4afb5ceSopenharmony_cilws_dsh_free(void **pobj) 287d4afb5ceSopenharmony_ci{ 288d4afb5ceSopenharmony_ci lws_dsh_obj_t *_o = (lws_dsh_obj_t *)((uint8_t *)(*pobj) - sizeof(*_o)), 289d4afb5ceSopenharmony_ci *_o2; 290d4afb5ceSopenharmony_ci lws_dsh_t *dsh = _o->dsh; 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci /* anything coming out of here must be aligned */ 293d4afb5ceSopenharmony_ci assert(!(((unsigned long)_o) & (sizeof(int *) - 1))); 294d4afb5ceSopenharmony_ci 295d4afb5ceSopenharmony_ci /* 296d4afb5ceSopenharmony_ci * Remove the object from its list and place on the free list of the 297d4afb5ceSopenharmony_ci * dsh the buffer space belongs to 298d4afb5ceSopenharmony_ci */ 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ci lws_dll2_remove(&_o->list); 301d4afb5ceSopenharmony_ci *pobj = NULL; 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ci assert(dsh->locally_in_use >= _o->asize); 304d4afb5ceSopenharmony_ci dsh->locally_free += _o->asize; 305d4afb5ceSopenharmony_ci dsh->locally_in_use -= _o->asize; 306d4afb5ceSopenharmony_ci dsh->oha[_o->kind].total_size -= _o->asize; /* account for usage by kind */ 307d4afb5ceSopenharmony_ci assert(dsh->locally_in_use <= dsh->buffer_size); 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci /* 310d4afb5ceSopenharmony_ci * The free space list is sorted in buffer address order, so detecting 311d4afb5ceSopenharmony_ci * coalescing opportunities is cheap. Because the free list should be 312d4afb5ceSopenharmony_ci * continuously tending to reduce by coalescing, the sorting should not 313d4afb5ceSopenharmony_ci * be expensive to maintain. 314d4afb5ceSopenharmony_ci */ 315d4afb5ceSopenharmony_ci _o->size = 0; /* not meaningful when on free list */ 316d4afb5ceSopenharmony_ci lws_dll2_add_sorted(&_o->list, &_o->dsh->oha[0].owner, buf_compare); 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci /* First check for already-free block at the end we can subsume. 319d4afb5ceSopenharmony_ci * Because the free list is sorted, if there is such a guy he is 320d4afb5ceSopenharmony_ci * already our list.next */ 321d4afb5ceSopenharmony_ci 322d4afb5ceSopenharmony_ci _o2 = (lws_dsh_obj_t *)_o->list.next; 323d4afb5ceSopenharmony_ci if (_o2 && (uint8_t *)_o + _o->asize == (uint8_t *)_o2) { 324d4afb5ceSopenharmony_ci /* 325d4afb5ceSopenharmony_ci * since we are freeing _obj, we can coalesce with a 326d4afb5ceSopenharmony_ci * free area immediately ahead of it 327d4afb5ceSopenharmony_ci * 328d4afb5ceSopenharmony_ci * [ _o (being freed) ][ _o2 (free) ] -> [ larger _o ] 329d4afb5ceSopenharmony_ci */ 330d4afb5ceSopenharmony_ci _o->asize += _o2->asize; 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci /* guy next to us was absorbed into us */ 333d4afb5ceSopenharmony_ci lws_dll2_remove(&_o2->list); 334d4afb5ceSopenharmony_ci } 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_ci /* Then check if we can be subsumed by a free block behind us. 337d4afb5ceSopenharmony_ci * Because the free list is sorted, if there is such a guy he is 338d4afb5ceSopenharmony_ci * already our list.prev */ 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci _o2 = (lws_dsh_obj_t *)_o->list.prev; 341d4afb5ceSopenharmony_ci if (_o2 && (uint8_t *)_o2 + _o2->asize == (uint8_t *)_o) { 342d4afb5ceSopenharmony_ci /* 343d4afb5ceSopenharmony_ci * since we are freeing obj, we can coalesce it with 344d4afb5ceSopenharmony_ci * the previous free area that abuts it 345d4afb5ceSopenharmony_ci * 346d4afb5ceSopenharmony_ci * [ _o2 (free) ][ _o (being freed) ] -> [ larger _o2 ] 347d4afb5ceSopenharmony_ci */ 348d4afb5ceSopenharmony_ci _o2->asize += _o->asize; 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci /* we were absorbed! */ 351d4afb5ceSopenharmony_ci lws_dll2_remove(&_o->list); 352d4afb5ceSopenharmony_ci } 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci // lws_dsh_describe(dsh, "post-alloc"); 355d4afb5ceSopenharmony_ci} 356d4afb5ceSopenharmony_ci 357d4afb5ceSopenharmony_ciint 358d4afb5ceSopenharmony_cilws_dsh_get_head(lws_dsh_t *dsh, int kind, void **obj, size_t *size) 359d4afb5ceSopenharmony_ci{ 360d4afb5ceSopenharmony_ci lws_dsh_obj_t *_obj; 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci if (!dsh) 363d4afb5ceSopenharmony_ci return 1; 364d4afb5ceSopenharmony_ci 365d4afb5ceSopenharmony_ci _obj = (lws_dsh_obj_t *)lws_dll2_get_head(&dsh->oha[kind + 1].owner); 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci if (!_obj) { 368d4afb5ceSopenharmony_ci *obj = 0; 369d4afb5ceSopenharmony_ci *size = 0; 370d4afb5ceSopenharmony_ci 371d4afb5ceSopenharmony_ci return 1; /* there is no head */ 372d4afb5ceSopenharmony_ci } 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci *obj = (void *)(&_obj[1]); 375d4afb5ceSopenharmony_ci *size = _obj->size; 376d4afb5ceSopenharmony_ci 377d4afb5ceSopenharmony_ci /* anything coming out of here must be aligned */ 378d4afb5ceSopenharmony_ci assert(!(((unsigned long)(intptr_t)(*obj)) & (sizeof(int *) - 1))); 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci return 0; /* we returned the head */ 381d4afb5ceSopenharmony_ci} 382d4afb5ceSopenharmony_ci 383d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS) 384d4afb5ceSopenharmony_ci 385d4afb5ceSopenharmony_cistatic int 386d4afb5ceSopenharmony_cidescribe_kind(struct lws_dll2 *d, void *user) 387d4afb5ceSopenharmony_ci{ 388d4afb5ceSopenharmony_ci lws_dsh_obj_t *obj = lws_container_of(d, lws_dsh_obj_t, list); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci lwsl_info(" _obj %p - %p, dsh %p, size %zu, asize %zu\n", 391d4afb5ceSopenharmony_ci obj, (uint8_t *)obj + obj->asize, 392d4afb5ceSopenharmony_ci obj->dsh, obj->size, obj->asize); 393d4afb5ceSopenharmony_ci 394d4afb5ceSopenharmony_ci return 0; 395d4afb5ceSopenharmony_ci} 396d4afb5ceSopenharmony_ci 397d4afb5ceSopenharmony_civoid 398d4afb5ceSopenharmony_cilws_dsh_describe(lws_dsh_t *dsh, const char *desc) 399d4afb5ceSopenharmony_ci{ 400d4afb5ceSopenharmony_ci int n = 0; 401d4afb5ceSopenharmony_ci 402d4afb5ceSopenharmony_ci lwsl_info("%s: dsh %p, bufsize %zu, kinds %d, lf: %zu, liu: %zu, %s\n", 403d4afb5ceSopenharmony_ci __func__, dsh, dsh->buffer_size, dsh->count_kinds, 404d4afb5ceSopenharmony_ci dsh->locally_free, dsh->locally_in_use, desc); 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci for (n = 0; n < dsh->count_kinds; n++) { 407d4afb5ceSopenharmony_ci lwsl_info(" Kind %d:\n", n); 408d4afb5ceSopenharmony_ci lws_dll2_foreach_safe(&dsh->oha[n].owner, dsh, describe_kind); 409d4afb5ceSopenharmony_ci } 410d4afb5ceSopenharmony_ci} 411d4afb5ceSopenharmony_ci#endif 412