aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/memory_limiter.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2008-11-25 02:37:47 +0200
committerLasse Collin <lasse.collin@tukaani.org>2008-11-25 02:37:47 +0200
commita8368b75cdcd5427299001cc42839287f27b244d (patch)
tree5b27a19002eb9f0c31ab4730d9073b0dc0f68c03 /src/liblzma/common/memory_limiter.c
parentVLI encoder and decoder cleanups. Made encoder return (diff)
downloadxz-a8368b75cdcd5427299001cc42839287f27b244d.tar.xz
Remove the nowadays unneeded memory limitting malloc() wrapper.
Diffstat (limited to 'src/liblzma/common/memory_limiter.c')
-rw-r--r--src/liblzma/common/memory_limiter.c288
1 files changed, 0 insertions, 288 deletions
diff --git a/src/liblzma/common/memory_limiter.c b/src/liblzma/common/memory_limiter.c
deleted file mode 100644
index a2a0cbdc..00000000
--- a/src/liblzma/common/memory_limiter.c
+++ /dev/null
@@ -1,288 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file memory_limiter.c
-/// \brief Limitting memory usage
-//
-// Copyright (C) 2007 Lasse Collin
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-
-/// Rounds an unsigned integer upwards to the next multiple.
-#define my_ceil(num, multiple) \
- ((num) + (((multiple) - ((num) % (multiple))) % (multiple)))
-
-
-/// Add approximated overhead of malloc() to size and round upwards to the
-/// next multiple of 2 * sizeof(size_t). I suppose that most malloc()
-/// implementations align small allocations this way, but the overhead
-/// varies due to several reasons (free lists, mmap() usage etc.).
-///
-/// This doesn't need to be exact at all. It's enough to take into account
-/// that there is some overhead. That way our memory usage count won't be
-/// horribly wrong if we are used to allocate lots of small memory chunks.
-#define malloc_ceil(size) \
- my_ceil((size) + 2 * sizeof(void *), 2 * sizeof(size_t))
-
-
-typedef struct lzma_memlimit_list_s lzma_memlimit_list;
-struct lzma_memlimit_list_s {
- lzma_memlimit_list *next;
- void *ptr;
- size_t size;
-};
-
-
-struct lzma_memlimit_s {
- /// List of allocated memory chunks
- lzma_memlimit_list *list;
-
- /// Number of bytes currently allocated; this includes the memory
- /// needed for the helper structures.
- size_t used;
-
- /// Memory usage limit
- size_t limit;
-
- /// Maximum amount of memory that have been or would have been needed.
- /// That is, this is updated also if memory allocation fails, letting
- /// the application check how much memory was tried to be allocated
- /// in total.
- size_t max;
-
- /// True if lzma_memlimit_alloc() has returned NULL due to memory
- /// usage limit.
- bool limit_reached;
-};
-
-
-extern LZMA_API lzma_memlimit *
-lzma_memlimit_create(size_t limit)
-{
- const size_t base_size = malloc_ceil(sizeof(lzma_memlimit));
-
- if (limit < base_size)
- return NULL;
-
- lzma_memlimit *mem = malloc(sizeof(lzma_memlimit));
-
- if (mem != NULL) {
- mem->list = NULL;
- mem->used = base_size;
- mem->limit = limit;
- mem->max = base_size;
- mem->limit_reached = false;
- }
-
- return mem;
-}
-
-
-extern LZMA_API void
-lzma_memlimit_set(lzma_memlimit *mem, size_t limit)
-{
- mem->limit = limit;
- return;
-}
-
-
-extern LZMA_API size_t
-lzma_memlimit_get(const lzma_memlimit *mem)
-{
- return mem->limit;
-}
-
-
-extern LZMA_API size_t
-lzma_memlimit_used(const lzma_memlimit *mem)
-{
- return mem->used;
-}
-
-
-extern LZMA_API size_t
-lzma_memlimit_max(lzma_memlimit *mem, lzma_bool clear)
-{
- const size_t ret = mem->max;
-
- if (clear)
- mem->max = mem->used;
-
- return ret;
-}
-
-
-extern LZMA_API lzma_bool
-lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear)
-{
- const bool ret = mem->limit_reached;
-
- if (clear)
- mem->limit_reached = false;
-
- return ret;
-}
-
-
-extern LZMA_API size_t
-lzma_memlimit_count(const lzma_memlimit *mem)
-{
- // This is slow; we could have a counter in lzma_memlimit
- // for fast version. I expect the primary use of this
- // function to be limited to easy checking of memory leaks,
- // in which this implementation is just fine.
- size_t count = 0;
- const lzma_memlimit_list *record = mem->list;
-
- while (record != NULL) {
- ++count;
- record = record->next;
- }
-
- return count;
-}
-
-
-extern LZMA_API void
-lzma_memlimit_end(lzma_memlimit *mem, lzma_bool free_allocated)
-{
- if (mem == NULL)
- return;
-
- lzma_memlimit_list *record = mem->list;
- while (record != NULL) {
- if (free_allocated)
- free(record->ptr);
-
- lzma_memlimit_list *tmp = record;
- record = record->next;
- free(tmp);
- }
-
- free(mem);
-
- return;
-}
-
-
-extern LZMA_API void *
-lzma_memlimit_alloc(lzma_memlimit *mem, size_t nmemb, size_t size)
-{
- // While liblzma always sets nmemb to one, do this multiplication
- // to make these functions usable e.g. with zlib and libbzip2.
- // Making sure that this doesn't overflow is up to the application.
- size *= nmemb;
-
- // Some malloc() implementations return NULL on malloc(0). We like
- // to get a non-NULL value.
- if (size == 0)
- size = 1;
-
- // Calculate how much memory we are going to allocate in reality.
- const size_t total_size = malloc_ceil(size)
- + malloc_ceil(sizeof(lzma_memlimit_list));
-
- // Integer overflow protection for total_size and mem->used.
- if (total_size <= size || SIZE_MAX - total_size < mem->used) {
- mem->max = SIZE_MAX;
- mem->limit_reached = true;
- return NULL;
- }
-
- // Update the maximum memory requirement counter if needed. This
- // is updated even if memory allocation would fail or limit would
- // be reached.
- if (mem->used + total_size > mem->max)
- mem->max = mem->used + total_size;
-
- // Check if we would stay in the memory usage limits. We need to
- // check also that the current usage is in the limits, because
- // the application could have decreased the limit between calls
- // to this function.
- if (mem->limit < mem->used || mem->limit - mem->used < total_size) {
- mem->limit_reached = true;
- return NULL;
- }
-
- // Allocate separate memory chunks for lzma_memlimit_list and the
- // actual requested memory. Optimizing this to use only one
- // allocation is not a good idea, because applications may want to
- // detach lzma_extra structures that have been allocated with
- // lzma_memlimit_alloc().
- lzma_memlimit_list *record = malloc(sizeof(lzma_memlimit_list));
- void *ptr = malloc(size);
-
- if (record == NULL || ptr == NULL) {
- free(record);
- free(ptr);
- return NULL;
- }
-
- // Add the new entry to the beginning of the list. This should be
- // more efficient when freeing memory, because usually it is
- // "last allocated, first freed".
- record->next = mem->list;
- record->ptr = ptr;
- record->size = total_size;
-
- mem->list = record;
- mem->used += total_size;
-
- return ptr;
-}
-
-
-extern LZMA_API void
-lzma_memlimit_detach(lzma_memlimit *mem, void *ptr)
-{
- if (ptr == NULL || mem->list == NULL)
- return;
-
- lzma_memlimit_list *record = mem->list;
- lzma_memlimit_list *prev = NULL;
-
- while (record->ptr != ptr) {
- prev = record;
- record = record->next;
- if (record == NULL)
- return;
- }
-
- if (prev != NULL)
- prev->next = record->next;
- else
- mem->list = record->next;
-
- assert(mem->used >= record->size);
- mem->used -= record->size;
-
- free(record);
-
- return;
-}
-
-
-extern LZMA_API void
-lzma_memlimit_free(lzma_memlimit *mem, void *ptr)
-{
- if (ptr == NULL)
- return;
-
- lzma_memlimit_detach(mem, ptr);
-
- free(ptr);
-
- return;
-}