summaryrefslogtreecommitdiff
path: root/lib/talloc
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2013-08-27 12:36:23 -0700
committerJeremy Allison <jra@samba.org>2013-08-27 15:44:19 -0700
commitfe790f6cbc9b888a8d613cfb515f0d0c76daad47 (patch)
tree30b307f02aaa200c3cc9817332b6b9988d92f912 /lib/talloc
parent323cccd35d06c7327c19dc5cb891043507624d7d (diff)
downloadsamba-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/talloc')
-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 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)
{