From 3be21fb12f4cec2cf07799e8960382f4cb375369 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 28 Apr 2008 17:06:34 +0300 Subject: Fixed wrong spelling "limitter" to "limiter". This affects liblzma's API. --- src/liblzma/api/lzma/base.h | 4 +- src/liblzma/api/lzma/memlimit.h | 10 +- src/liblzma/api/lzma/stream.h | 4 +- src/liblzma/common/Makefile.am | 2 +- src/liblzma/common/memory_limiter.c | 288 +++++++++++++++++++++++++++++++++++ src/liblzma/common/memory_limitter.c | 288 ----------------------------------- 6 files changed, 298 insertions(+), 298 deletions(-) create mode 100644 src/liblzma/common/memory_limiter.c delete mode 100644 src/liblzma/common/memory_limitter.c (limited to 'src/liblzma') diff --git a/src/liblzma/api/lzma/base.h b/src/liblzma/api/lzma/base.h index e7edf531..d39bfe95 100644 --- a/src/liblzma/api/lzma/base.h +++ b/src/liblzma/api/lzma/base.h @@ -265,8 +265,8 @@ typedef struct { * custom memory allocation functions for use with liblzma. * * When using lzma_memory_alloc() and lzma_memory_free(), opaque - * must point to lzma_memory_limitter structure allocated and - * initialized with lzma_memory_limitter_create(). + * must point to lzma_memory_limiter structure allocated and + * initialized with lzma_memory_limiter_create(). * * If you don't need this, you should set it to NULL. */ diff --git a/src/liblzma/api/lzma/memlimit.h b/src/liblzma/api/lzma/memlimit.h index c0449f2b..6b07679d 100644 --- a/src/liblzma/api/lzma/memlimit.h +++ b/src/liblzma/api/lzma/memlimit.h @@ -1,6 +1,6 @@ /** * \file lzma/memlimit.h - * \brief Memory usage limitter + * \brief Memory usage limiter * * \author Copyright (C) 1999-2006 Igor Pavlov * \author Copyright (C) 2007 Lasse Collin @@ -39,7 +39,7 @@ typedef struct lzma_memlimit_s lzma_memlimit; * to these functions can be used in lzma_allocator structure, which makes * it easy to limit memory usage with liblzma. * - * The memory limitter functions are not tied to limitting memory usage + * The memory limiter functions are not tied to limitting memory usage * with liblzma itself. You can use them with anything you like. * * In multi-threaded applications, only one thread at once may use the same @@ -128,7 +128,7 @@ extern lzma_bool lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear); /** - * \brief Gets the number of allocations owned by the memory limitter + * \brief Gets the number of allocations owned by the memory limiter * * The count does not include the helper structures; if no memory has * been allocated with lzma_memlimit_alloc() or all memory allocated @@ -189,9 +189,9 @@ extern void lzma_memlimit_free(lzma_memlimit *mem, void *ptr); /** - * \brief Frees the memory allocated for and by the memory usage limitter + * \brief Frees the memory allocated for and by the memory usage limiter * - * \param mem Pointer to memory limitter + * \param mem Pointer to memory limiter * \param free_allocated If this is non-zero, all the memory allocated * by lzma_memlimit_alloc() using *mem is also * freed if it hasn't already been freed with diff --git a/src/liblzma/api/lzma/stream.h b/src/liblzma/api/lzma/stream.h index d111be37..346bdd17 100644 --- a/src/liblzma/api/lzma/stream.h +++ b/src/liblzma/api/lzma/stream.h @@ -169,8 +169,8 @@ extern lzma_ret lzma_stream_encoder_multi( * completely when lzma_code() returns LZMA_STREAM_END. If *footer is still * NULL, there was no Extra field in the Footer Metadata Block. * - * \note If you use lzma_memory_limitter, the Extra Records will be - * allocated with it, and thus remain in the lzma_memory_limitter + * \note If you use lzma_memory_limiter, the Extra Records will be + * allocated with it, and thus remain in the lzma_memory_limiter * even after they get exported to the application via *header * and *footer pointers. */ diff --git a/src/liblzma/common/Makefile.am b/src/liblzma/common/Makefile.am index c650a34c..c76ce14f 100644 --- a/src/liblzma/common/Makefile.am +++ b/src/liblzma/common/Makefile.am @@ -31,7 +31,7 @@ libcommon_la_SOURCES = \ index.c \ info.c \ init.c \ - memory_limitter.c \ + memory_limiter.c \ memory_usage.c \ next_coder.c \ raw_common.c \ diff --git a/src/liblzma/common/memory_limiter.c b/src/liblzma/common/memory_limiter.c new file mode 100644 index 00000000..a2a0cbdc --- /dev/null +++ b/src/liblzma/common/memory_limiter.c @@ -0,0 +1,288 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \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; +} diff --git a/src/liblzma/common/memory_limitter.c b/src/liblzma/common/memory_limitter.c deleted file mode 100644 index e6aa6300..00000000 --- a/src/liblzma/common/memory_limitter.c +++ /dev/null @@ -1,288 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file memory_limitter.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; -} -- cgit v1.2.3