gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]