Update Files

This commit is contained in:
2025-01-22 17:22:38 +01:00
parent 89b9349629
commit 4c5e729485
5132 changed files with 1195369 additions and 0 deletions

View File

@ -0,0 +1,148 @@
## LWS Allocated Chunks
![lwsac flow](/doc-assets/lwsac.svg)
These apis provide a way to manage a linked-list of allocated chunks...
[ HEAD alloc ] -> [ next alloc ] -> [ next alloc ] -> [ curr alloc ]
... and sub-allocate trivially inside the chunks. These sub-allocations are
not tracked by lwsac at all, there is a "used" high-water mark for each chunk
that's simply advanced by the amount sub-allocated. If the allocation size
matches the platform pointer alignment, there is zero overhead to sub-allocate
(otherwise the allocation is padded to the next platform pointer alignment
automatically).
If you have an unknown amount of relatively little things to allocate, including
strings or other unstructured data, lwsac is significantly more efficient than
individual allocations using malloc or so.
[lwsac full public api](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-lwsac.h)
## lwsac_use() api
```
/**
* lwsac_use - allocate / use some memory from a lwsac
*
* \param head: pointer to the lwsac list object
* \param ensure: the number of bytes we want to use
* \param chunk_size: 0, or the size of the chunk to (over)allocate if
* what we want won't fit in the current tail chunk. If
* 0, the default value of 4000 is used. If ensure is
* larger, it is used instead.
*
* This also serves to init the lwsac if *head is NULL. Basically it does
* whatever is necessary to return you a pointer to ensure bytes of memory
* reserved for the caller.
*
* Returns NULL if OOM.
*/
LWS_VISIBLE LWS_EXTERN void *
lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size);
```
When you make an sub-allocation using `lwsac_use()`, you can either
set the `chunk_size` arg to zero, defaulting to 4000, or a specific chunk size.
In the event the requested sub-allocation exceeds the chunk size, the chunk
size is increated to match it automatically for this allocation only.
Subsequent `lwsac_use()` calls will advance internal pointers to use up the
remaining space inside the current chunk if possible; if not enough remaining
space it is skipped, a new allocation is chained on and the request pointed to
there.
Lwsac does not store information about sub-allocations. There is really zero
overhead for individual sub-allocations (unless their size is not
pointer-aligned, in which case the actual amount sub-allocated is rounded up to
the next pointer alignment automatically). For structs, which are pointer-
aligned naturally, and a chunk size relatively large for the sub-allocation
size, lwsac is extremely efficient even for huge numbers of small allocations.
This makes lwsac very effective when the total amount of allocation needed is
not known at the start and may be large... it will simply add on chunks to cope
with whatever happens.
## lwsac_free() api
```
/**
* lwsac_free - deallocate all chunks in the lwsac and set head NULL
*
* \param head: pointer to the lwsac list object
*
* This deallocates all chunks in the lwsac, then sets *head to NULL. All
* lwsac_use() pointers are invalidated in one hit without individual frees.
*/
LWS_VISIBLE LWS_EXTERN void
lwsac_free(struct lwsac **head);
```
When you are finished with the lwsac, you simply free the chain of allocated
chunks using lwsac_free() on the lwsac head. There's no tracking or individual
destruction of suballocations - the whole chain of chunks the suballocations
live in are freed and invalidated all together.
If the structs stored in the lwsac allocated things **outside** the lwsac, then the
user must unwind through them and perform the frees. But the idea of lwsac is
things stored in the lwsac also suballocate into the lwsac, and point into the
lwsac if they need to, avoiding any need to visit them during destroy. It's
like clearing up after a kids' party by gathering up a disposable tablecloth:
no matter what was left on the table, it's all gone in one step.
## `lws_list_ptr` helpers
```
/* sort may be NULL if you don't care about order */
LWS_VISIBLE LWS_EXTERN void
lws_list_ptr_insert(lws_list_ptr *phead, lws_list_ptr *add,
lws_list_ptr_sort_func_t sort);
```
A common pattern needed with sub-allocated structs is they are on one or more
linked-list. To make that simple to do cleanly, `lws_list...` apis are provided
along with a generic insertion function that can take a sort callback. These
allow a struct to participate on multiple linked-lists simultaneously.
## common const string and blob folding
In some cases the input to be stored in the lwsac may repeat the same tokens
multiple times... if the pattern is to store the string or blob in the lwsac
and then point to it, you can make use of a helper api
```
uint8_t *
lwsac_scan_extant(struct lwsac *head, uint8_t *find, size_t len, int nul);
```
This lets you check in all previous used parts of the lwsac for the same
string or blob, plus optionally a terminal NUL afterwards. If not found,
it returns `NULL` and you can copy it into the lwsac as usual. If it is
found, a pointer is returned, and you can use this directly without copying
the string or blob in again.
## optimizations to minimize overhead
If the lwsac will persist in the system for some time, it's desirable to reduce
the memory needed as overhead. Overhead is created
- once per chunk... in addition to the malloc overhead, there's an lwsac
chunk header of 2 x pointers and 2 x size_t
- at the unused part at the end that was allocated but not used
A good strategy is to make the initial allocation reflect the minimum expected
size of the overall lwsac in one hit. Then use a chunk size that is a tradeoff
between the number of chunks that might be needed and the fact that on average,
you can expect to waste half a chunk. For example if the storage is typically
between 4K - 6K, you could allocate 4K or 4.5K for the first chunk and then fill
in using 256 or 512 byte chunks.
You can measure the overhead in an lwsac using `lwsac_total_overhead()`.
The lwsac apis look first in the unused part of previous chunks, if any, and
will place new allocations there preferentially if they fit. This helps for the
case lwsac was forced to allocate a new chunk because you asked for something
large, while there was actually significant free space left in the old chunk,
just not enough for that particular allocation. Subsequent lwsac use can then
"backfill" smaller things there to make best use of allocated space.

