## -*-Makefile-*-
##
-## $Id: Makefile.am,v 1.36 2003/05/18 15:17:04 mdw Exp $
+## $Id: Makefile.am,v 1.37 2003/10/12 14:44:46 mdw Exp $
##
## Building the distribution
##
##----- Revision history ----------------------------------------------------
##
## $Log: Makefile.am,v $
+## Revision 1.37 2003/10/12 14:44:46 mdw
+## Various fixes.
+##
## Revision 1.36 2003/05/18 15:17:04 mdw
## Version bump.
##
pkglibexec_PROGRAMS = bres
pkginclude_HEADERS = \
- alloc.h arena.h bits.h exc.h quis.h report.h sub.h trace.h track.h \
+ align.h alloc.h arena.h bits.h exc.h quis.h report.h sub.h \
+ trace.h track.h unihash.h \
pool.h \
atom.h assoc.h darray.h dstr.h dspool.h hash.h sym.h crc32.h \
env.h fdflags.h fwatch.h lock.h \
libmLib_la_SOURCES = \
alloc.c arena.c exc.c quis.c pquis.c report.c sub.c trace.c \
- traceopt.c track.c \
+ traceopt.c track.c unihash.c \
pool.c pool-file.c pool-sub.c \
atom.c assoc.c darray.c dstr.c dputf.c dspool.c hash.c sym.c \
crc32.c crc32-tab.c \
da_t_LDADD = libmLib.la
da_t_LDFLAGS = -static
da.in: $(srcdir)/da-gtest
- perl $(srcdir)/da-gtest 10000 >da.in
+ perl $(srcdir)/da-gtest 10000 >da.in.new
+ mv da.in.new da.in
da.ref: da.in $(srcdir)/da-ref
- perl $(srcdir)/da-ref <da.in >da.ref
+ perl $(srcdir)/da-ref <da.in >da.ref.new
+ mv da.ref.new da.ref
da.test: da.t da.in da.ref
./da.t <da.in >da.out
cmp da.out da.ref
sym_t_LDADD = libmLib.la
sym_t_LDFLAGS = -static
sym.in: $(srcdir)/sym-gtest
- perl $(srcdir)/sym-gtest 10000 >sym.in
+ perl $(srcdir)/sym-gtest 10000 >sym.in.new
+ mv sym.in.new sym.in
sym.ref: sym.in $(srcdir)/sym-ref
- perl $(srcdir)/sym-ref <sym.in >sym.ref
+ perl $(srcdir)/sym-ref <sym.in >sym.ref.new
+ mv sym.ref.new sym.ref
sym.test: sym.t sym.in sym.ref
./sym.t <sym.in >sym.out
cmp sym.out sym.ref
.SH "RETURN VALUE"
The return value is the 32-bit CRC of the input block.
.SH "SEE ALSO"
+.BR unihash (3),
.BR mLib (3).
.SH AUTHOR
Mark Wooding, <mdw@nsict.org>
pool \- resource pool management
.\" @pool_alloc
.\" @pool_strdup
+.\" @pool_init
.\" @pool_create
.\" @pool_destroy
.\" @pool_sub
.nf
.B "#include <mLib/pool.h>"
+.BI "void pool_init(pool *" p ", arena *" a );
.BI "pool *pool_create(arena *" a );
.BI "pool *pool_sub(pool *" p );
.BI "void pool_destroy(pool *" p );
A new root pool is created using
.BR pool_create ,
passing it an arena from which it can allocate large memory blocks.
+Alternatively, you can allocate a
+.B pool
+structure from somewhere and initialize it by passing its address and an
+arena to
+.BR pool_init .
.PP
A subpool is created by calling
.BR pool_sub ,
.PP
Pools are destroyed by passing them to
.BR pool_destroy .
-Root pools are completely destroyed, since the memory containing the
-pool structure is allocated from the pool itself. Subpools, on the
-other hand, are allocated from a parent pool, and may be reused after
-being `destroyed'.
+Pools created by
+.B pool_create
+are completely destroyed, since the memory containing the pool structure
+is allocated from the pool itself. Subpools and pools allocated by the
+caller and initialized by
+.BR pool_init ,
+on the other hand, are
+allocated from a parent pool, and may be reused after being `destroyed'.
.SS "Memory allocation"
Memory is allocated from a pool by calling
.BR pool_alloc ,
.TH sub 3 "8 May 1999" "Straylight/Edgeware" "mLib utilities library"
.SH NAME
sub \- efficient allocation and freeing of small blocks
+.\" @subarena_create
+.\" @subarena_destroy
+.\" @subarena_alloc
+.\" @subarena_free
.\" @sub_alloc
.\" @sub_free
.\" @sub_init
.\"
+.\" @A_CREATE
+.\" @A_DESTROY
.\" @CREATE
.\" @DESTROY
.\"
.nf
.B "#include <mLib/sub.h>"
+.BI "void subarena_create(subarena *" s ", arena *" a );
+.BI "void subarena_destroy(subarena *" s );
+.BI "void subarena_alloc(subarena *" s ", size_t " sz );
+.BI "void subarena_free(subarena *" s ", void *" p ", size_t " sz );
+
.B "void sub_init(void);"
.BI "void *sub_alloc(size_t " sz );
.BI "void sub_free(void *" p ", size_t " sz );
+.BI "void *A_CREATE(subarena *" s ", " type );
+.BI "void A_DESTROY(subarena *" s ", " type " *" p );
.BI "void *CREATE(" type );
.BI "void DESTROY(" type " *" p );
.fi
.SH DESCRIPTION
The
-.B sub
+.B subarena
collection of functions and macros implement an efficient allocator for
-small blocks of known sizes. Free blocks of the same size are linked
-together in list, making freeing and allocation fast. The `free'
-operation requires the block size as an argument, so there's no data
-overhead for an allocated block. The system takes advantage of this by
-allocating big chunks from the underlying system (actually via
-.BR xmalloc (3),
-q.v.) and splitting the chunks into smaller blocks of the right size, so
-the space and time overhead from the underlying allocator is divided
-over many blocks.
+small blocks of known sizes, constructed from a general allocator
+implemented by an
+.BR arena (3).
+Free blocks of the same size are linked together in list, making freeing
+and allocation fast. The `free' operation requires the block size as an
+argument, so there's no data overhead for an allocated block. The
+system takes advantage of this by allocating big chunks from the
+underlying arena and splitting the chunks into smaller blocks of the
+right size, so the space and time overhead from the underlying allocator
+is divided over many blocks.
.PP
Calling
-.B sub_alloc
+.B subarena_alloc
allocates a block of
.I sz
-bytes. If there isn't enough memory to allocate the block, the
+bytes from the subarena
+.IR s .
+If there isn't enough memory to allocate the block, the
exception
.B EXC_NOMEM
is raised.
.PP
The
-.B sub_free
+.B subarena_free
function frees a block allocated by
-.BR sub_alloc .
-You must know the size of the block in advance. Note that
-.B sub_free
+.B subarena_alloc
+from the same subarena. You must know the size of the block in advance.
+Note that
+.B subarena_free
never gives memory back to the underlying allocator. Free sub-blocks
are just made available to later calls of
-.BR sub_alloc .
+.BR subarena_alloc .
.PP
-Don't try to pass blocks allocated by
-.B sub_alloc
-to
-.BR free (3);
-similarly, don't try to pass blocks allocated by
-.BR xmalloc (3)
-or
-.BR malloc (3)
-to
-.BR sub_free .
+Don't try to free blocks allocated by
+.B subarena_alloc
+to the underlying arena's
+.I free
+function, or to try freeing blocks obtained directly from the arena's
+.I alloc
+function using
+.BR subarena_free .
If you do, you'll get what you deserve.
.PP
The pair of macros
-.B CREATE
+.B A_CREATE
and
-.B DESTROY
+.B A_DESTROY
are intended to provide a slightly more natural interface to
allocation. The call
.VS
-mystruct *p = sub_alloc(sizeof(mystruct));
+mystruct *p = subarena_alloc(s, sizeof(mystruct));
.VE
can be replaced by
.VS
-mystruct p = CREATE(mystruct);
+mystruct p = A_CREATE(s, mystruct);
.VE
Similarly, the block can be freed by saying
.VS
-DESTROY(p)
+A_DESTROY(s, p)
.VE
rather than the more cumbersome
.VS
-sub_free(p, sizeof(*p));
+subarena_free(s, p, sizeof(*p));
.VE
+There is a standard subarena
+.B sub_global
+which uses
+.B arena_global
+as its underlying allocator (obtained the first time the subarena is
+used). The functions
+.B sub_alloc
+and
+.B sub_free
+and the macros
+.B CREATE
+and
+.B DESTROY
+use this subarena.
+.PP
The function
.B sub_init
-must be called before any of the other
-.B sub
-functions or macros.
+ought to be called before any of the other functions as a matter of good
+taste, but actually the system will initialize itself the first time
+it's used.
.SH "SEE ALSO"
+.BR arena (3),
.BR exc (3),
.BR alloc (3),
.BR mLib (3).
/* -*-c-*-
*
- * $Id: pool.c,v 1.1 2000/07/16 12:28:48 mdw Exp $
+ * $Id: pool.c,v 1.2 2003/10/12 14:44:46 mdw Exp $
*
* Resource pool handling
*
/*----- Revision history --------------------------------------------------*
*
* $Log: pool.c,v $
+ * Revision 1.2 2003/10/12 14:44:46 mdw
+ * Various fixes.
+ *
* Revision 1.1 2000/07/16 12:28:48 mdw
* Support for resource pools, based on the Apache model.
*
/*----- Header files ------------------------------------------------------*/
+#include "align.h"
#include "alloc.h"
#include "arena.h"
#include "pool.h"
void *p;
size_t csz, ssz;
- /* --- Round up the requested size --- *
- *
- * This assumes too much about how various objects are aligned. It could
- * do with improvement some time. This is, I believe, the only
- * nonportability in the code, and it should work on `sane' architectures
- * anyway.
- */
-
-#define ROUNDUP(sz) ((sz + 15) % 16)
-
- sz = ROUNDUP(sz);
-
/* --- See if there's enough space --- *
*
* The chunks are sorted by available space, so if there's not enough space
* in the first chunk there isn't enough space anywhere.
*/
+ ALIGN(sz);
c = *cc;
if (c && c->left >= sz) {
p = c->p;
*/
else {
- ssz = ROUNDUP(sizeof(pool_chunk));
- csz = (ssz + sz + POOL_CHUNKSZ - 1) % POOL_CHUNKSZ;
- p = x_alloc(a, csz);
+ ssz = sizeof(pool_chunk);
+ ALIGN(ssz);
+ csz = (ssz + sz + POOL_CHUNKSZ - 1); csz -= csz % POOL_CHUNKSZ;
+ c = x_alloc(a, csz);
p = (char *)c + ssz;
c->p = (char *)p + sz;
c->left = csz - ssz - sz;
/* --- Done --- */
return (p);
-
-#undef ROUNDUP
}
/* --- @pool_alloc@ --- *
static arena_ops pool_ops = { palloc, arena_fakerealloc, pfree, 0 };
+/* --- @pool_init@ --- *
+ *
+ * Arguments: @pool *p@ = pointer to the pool structure to initialize
+ * @arena *a@ = pointer to an arena to allocate memory from
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a chunk of memory as a resource pool which is not
+ * a child of any other resource pool.
+ */
+
+void pool_init(pool *p, arena *a)
+{
+ p->a.ops = &pool_ops;
+ p->c = 0;
+ p->r = 0;
+ p->pa = a;
+}
+
/* --- @pool_create@ --- *
*
* Arguments: @arena *a@ = pointer to an arena to allocate memory from
{
pool_chunk *c = 0;
pool *p = doalloc(a, &c, sizeof(pool));
- p->a.ops = &pool_ops;
+ pool_init(p, a);
p->c = c;
- p->r = 0;
- p->pa = a;
return (p);
}
* Returns: ---
*
* Use: Destroys a pool, freeing all of the resources within it. If
- * this is a root pool, its memory will be deallocated; if it's
- * a subpool, it is emptied and can be used again.
+ * this is a pool created by @pool_create@, its memory will be
+ * deallocated; if it's a subpool or it was initialized by
+ * @pool_init@, it is emptied and can be used again.
*/
void pool_destroy(pool *p)
/* -*-c-*-
*
- * $Id: sub.c,v 1.7 2003/05/18 15:10:20 mdw Exp $
+ * $Id: sub.c,v 1.8 2003/10/12 14:44:46 mdw Exp $
*
* Allocation of known-size blocks
*
/*----- Revision history --------------------------------------------------*
*
* $Log: sub.c,v $
+ * Revision 1.8 2003/10/12 14:44:46 mdw
+ * Various fixes.
+ *
* Revision 1.7 2003/05/18 15:10:20 mdw
* Add debugging mode which just uses the underlying arena.
*
p = *(void **)q;
A_FREE(s->a, q);
}
+ s->bin[i] = 0;
}
#endif
/* -*-c-*-
*
- * $Id: sub.h,v 1.6 2000/06/17 10:35:51 mdw Exp $
+ * $Id: sub.h,v 1.7 2003/10/12 14:44:46 mdw Exp $
*
* Allocation of known-size blocks
*
/*----- Revision history --------------------------------------------------*
*
* $Log: sub.h,v $
+ * Revision 1.7 2003/10/12 14:44:46 mdw
+ * Various fixes.
+ *
* Revision 1.6 2000/06/17 10:35:51 mdw
* Major overhaul for arena support.
*
#include <stdlib.h>
+#ifndef MLIB_ALIGN_H
+# include "align.h"
+#endif
+
#ifndef MLIB_ARENA_H
# include "arena.h"
#endif
/* --- The granularity of bin buffers --- *
*
- * All blocks allocated by the binner are a multiple of this size. I've
- * chosen @void *@ because I need to store @void *@ things in here.
+ * All blocks allocated by the binner are a multiple of this size.
*/
-#define SUB_GRANULE sizeof(void *)
+#define SUB_GRANULE sizeof(union align)
/* --- Finding the right bin for a given size --- *
*