diff options
Diffstat (limited to 'source4/lib/talloc')
-rw-r--r-- | source4/lib/talloc/Makefile.in | 68 | ||||
-rw-r--r-- | source4/lib/talloc/config.mk | 4 | ||||
-rw-r--r-- | source4/lib/talloc/configure.ac | 2 | ||||
-rw-r--r-- | source4/lib/talloc/rules.mk | 18 | ||||
-rw-r--r-- | source4/lib/talloc/talloc.c | 197 | ||||
-rw-r--r-- | source4/lib/talloc/talloc.h | 1 | ||||
-rw-r--r-- | source4/lib/talloc/talloc.mk | 37 | ||||
-rw-r--r-- | source4/lib/talloc/testsuite.c | 37 | ||||
-rw-r--r-- | source4/lib/talloc/web/index.html | 15 |
9 files changed, 304 insertions, 75 deletions
diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index a33085f95b..07b8fd4ff0 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -19,71 +19,25 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ SHLIBEXT = @SHLIBEXT@ SHLD = @SHLD@ SHLD_FLAGS = @SHLD_FLAGS@ +tallocdir = @tallocdir@ -.SUFFIXES: .c .o .3 .3.xml .xml .html +LIBOBJ = $(TALLOC_OBJ) @LIBREPLACEOBJ@ -LIBOBJ = @TALLOC_OBJ@ @LIBREPLACEOBJ@ +all:: showflags $(EXTRA_TARGETS) -SOLIB = libtalloc.$(SHLIBEXT).$(PACKAGE_VERSION) -SONAME = libtalloc.$(SHLIBEXT).1 +include $(tallocdir)/rules.mk +include $(tallocdir)/talloc.mk -.c.o: - $(CC) $(PICFLAG) -o $@ -c $< $(CFLAGS) +$(TALLOC_SOLIB): $(LIBOBJ) + $(SHLD) $(SHLD_FLAGS) -o $@ $(LIBOBJ) @SONAMEFLAG@$(TALLOC_SONAME) -all: showflags libtalloc.a $(SOLIB) testsuite $(EXTRA_TARGETS) +check: test -showflags: - @echo 'talloc will be compiled with flags:' - @echo ' CFLAGS = $(CFLAGS)' - @echo ' LIBS = $(LIBS)' +installcheck:: test install -testsuite: $(LIBOBJ) testsuite.o - $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) - -libtalloc.a: $(LIBOBJ) - ar -rv $@ $(LIBOBJ) - @-ranlib $@ - -$(SOLIB): $(LIBOBJ) - $(SHLD) $(SHLD_FLAGS) -o $@ $(LIBOBJ) @SONAMEFLAG@$(SONAME) - -install: all - ${INSTALLCMD} -d $(DESTDIR)$(libdir) - ${INSTALLCMD} -d $(DESTDIR)$(libdir)/pkgconfig - ${INSTALLCMD} -m 755 libtalloc.a $(DESTDIR)$(libdir) - ${INSTALLCMD} -m 755 $(SOLIB) $(DESTDIR)$(libdir) - ${INSTALLCMD} -d $(DESTDIR)${includedir} - ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(DESTDIR)$(includedir) - ${INSTALLCMD} -m 644 talloc.pc $(DESTDIR)$(libdir)/pkgconfig - if [ -f talloc.3 ];then ${INSTALLCMD} -d $(DESTDIR)$(mandir)/man3; fi - if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(DESTDIR)$(mandir)/man3; fi - which swig >/dev/null 2>&1 && ${INSTALLCMD} -d $(DESTDIR)`swig -swiglib` || true - which swig >/dev/null 2>&1 && ${INSTALLCMD} -m 644 talloc.i $(DESTDIR)`swig -swiglib` || true - -doc: talloc.3 talloc.3.html - -.3.xml.3: - -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< - -.xml.html: - -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< - -clean: - rm -f *~ $(LIBOBJ) $(SOLIB) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html - -test: testsuite - ./testsuite - -gcov: - gcov talloc.c - -installcheck: - $(MAKE) test - -distclean: clean - rm -f *~ */*~ +distclean:: clean rm -f Makefile rm -f config.log config.status config.h config.cache -realdistclean: distclean +realdistclean:: distclean rm -f configure config.h.in diff --git a/source4/lib/talloc/config.mk b/source4/lib/talloc/config.mk index 16b5063f87..af1b590c98 100644 --- a/source4/lib/talloc/config.mk +++ b/source4/lib/talloc/config.mk @@ -1,8 +1,6 @@ [LIBRARY::LIBTALLOC] -VERSION = 1.0.0 -SO_VERSION = 1 +OUTPUT_TYPE = STATIC_LIBRARY OBJ_FILES = talloc.o -PC_FILE = talloc.pc MANPAGE = talloc.3 CFLAGS = -Ilib/talloc PUBLIC_HEADERS = talloc.h diff --git a/source4/lib/talloc/configure.ac b/source4/lib/talloc/configure.ac index 7878d59300..4719aa04b5 100644 --- a/source4/lib/talloc/configure.ac +++ b/source4/lib/talloc/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT(talloc, 1.1.0) +AC_INIT(talloc, 1.2.0) AC_CONFIG_SRCDIR([talloc.c]) AC_SUBST(datarootdir) AC_CONFIG_HEADER(config.h) diff --git a/source4/lib/talloc/rules.mk b/source4/lib/talloc/rules.mk new file mode 100644 index 0000000000..6cee126529 --- /dev/null +++ b/source4/lib/talloc/rules.mk @@ -0,0 +1,18 @@ +.SUFFIXES: .c .o .3 .3.xml .xml .html + +showflags:: + @echo 'talloc will be compiled with flags:' + @echo ' CFLAGS = $(CFLAGS)' + @echo ' LIBS = $(LIBS)' + +.c.o: + $(CC) $(PICFLAG) -o $@ -c $< $(CFLAGS) + +.3.xml.3: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +.xml.html: + -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< + +distclean:: + rm -f *~ */*~ diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index f9aefcd6de..12b85f5a65 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -60,6 +60,8 @@ #define TALLOC_MAGIC 0xe814ec70 #define TALLOC_FLAG_FREE 0x01 #define TALLOC_FLAG_LOOP 0x02 +#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ +#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -109,6 +111,19 @@ struct talloc_chunk { const char *name; size_t size; unsigned flags; + + /* + * "pool" has dual use: + * + * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool" + * marks the end of the currently allocated area. + * + * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" + * is a pointer to the struct talloc_chunk of the pool that it was + * allocated from. This way children can quickly find the pool to chew + * from. + */ + void *pool; }; /* 16 byte alignment seems to keep everyone happy */ @@ -200,12 +215,87 @@ const char *talloc_parent_name(const void *ptr) return tc? tc->name : NULL; } +/* + A pool carries an in-pool object count count in the first 16 bytes. + bytes. This is done to support talloc_steal() to a parent outside of the + pool. The count includes the pool itself, so a talloc_free() on a pool will + only destroy the pool if the count has dropped to zero. A talloc_free() of a + pool member will reduce the count, and eventually also call free(3) on the + pool memory. + + The object count is not put into "struct talloc_chunk" because it is only + relevant for talloc pools and the alignment to 16 bytes would increase the + memory footprint of each talloc chunk by those 16 bytes. +*/ + +#define TALLOC_POOL_HDR_SIZE 16 + +static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) +{ + return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk)); +} + +/* + Allocate from a pool +*/ + +static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, + size_t size) +{ + struct talloc_chunk *pool_ctx = NULL; + size_t space_left; + struct talloc_chunk *result; + size_t chunk_size; + + if (parent == NULL) { + return NULL; + } + + if (parent->flags & TALLOC_FLAG_POOL) { + pool_ctx = parent; + } + else if (parent->flags & TALLOC_FLAG_POOLMEM) { + pool_ctx = (struct talloc_chunk *)parent->pool; + } + + if (pool_ctx == NULL) { + return NULL; + } + + space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) + - ((char *)pool_ctx->pool); + + /* + * Align size to 16 bytes + */ + chunk_size = ((size + 15) & ~15); + + if (space_left < chunk_size) { + return NULL; + } + + result = (struct talloc_chunk *)pool_ctx->pool; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(result, size); +#endif + + pool_ctx->pool = (void *)((char *)result + chunk_size); + + result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; + result->pool = pool_ctx; + + *talloc_pool_objectcount(pool_ctx) += 1; + + return result; +} + /* Allocate a bit of memory as a child of an existing pointer */ static inline void *__talloc(const void *context, size_t size) { - struct talloc_chunk *tc; + struct talloc_chunk *tc = NULL; if (unlikely(context == NULL)) { context = null_context; @@ -215,11 +305,19 @@ static inline void *__talloc(const void *context, size_t size) return NULL; } - tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); - if (unlikely(tc == NULL)) return NULL; + if (context != NULL) { + tc = talloc_alloc_pool(talloc_chunk_from_ptr(context), + TC_HDR_SIZE+size); + } + + if (tc == NULL) { + tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); + if (unlikely(tc == NULL)) return NULL; + tc->flags = TALLOC_MAGIC; + tc->pool = NULL; + } tc->size = size; - tc->flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -246,6 +344,33 @@ static inline void *__talloc(const void *context, size_t size) } /* + * Create a talloc pool + */ + +void *talloc_pool(const void *context, size_t size) +{ + void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); + struct talloc_chunk *tc; + + if (unlikely(result == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(result); + + tc->flags |= TALLOC_FLAG_POOL; + tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE; + + *talloc_pool_objectcount(tc) = 1; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); +#endif + + return result; +} + +/* setup a destructor to be called on free of a pointer the destructor should return 0 on success, or -1 on failure. if the destructor fails then the free is failed, and the memory can @@ -420,7 +545,29 @@ static inline int _talloc_free(void *ptr) } tc->flags |= TALLOC_FLAG_FREE; - free(tc); + + if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { + struct talloc_chunk *pool; + unsigned int *pool_object_count; + + pool = (tc->flags & TALLOC_FLAG_POOL) + ? tc : (struct talloc_chunk *)tc->pool; + + pool_object_count = talloc_pool_objectcount(pool); + + if (*pool_object_count == 0) { + TALLOC_ABORT("Pool object count zero!"); + } + + *pool_object_count -= 1; + + if (*pool_object_count == 0) { + free(pool); + } + } + else { + free(tc); + } return 0; } @@ -718,6 +865,15 @@ void talloc_free_children(void *ptr) talloc_steal(new_parent, child); } } + + if ((tc->flags & TALLOC_FLAG_POOL) + && (*talloc_pool_objectcount(tc) == 1)) { + tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE); +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS( + tc->pool, tc->size - TALLOC_POOL_HDR_SIZE); +#endif + } } /* @@ -769,6 +925,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n { struct talloc_chunk *tc; void *new_ptr; + bool malloced = false; /* size zero is equivalent to free() */ if (unlikely(size == 0)) { @@ -792,6 +949,12 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n return NULL; } + /* don't shrink if we have less than 1k to gain */ + if ((size < tc->size) && ((tc->size - size) < 1024)) { + tc->size = size; + return ptr; + } + /* by resetting magic we catch users of the old memory */ tc->flags |= TALLOC_FLAG_FREE; @@ -802,7 +965,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n free(tc); } #else - new_ptr = realloc(tc, size + TC_HDR_SIZE); + if (tc->flags & TALLOC_FLAG_POOLMEM) { + + new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); + *talloc_pool_objectcount((struct talloc_chunk *) + (tc->pool)) -= 1; + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + } + } + else { + new_ptr = realloc(tc, size + TC_HDR_SIZE); + } #endif if (unlikely(!new_ptr)) { tc->flags &= ~TALLOC_FLAG_FREE; @@ -810,7 +990,10 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } tc = (struct talloc_chunk *)new_ptr; - tc->flags &= ~TALLOC_FLAG_FREE; + tc->flags &= ~TALLOC_FLAG_FREE; + if (malloced) { + tc->flags &= ~TALLOC_FLAG_POOLMEM; + } if (tc->parent) { tc->parent->child = tc; } diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index e103391681..5431971655 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -116,6 +116,7 @@ typedef void TALLOC_CTX; /* The following definitions come from talloc.c */ void *_talloc(const void *context, size_t size); +void *talloc_pool(const void *context, size_t size); void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)); int talloc_increase_ref_count(const void *ptr); size_t talloc_reference_count(const void *ptr); diff --git a/source4/lib/talloc/talloc.mk b/source4/lib/talloc/talloc.mk new file mode 100644 index 0000000000..e1fe88c84b --- /dev/null +++ b/source4/lib/talloc/talloc.mk @@ -0,0 +1,37 @@ +TALLOC_OBJ = $(tallocdir)/talloc.o + +TALLOC_SOLIB = libtalloc.$(SHLIBEXT).$(PACKAGE_VERSION) +TALLOC_SONAME = libtalloc.$(SHLIBEXT).1 + +all:: libtalloc.a $(TALLOC_SOLIB) testsuite + +testsuite:: $(LIBOBJ) testsuite.o + $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) + +libtalloc.a: $(LIBOBJ) + ar -rv $@ $(LIBOBJ) + @-ranlib $@ + +install:: all + ${INSTALLCMD} -d $(DESTDIR)$(libdir) + ${INSTALLCMD} -d $(DESTDIR)$(libdir)/pkgconfig + ${INSTALLCMD} -m 755 libtalloc.a $(DESTDIR)$(libdir) + ${INSTALLCMD} -m 755 $(TALLOC_SOLIB) $(DESTDIR)$(libdir) + ${INSTALLCMD} -d $(DESTDIR)${includedir} + ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(DESTDIR)$(includedir) + ${INSTALLCMD} -m 644 talloc.pc $(DESTDIR)$(libdir)/pkgconfig + if [ -f talloc.3 ];then ${INSTALLCMD} -d $(DESTDIR)$(mandir)/man3; fi + if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(DESTDIR)$(mandir)/man3; fi + which swig >/dev/null 2>&1 && ${INSTALLCMD} -d $(DESTDIR)`swig -swiglib` || true + which swig >/dev/null 2>&1 && ${INSTALLCMD} -m 644 talloc.i $(DESTDIR)`swig -swiglib` || true + +doc:: talloc.3 talloc.3.html + +clean:: + rm -f *~ $(LIBOBJ) $(TALLOC_SOLIB) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html + +test:: testsuite + ./testsuite + +gcov:: + gcov talloc.c diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index e16c91f8b9..fedbda95aa 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -813,6 +813,25 @@ static bool test_speed(void) talloc_free(ctx); + ctx = talloc_pool(NULL, 1024); + + tv = timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + for (i=0;i<loop;i++) { + p1 = talloc_size(ctx, loop % 100); + p2 = talloc_strdup(p1, "foo bar"); + p3 = talloc_size(p1, 300); + talloc_free_children(ctx); + } + count += 3 * loop; + } while (timeval_elapsed(&tv) < 5.0); + + talloc_free(ctx); + + fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + tv = timeval_current(); count = 0; do { @@ -1066,6 +1085,23 @@ static bool test_autofree(void) return true; } +static bool test_pool(void) +{ + void *pool; + void *p1, *p2, *p3, *p4; + + pool = talloc_pool(NULL, 1024); + + p1 = talloc_size(pool, 80); + p2 = talloc_size(pool, 20); + p3 = talloc_size(p1, 50); + p4 = talloc_size(p3, 1000); + + talloc_free(pool); + + return true; +} + struct torture_context; bool torture_local_talloc(struct torture_context *tctx) { @@ -1094,6 +1130,7 @@ bool torture_local_talloc(struct torture_context *tctx) ret &= test_free_parent_deny_child(); ret &= test_talloc_ptrtype(); ret &= test_talloc_free_in_destructor(); + ret &= test_pool(); if (ret) { ret &= test_speed(); diff --git a/source4/lib/talloc/web/index.html b/source4/lib/talloc/web/index.html index 106920e8a5..628030ad4c 100644 --- a/source4/lib/talloc/web/index.html +++ b/source4/lib/talloc/web/index.html @@ -12,7 +12,7 @@ destructors. It is the core memory allocator used in Samba4, and has made a huge difference in many aspects of Samba4 development.<p> To get started with talloc, I would recommend you read the <a -href="http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt">talloc guide</a>. +href="http://samba.org/ftp/unpacked/samba_4_0_test/source/lib/talloc/talloc_guide.txt">talloc guide</a>. <h2>Discussion and bug reports</h2> @@ -24,19 +24,20 @@ bugzilla</a> bug tracking system. <h2>Download</h2> -You can download the latest release either via rsync or anonymous -svn. To fetch via svn use the following command: +You can download the latest release either via rsync or git. +To fetch via git use the following command: <pre> - svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc - svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/replace libreplace + git-clone git://git.samba.org/samba.git samba + cd samba + git checkout -b samba4 origin/v4-0-test </pre> To fetch via rsync use this command: <pre> - rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc . - rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/libreplace . + rsync -Pavz samba.org::ftp/unpacked/samba_4_0_test/source/lib/talloc . + rsync -Pavz samba.org::ftp/unpacked/samba_4_0_test/source/lib/libreplace . </pre> <hr> |