View File

@ -0,0 +1,218 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
#include "private-lib-core.h"
#include "private-lib-misc-lwsac.h"
/*
* Helper for caching a file in memory in a lac, but also to check at intervals
* no less than 5s if the file is still fresh.
*
* Set *cache to NULL the first time before calling.
*
* You should call this each time before using the cache... if it's
*
* - less than 5s since the last freshness check, and
* - the file is already in memory
*
* it just returns with *cache left alone; this costs very little. You should
* call `lwsac_use_cached_file_start()` and `lwsac_use_cached_file_end()`
* to lock the cache against deletion while you are using it.
*
* If it's
*
* - at least 5s since the last freshness check, and
* - the file timestamp has changed
*
* then
*
* - the file is reloaded into a new lac and *cache set to that
*
* - the old cache lac, if any, is detached (so it will be freed when its
* reference count reaches zero, or immediately if nobody has it)
*
* Note the call can fail due to OOM or filesystem issue at any time.
*
*
* After the LAC header there is stored a `struct cached_file_info` and then
* the raw file contents. *
*
* [LAC header]
* [struct cached_file_info]
* [file contents] <--- *cache is set to here
*
* The api returns a lwsac_cached_file_t type offset to point to the file
* contents. Helpers for reference counting and freeing are also provided
* that take that type and know how to correct it back to operate on the LAC.
*/
#define cache_file_to_lac(c) ((struct lwsac *)((char *)c - \
sizeof(struct cached_file_info) - \
sizeof(struct lwsac_head) - \
sizeof(struct lwsac)))
void
lwsac_use_cached_file_start(lwsac_cached_file_t cache)
{
struct lwsac *lac = cache_file_to_lac(cache);
struct lwsac_head *lachead = (struct lwsac_head *)&lac->head[1];
lachead->refcount++;
// lwsl_debug("%s: html refcount: %d\n", __func__, lachead->refcount);
}
void
lwsac_use_cached_file_end(lwsac_cached_file_t *cache)
{
struct lwsac *lac;
struct lwsac_head *lachead;
if (!cache || !*cache)
return;
lac = cache_file_to_lac(*cache);
lachead = (struct lwsac_head *)&lac->head[1];
if (!lachead->refcount)
lwsl_err("%s: html refcount zero on entry\n", __func__);
if (lachead->refcount && !--lachead->refcount && lachead->detached) {
*cache = NULL; /* not usable any more */
lwsac_free(&lac);
}
}
void
lwsac_use_cached_file_detach(lwsac_cached_file_t *cache)
{
struct lwsac *lac = cache_file_to_lac(*cache);
struct lwsac_head *lachead = NULL;
if (lac) {
lachead = (struct lwsac_head *)&lac->head[1];
lachead->detached = 1;
if (lachead->refcount)
return;
}
*cache = NULL;
lwsac_free(&lac);
}
int
lwsac_cached_file(const char *filepath, lwsac_cached_file_t *cache, size_t *len)
{
struct cached_file_info *info = NULL;
lwsac_cached_file_t old = *cache;
struct lwsac *lac = NULL;
time_t t = time(NULL);
unsigned char *a;
struct stat s;
size_t all;
ssize_t rd;
int fd;
if (old) { /* we already have a cached copy of it */
info = (struct cached_file_info *)((*cache) - sizeof(*info));
if (t - info->last_confirm < 5)
/* we checked it as fresh less than 5s ago, use old */
return 0;
}
/*
* ...it's been 5s, we should check again on the filesystem
* that the file hasn't changed
*/
fd = open(filepath, O_RDONLY);
if (fd < 0) {
lwsl_err("%s: cannot open %s\n", __func__, filepath);
return 1;
}
if (fstat(fd, &s)) {
lwsl_err("%s: cannot stat %s\n", __func__, filepath);
goto bail;
}
if (old && s.st_mtime == info->s.st_mtime) {
/* it still seems to be the same as our cached one */
info->last_confirm = t;
close(fd);
return 0;
}
/*
* we either didn't cache it yet, or it has changed since we cached
* it... reload in a new lac and then detach the old lac.
*/
all = sizeof(*info) + (unsigned long)s.st_size + 2;
info = lwsac_use(&lac, all, all);
if (!info)
goto bail;
info->s = s;
info->last_confirm = t;
a = (unsigned char *)(info + 1);
*len = (unsigned long)s.st_size;
a[s.st_size] = '\0';
rd = read(fd, a, (unsigned long)s.st_size);
if (rd != s.st_size) {
lwsl_err("%s: cannot read %s (%d)\n", __func__, filepath,
(int)rd);
goto bail1;
}
close(fd);
*cache = (lwsac_cached_file_t)a;
if (old)
lwsac_use_cached_file_detach(&old);
return 0;
bail1:
lwsac_free(&lac);
bail:
close(fd);
return 1;
}
#endif

