diff --git a/include/libwebsockets/lws-lwsac.h b/include/libwebsockets/lws-lwsac.h index 1c0d69b8a..a59e45942 100644 --- a/include/libwebsockets/lws-lwsac.h +++ b/include/libwebsockets/lws-lwsac.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -198,6 +198,38 @@ lwsac_reference(struct lwsac *head); LWS_VISIBLE LWS_EXTERN void lwsac_unreference(struct lwsac **head); +/** + * lwsac_extend() - try to increase the size of the last block + * + * \param head: pointer to the lwsac list object + * \param amount: amount to try to increase usage for + * + * This will either increase the usage reservation of the last allocated block + * by amount and return 0, or fail and return 1. + * + * This is very cheap to call and is designed to optimize usage after a static + * struct for vari-sized additional content which may flow into an additional + * block in a new chunk if necessary, but wants to make the most of the space + * in front of it first to try to avoid gaps and the new chunk if it can. + * + * The additional area if the call succeeds will have been memset to 0. + * + * To use it, the following must be true: + * + * - only the last lwsac use can be extended + * + * - if another use happens inbetween the use and extend, it will break + * + * - the use cannot have been using backfill + * + * - a user object must be tracking the current allocated size of the last use + * (lwsac doesn't know it) and increment by amount if the extend call succeeds + * + * Despite these restrictions this can be an important optimization for some + * cases + */ +LWS_VISIBLE LWS_EXTERN int +lwsac_extend(struct lwsac *head, int amount); /* helpers to keep a file cached in memory */ diff --git a/lib/misc/lwsac/lwsac.c b/lib/misc/lwsac/lwsac.c index 426fdb381..3ca48a707 100644 --- a/lib/misc/lwsac/lwsac.c +++ b/lib/misc/lwsac/lwsac.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -69,6 +69,29 @@ lwsac_get_next(struct lwsac *lac) return lac->next; } +int +lwsac_extend(struct lwsac *head, int 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) { diff --git a/lib/misc/lwsac/private-lib-misc-lwsac.h b/lib/misc/lwsac/private-lib-misc-lwsac.h index 8c09595fc..026e7adbd 100644 --- a/lib/misc/lwsac/private-lib-misc-lwsac.h +++ b/lib/misc/lwsac/private-lib-misc-lwsac.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -38,18 +38,26 @@ * 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; + 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; /* applies to head chunk only */ - size_t total_alloc_size; /* applies to head chunk only */ - int refcount; /* applies to head chunk only */ - int total_blocks; /* applies to head chunk only */ + 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 */ };