diff options
author | Jeremy Allison <jra@samba.org> | 2013-08-27 12:36:23 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2013-08-27 15:44:19 -0700 |
commit | fe790f6cbc9b888a8d613cfb515f0d0c76daad47 (patch) | |
tree | 30b307f02aaa200c3cc9817332b6b9988d92f912 /lib | |
parent | 323cccd35d06c7327c19dc5cb891043507624d7d (diff) | |
download | samba-fe790f6cbc9b888a8d613cfb515f0d0c76daad47.tar.gz samba-fe790f6cbc9b888a8d613cfb515f0d0c76daad47.tar.bz2 samba-fe790f6cbc9b888a8d613cfb515f0d0c76daad47.zip |
Start to fix talloc memlimits with talloc pools.
Add the functions:
talloc_memlimit_grow(), talloc_memlimit_shrink(),
talloc_memlimit_update_on_free().
as replacements for talloc_memlimit_update().
The interface to talloc_memlimit_update() is very
hard to understand and use. The above functions
are (to me) much clearer.
The goal of these changes is to only update
the memlimits on malloc/free/realloc, not
on every pool allocation. That way we only
count pool creation as allocation from any
imposed limits, not allocation from an already
created pool.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Simo Sorce <idra@samba.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/talloc/talloc.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 76f0aeedfd..067d46f97d 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -238,6 +238,11 @@ struct talloc_memlimit { static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size); static bool talloc_memlimit_update(struct talloc_memlimit *limit, size_t old_size, size_t new_size); +static void talloc_memlimit_grow(struct talloc_memlimit *limit, + size_t size); +static void talloc_memlimit_shrink(struct talloc_memlimit *limit, + size_t size); +static void talloc_memlimit_update_on_free(struct talloc_chunk *tc); typedef int (*talloc_destructor_t)(void *); @@ -2564,6 +2569,73 @@ static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size) return true; } +/* + Update memory limits when freeing a talloc_chunk. +*/ +static void talloc_memlimit_update_on_free(struct talloc_chunk *tc) +{ + if (!tc->limit) { + return; + } + + /* + * Pool entries don't count. Only the pools + * themselves are counted as part of the memory + * limits. + */ + if (tc->flags & TALLOC_FLAG_POOLMEM) { + return; + } + + /* + * If we are part of a memory limited context hierarchy + * we need to subtract the memory used from the counters + */ + + talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE); + + if (tc->limit->parent == tc) { + free(tc->limit); + } + + tc->limit = NULL; +} + +/* + Increase memory limit accounting after a malloc/realloc. +*/ +static void talloc_memlimit_grow(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + size_t new_cur_size = l->cur_size + size; + if (new_cur_size < l->cur_size) { + talloc_abort("logic error in talloc_memlimit_grow\n"); + return; + } + l->cur_size = new_cur_size; + } +} + +/* + Decrease memory limit accounting after a free/realloc. +*/ +static void talloc_memlimit_shrink(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + if (l->cur_size < size) { + talloc_abort("logic error in talloc_memlimit_shrink\n"); + return; + } + l->cur_size = l->cur_size - size; + } +} + static bool talloc_memlimit_update(struct talloc_memlimit *limit, size_t old_size, size_t new_size) { |