[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 02/02: Partially reworked memory allocation from the poo
From: |
gnunet |
Subject: |
[libmicrohttpd] 02/02: Partially reworked memory allocation from the pool |
Date: |
Sun, 10 Oct 2021 19:28:47 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit abcbf778676ee0e081e4fa99443f4348828d6ab6
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sat Oct 9 17:24:04 2021 +0300
Partially reworked memory allocation from the pool
More robust implementation, should catch non-standard situations.
Always track read and write buffers, even if size is zero as
buffer pointers are used for data size calculations.
---
src/microhttpd/connection.c | 51 ++++++++++++++++------------------
src/microhttpd/memorypool.c | 68 +++++++++++++++++++++++++++++++++------------
src/microhttpd/memorypool.h | 38 ++++++++++++++++---------
3 files changed, 100 insertions(+), 57 deletions(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index a9619575..536bb28f 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -204,16 +204,12 @@ connection_alloc_memory (struct MHD_Connection
*connection,
{
struct MHD_Connection *const c = connection; /* a short alias */
struct MemoryPool *const pool = c->pool; /* a short alias */
- size_t required_free_size; /**< The required amount of free memory */
- size_t pool_free; /**< The amount of free memory in the pool */
+ size_t need_to_free; /**< The required amount of free memory */
void *res;
- required_free_size = MHD_pool_alloc_size (size);
- pool_free = MHD_pool_get_free (pool);
- if (pool_free < required_free_size)
+ res = MHD_pool_try_alloc (pool, size, &need_to_free);
+ if (NULL == res)
{
- size_t need_to_free = required_free_size - pool_free;
- mhd_assert (MHD_pool_alloc_size (need_to_free) == need_to_free);
if (NULL != c->write_buffer)
{
/* The connection is in the sending phase */
@@ -227,12 +223,10 @@ connection_alloc_memory (struct MHD_Connection
*connection,
c->write_buffer_size,
new_buf_size);
mhd_assert (c->write_buffer == buf);
-#ifdef NDEBUG
- (void) buf; /* mute compiler warning */
-#endif
mhd_assert (c->write_buffer_append_offset <= new_buf_size);
mhd_assert (c->write_buffer_send_offset <= new_buf_size);
c->write_buffer_size = new_buf_size;
+ c->write_buffer = buf;
}
else
return NULL;
@@ -249,20 +243,18 @@ connection_alloc_memory (struct MHD_Connection
*connection,
c->read_buffer_size,
new_buf_size);
mhd_assert (c->read_buffer == buf);
-#ifdef NDEBUG
- (void) buf; /* mute compiler warning */
-#endif
mhd_assert (c->read_buffer_offset <= new_buf_size);
c->read_buffer_size = new_buf_size;
+ c->read_buffer = buf;
}
else
return NULL;
}
else
return NULL;
+ res = MHD_pool_allocate (pool, size, true);
+ mhd_assert (NULL != res); /* It has been checked that pool has enough
space */
}
- res = MHD_pool_allocate (pool, size, true);
- mhd_assert (NULL != res); /* It has been checked that pool has enough space
*/
return res;
}
@@ -1486,7 +1478,7 @@ try_grow_read_buffer (struct MHD_Connection *connection,
/**
- * Shrink connection read buffer to the zero of data in the buffer
+ * Shrink connection read buffer to the zero size of free space in the buffer
* @param connection the connection whose read buffer is being manipulated
*/
static void
@@ -1495,11 +1487,10 @@ connection_shrink_read_buffer (struct MHD_Connection
*connection)
struct MHD_Connection *const c = connection; /**< a short alias */
void *new_buf;
- if (NULL == c->read_buffer)
+ if ((NULL == c->read_buffer) || (0 == c->read_buffer_size))
{
mhd_assert (0 == c->read_buffer_size);
mhd_assert (0 == c->read_buffer_offset);
- c->read_buffer = NULL;
return;
}
@@ -1507,12 +1498,8 @@ connection_shrink_read_buffer (struct MHD_Connection
*connection)
new_buf = MHD_pool_reallocate (c->pool, c->read_buffer, c->read_buffer_size,
c->read_buffer_offset);
mhd_assert (c->read_buffer == new_buf);
-#ifdef NDEBUG
- (void) new_buf; /* squash compiler warning */
-#endif /* NDEBUG */
+ c->read_buffer = new_buf;
c->read_buffer_size = c->read_buffer_offset;
- if (0 == c->read_buffer_size)
- c->read_buffer = NULL;
}
@@ -1582,16 +1569,25 @@ connection_shrink_write_buffer (struct MHD_Connection
*connection)
mhd_assert (c->write_buffer_append_offset >= c->write_buffer_send_offset);
mhd_assert (c->write_buffer_size >= c->write_buffer_append_offset);
- if (NULL == c->write_buffer)
+ if ( (NULL == c->write_buffer) || (0 == c->write_buffer_size))
+ {
+ mhd_assert (0 == c->write_buffer_append_offset);
+ mhd_assert (0 == c->write_buffer_send_offset);
+ c->write_buffer = NULL;
return;
+ }
if (c->write_buffer_append_offset == c->write_buffer_size)
return;
new_buf = MHD_pool_reallocate (pool, c->write_buffer, c->write_buffer_size,
c->write_buffer_append_offset);
- mhd_assert (c->write_buffer == new_buf);
- (void) new_buf; /* squash compiler warning */
+ mhd_assert ((c->write_buffer == new_buf) || \
+ (0 == c->write_buffer_append_offset));
c->write_buffer_size = c->write_buffer_append_offset;
+ if (0 == c->write_buffer_size)
+ c->write_buffer = NULL;
+ else
+ c->write_buffer = new_buf;
}
@@ -1987,8 +1983,9 @@ build_header_response (struct MHD_Connection *connection)
buf = c->write_buffer;
pos = c->write_buffer_append_offset;
buf_size = c->write_buffer_size;
- if ((NULL == buf) || (0 == buf_size))
+ if (0 == buf_size)
return MHD_NO;
+ mhd_assert (NULL != buf);
/* * The status line * */
diff --git a/src/microhttpd/memorypool.c b/src/microhttpd/memorypool.c
index c5e5b4fd..fb6c0652 100644
--- a/src/microhttpd/memorypool.c
+++ b/src/microhttpd/memorypool.c
@@ -104,22 +104,6 @@ MHD_init_mem_pools_ (void)
}
-/**
- * Get the real size that would be allocated by the memory pool when
- * requested to allocate @a size.
- * @param size the size of memory area that would be rounded up to the
- * allocation granularity
- * @return the size that would be allocated by #MHD_pool_allocate() when
- * requested to allocate @a size. It is also minimal size of free
- * space in the pool required to #MHD_pool_allocate() succeed.
- */
-size_t
-MHD_pool_alloc_size (size_t size)
-{
- return ROUND_TO_ALIGN (size);
-}
-
-
/**
* Handle for a memory pool. Pools are not reentrant and must not be
* used by multiple threads.
@@ -311,6 +295,56 @@ MHD_pool_allocate (struct MemoryPool *pool,
}
+/**
+ * Try to allocate @a size bytes memory area from the @a pool.
+ *
+ * If allocation fails, @a required_bytes is updated with size required to be
+ * freed in the @a pool from relocatable area to allocate requested number
+ * of bytes.
+ * Allocated memory area is always not rellocatable ("from end").
+ *
+ * @param pool memory pool to use for the operation
+ * @param size the size of memory in bytes to allocate
+ * @param[out] required_bytes the pointer to variable to be updated with
+ * the size of the required additional free
+ * memory area, not updated if function succeed.
+ * Cannot be NULL.
+ * @return the pointer to allocated memory area if succeed,
+ * NULL if the pool doesn't have enough space, required_bytes is
updated
+ * with amount of space needed to be freed in relocatable area or
+ * set to SIZE_MAX if requested size is too large for the pool.
+ */
+void *
+MHD_pool_try_alloc (struct MemoryPool *pool,
+ size_t size,
+ size_t *required_bytes)
+{
+ void *ret;
+ size_t asize;
+
+ mhd_assert (pool->end >= pool->pos);
+ mhd_assert (pool->size >= pool->end - pool->pos);
+ asize = ROUND_TO_ALIGN (size);
+ if ( (0 == asize) && (0 != size) )
+ { /* size is too close to SIZE_MAX, very unlikely */
+ *required_bytes = SIZE_MAX;
+ return NULL;
+ }
+ if ( (pool->pos + asize > pool->end) ||
+ (pool->pos + asize < pool->pos))
+ {
+ if (asize <= pool->end)
+ *required_bytes = asize - (pool->end - pool->pos);
+ else
+ *required_bytes = SIZE_MAX;
+ return NULL;
+ }
+ ret = &pool->memory[pool->end - asize];
+ pool->end -= asize;
+ return ret;
+}
+
+
/**
* Reallocate a block of memory obtained from the pool.
* This is particularly efficient when growing or
@@ -355,7 +389,7 @@ MHD_pool_reallocate (struct MemoryPool *pool,
pool->end);
if (0 != old_size)
- { /* Need to save some data */
+ { /* Have previously allocated data */
const size_t old_offset = (uint8_t*) old - pool->memory;
const bool shrinking = (old_size > new_size);
/* Try resizing in-place */
diff --git a/src/microhttpd/memorypool.h b/src/microhttpd/memorypool.h
index 955fea4d..b569d33e 100644
--- a/src/microhttpd/memorypool.h
+++ b/src/microhttpd/memorypool.h
@@ -52,19 +52,6 @@ void
MHD_init_mem_pools_ (void);
-/**
- * Get the real size that would be allocated by the memory pool when
- * requested to allocate @a size.
- * @param size the size of memory area that would be rounded up to the
- * allocation granularity
- * @return the size that would be allocated by #MHD_pool_allocate() when
- * requested to allocate @a size. It is also minimal size of free
- * space in the pool required to #MHD_pool_allocate() succeed.
- */
-size_t
-MHD_pool_alloc_size (size_t size);
-
-
/**
* Create a memory pool.
*
@@ -101,6 +88,31 @@ MHD_pool_allocate (struct MemoryPool *pool,
bool from_end);
+/**
+ * Try to allocate @a size bytes memory area from the @a pool.
+ *
+ * If allocation fails, @a required_bytes is updated with size required to be
+ * freed in the @a pool from relocatable area to allocate requested number
+ * of bytes.
+ * Allocated memory area is always not rellocatable ("from end").
+ *
+ * @param pool memory pool to use for the operation
+ * @param size the size of memory in bytes to allocate
+ * @param[out] required_bytes the pointer to variable to be updated with
+ * the size of the required additional free
+ * memory area, not updated if function succeed.
+ * Cannot be NULL.
+ * @return the pointer to allocated memory area if succeed,
+ * NULL if the pool doesn't have enough space, required_bytes is
updated
+ * with amount of space needed to be freed in relocatable area or
+ * set to SIZE_MAX if requested size is too large for the pool.
+ */
+void *
+MHD_pool_try_alloc (struct MemoryPool *pool,
+ size_t size,
+ size_t *required_bytes);
+
+
/**
* Reallocate a block of memory obtained from the pool.
* This is particularly efficient when growing or
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.