View File

@ -0,0 +1,358 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "private-lib-core.h"
#include "private-lib-misc-lwsac.h"
void
lws_list_ptr_insert(lws_list_ptr *head, lws_list_ptr *add,
lws_list_ptr_sort_func_t sort_func)
{
while (sort_func && *head) {
if (sort_func(add, *head) <= 0)
break;
head = *head;
}
*add = *head;
*head = add;
}
size_t
lwsac_align(size_t length)
{
size_t align = sizeof(int *);
if (length & (align - 1))
length += align - (length & (align - 1));
return length;
}
size_t
lwsac_sizeof(int first)
{
return sizeof(struct lwsac) + (first ? sizeof(struct lwsac_head) : 0);
}
size_t
lwsac_get_tail_pos(struct lwsac *lac)
{
return lac->ofs;
}
struct lwsac *
lwsac_get_next(struct lwsac *lac)
{
return lac->next;
}
int
lwsac_extend(struct lwsac *head, size_t amount)
{
struct lwsac_head *lachead;
struct lwsac *bf;
assert(head);
lachead = (struct lwsac_head *)&head[1];
bf = lachead->curr;
assert(bf);
if (bf->alloc_size - bf->ofs < lwsac_align(amount))
return 1;
/* memset so constant folding never sees uninitialized data */
memset(((uint8_t *)bf) + bf->ofs, 0, lwsac_align(amount));
bf->ofs += lwsac_align(amount);
return 0;
}
static void *
_lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size, char backfill)
{
struct lwsac_head *lachead = NULL;
size_t ofs, alloc, al, hp;
struct lwsac *bf = *head;
if (bf)
lachead = (struct lwsac_head *)&bf[1];
al = lwsac_align(ensure);
/* backfill into earlier chunks if that is allowed */
if (backfill)
/*
* check if anything can take it, from the start
*/
while (bf) {
if (bf->alloc_size - bf->ofs >= ensure)
goto do_use;
bf = bf->next;
}
else {
/*
* If there's a current chunk, just check if he can take it
*/
if (lachead && lachead->curr) {
bf = lachead->curr;
if (bf->alloc_size - bf->ofs >= ensure)
goto do_use;
}
}
/* nothing can currently take it... so we must allocate */
hp = sizeof(*bf); /* always need the normal header part... */
if (!*head)
hp += sizeof(struct lwsac_head);
if (!chunk_size)
alloc = LWSAC_CHUNK_SIZE + hp;
else
alloc = chunk_size + hp;
/*
* If we get asked for something outside our expectation,
* increase the allocation to meet it
*/
if (al >= alloc - hp)
alloc = al + hp;
// lwsl_debug("%s: alloc %d for %d\n", __func__, (int)alloc, (int)ensure);
bf = malloc(alloc);
if (!bf) {
lwsl_err("%s: OOM trying to alloc %llud\n", __func__,
(unsigned long long)alloc);
return NULL;
}
/*
* belabouring the point... ofs is aligned to the platform's
* generic struct alignment at the start then
*/
bf->ofs = sizeof(*bf);
if (!*head) {
/*
* We are the first, head, entry...
*/
*head = bf;
/*
* ... allocate for the special head block
*/
bf->ofs += sizeof(*lachead);
lachead = (struct lwsac_head *)&bf[1];
memset(lachead, 0, sizeof(*lachead));
} else
if (lachead->curr)
lachead->curr->next = bf;
lachead->curr = bf;
bf->head = *head;
bf->next = NULL;
bf->alloc_size = alloc;
lachead->total_alloc_size += alloc;
lachead->total_blocks++;
do_use:
ofs = bf->ofs;
if (al > ensure)
/* zero down the alignment padding part */
memset((char *)bf + ofs + ensure, 0, al - ensure);
bf->ofs += al;
if (bf->ofs >= bf->alloc_size)
bf->ofs = bf->alloc_size;
return (char *)bf + ofs;
}
void *
lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size)
{
return _lwsac_use(head, ensure, chunk_size, 0);
}
void *
lwsac_use_backfill(struct lwsac **head, size_t ensure, size_t chunk_size)
{
return _lwsac_use(head, ensure, chunk_size, 1);
}
uint8_t *
lwsac_scan_extant(struct lwsac *head, uint8_t *find, size_t len, int nul)
{
while (head) {
uint8_t *pos = (uint8_t *)&head[1],
*end = ((uint8_t *)head) + head->ofs - len;
if (head->ofs - sizeof(*head) >= len)
while (pos < end) {
if (*pos == *find && (!nul || !pos[len]) &&
pos[len - 1] == find[len - 1] &&
!memcmp(pos, find, len))
/* found the blob */
return pos;
pos++;
}
head = head->next;
}
return NULL;
}
uint64_t
lwsac_total_overhead(struct lwsac *head)
{
uint64_t overhead = 0;
while (head) {
overhead += (head->alloc_size - head->ofs) + sizeof(*head);
head = head->next;
}
return overhead;
}
void *
lwsac_use_zero(struct lwsac **head, size_t ensure, size_t chunk_size)
{
void *p = lwsac_use(head, ensure, chunk_size);
if (p)
memset(p, 0, ensure);
return p;
}
void
lwsac_free(struct lwsac **head)
{
struct lwsac *it = *head;
*head = NULL;
// lwsl_debug("%s: head %p\n", __func__, *head);
while (it) {
struct lwsac *tmp = it->next;
free(it);
it = tmp;
}
}
void
lwsac_info(struct lwsac *head)
{
#if _LWS_ENABLED_LOGS & LLL_DEBUG
struct lwsac_head *lachead;
if (!head) {
lwsl_debug("%s: empty\n", __func__);
return;
}
lachead = (struct lwsac_head *)&head[1];
lwsl_debug("%s: lac %p: %dKiB in %d blocks\n", __func__, head,
(int)(lachead->total_alloc_size >> 10), lachead->total_blocks);
#endif
}
uint64_t
lwsac_total_alloc(struct lwsac *head)
{
struct lwsac_head *lachead;
if (!head)
return 0;
lachead = (struct lwsac_head *)&head[1];
return lachead->total_alloc_size;
}
void
lwsac_reference(struct lwsac *head)
{
struct lwsac_head *lachead = (struct lwsac_head *)&head[1];
lachead->refcount++;
lwsl_debug("%s: head %p: (det %d) refcount -> %d\n",
__func__, head, lachead->detached, lachead->refcount);
}
void
lwsac_unreference(struct lwsac **head)
{
struct lwsac_head *lachead;
if (!(*head))
return;
lachead = (struct lwsac_head *)&(*head)[1];
if (!lachead->refcount)
lwsl_warn("%s: refcount going below zero\n", __func__);
lachead->refcount--;
lwsl_debug("%s: head %p: (det %d) refcount -> %d\n",
__func__, *head, lachead->detached, lachead->refcount);
if (lachead->detached && !lachead->refcount) {
lwsl_debug("%s: head %p: FREED\n", __func__, *head);
lwsac_free(head);
}
}
void
lwsac_detach(struct lwsac **head)
{
struct lwsac_head *lachead;
if (!(*head))
return;
lachead = (struct lwsac_head *)&(*head)[1];
lachead->detached = 1;
if (!lachead->refcount) {
lwsl_debug("%s: head %p: FREED\n", __func__, *head);
lwsac_free(head);
} else
lwsl_debug("%s: head %p: refcount %d: Marked as detached\n",
__func__, *head, lachead->refcount);
}

