summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2013-08-27 12:36:23 -0700
committerKarolin Seeger <kseeger@samba.org>2015-03-15 22:14:07 +0100
commit079a5e628b535d4cb94e71a1899021986f3b657d (patch)
tree3470ee10bfc2a9206a396193b46abc06498788b9
parent6afc7bc1e8444a3a2f3443ec8184af0d79ffde00 (diff)
downloadsamba-079a5e628b535d4cb94e71a1899021986f3b657d.tar.gz
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> (cherry picked from commit fe790f6cbc9b888a8d613cfb515f0d0c76daad47)
-rw-r--r--lib/talloc/talloc.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 76f0aeedfd4..067d46f97d3 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)
{