View File

@ -0,0 +1,80 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* C++ classes for Secure Streams - atomic heap messages
*/
#include <libwebsockets.hxx>
#include "private-lib-misc-lwsac.h"
void
lssAc::start(bool atomic)
{
if (atomic && ac->next) {
struct lwsac *ac2 = NULL, *i;
size_t total = (size_t)lwsac_total_alloc(ac);
uint8_t *p = (uint8_t *)lwsac_use(&ac2, total, total);
/*
* He wants a single linear buffer, and we have more than one
* piece... let's make a new, single one, copy the fragments
* in and replace the fragmented one with the unified copy.
*/
i = ac;
while (i) {
size_t bl = lwsac_get_tail_pos(i) -
lwsac_sizeof(i == ac);
memcpy(p, (uint8_t *)i + lwsac_sizeof(i == ac), bl);
p += bl;
}
lwsac_free(&ac);
ac = ac2;
}
iter = ac;
}
int
lssAc::get(lssbuf_t *lb)
{
if (!ac)
return 1;
lb->buf = (uint8_t *)iter + lwsac_sizeof(iter == ac);
lb->len = lwsac_get_tail_pos(iter) - lwsac_sizeof(iter == ac);
iter = iter->next;
return 0;
}
void
lssAc::append(lssbuf_t *lb)
{
uint8_t *p = (uint8_t *)lwsac_use(&ac, lb->len, lb->len);
if (!p)
throw lssException("oom");
memcpy(p, lb->buf, lb->len);
}

View File

@ -0,0 +1,70 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#if !defined(__LWS_PRIVATE_LIB_MISC_LWSAC_H__)
#define __LWS_PRIVATE_LIB_MISC_LWSAC_H__
#if !defined(LWS_PLAT_OPTEE)
#include <sys/stat.h>
#endif
/* under page size of 4096 to allow overhead */
#define LWSAC_CHUNK_SIZE 4000
/*
* the chunk list members all point back to the head themselves so the list
* can be detached from the formal head and free itself when its reference
* count reaches zero.
*/
/*
* One of these per chunk
*/
struct lwsac {
struct lwsac *next;
struct lwsac *head; /* pointer back to the first chunk */
size_t alloc_size; /* alloc size of the whole chunk */
size_t ofs; /* next writeable position inside chunk */
};
/*
* One of these per lwsac, at start of first chunk
*/
struct lwsac_head {
struct lwsac *curr;
size_t total_alloc_size;
int refcount;
int total_blocks;
char detached; /* if our refcount gets to zero, free the chunk list */
};
#if !defined(LWS_PLAT_OPTEE)
struct cached_file_info {
struct stat s;
time_t last_confirm;
};
#endif
#endif