X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/0fd574c3198e0a08b7b27972f7931d0c7deb19fb..04924ac3cbcf3fc05e1e36c98b99ae479cbfed8e:/sub.c?ds=sidebyside diff --git a/sub.c b/sub.c index 45dcac4..06570b6 100644 --- a/sub.c +++ b/sub.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: sub.c,v 1.6 2000/06/17 10:35:51 mdw Exp $ + * $Id: sub.c,v 1.9 2004/04/08 01:36:13 mdw Exp $ * * Allocation of known-size blocks * * (c) 1998 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of the mLib utilities library. * @@ -15,41 +15,18 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * mLib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with mLib; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: sub.c,v $ - * Revision 1.6 2000/06/17 10:35:51 mdw - * Major overhaul for arena support. - * - * Revision 1.5 1999/05/19 20:27:11 mdw - * Change naming to match newer mLib conventions. - * - * Revision 1.4 1999/05/13 22:48:55 mdw - * Change `-ise' to `-ize' throughout. - * - * Revision 1.3 1999/05/06 19:51:35 mdw - * Reformatted the LGPL notice a little bit. - * - * Revision 1.2 1999/05/05 18:50:31 mdw - * Change licensing conditions to LGPL. - * - * Revision 1.1.1.1 1998/06/17 23:44:42 mdw - * Initial version of mLib - * - */ - /*----- The big idea ------------------------------------------------------* * * This file provides an extra layer over @malloc@. It provides fast @@ -83,6 +60,7 @@ /* --- ANSI headers --- */ +#include #include #include #include @@ -93,6 +71,10 @@ #include "exc.h" #include "sub.h" +/*----- Configuration tweaks ----------------------------------------------*/ + +/* #define SUBARENA_TRIVIAL */ + /*----- Static variables --------------------------------------------------*/ static size_t sizes[SUB_BINS]; @@ -101,6 +83,16 @@ static size_t sizes[SUB_BINS]; subarena sub_global; +#ifdef SUBARENA_TRIVIAL + +typedef struct sub_link { + struct sub_link *next; + void *p; + size_t sz; +} sub_link; + +#endif + /*----- Main code ---------------------------------------------------------*/ /* --- @subarena_create@ --- * @@ -116,11 +108,15 @@ subarena sub_global; void subarena_create(subarena *s, arena *a) { +#ifdef SUBARENA_TRIVIAL + s->bin[0] = 0; +#else size_t i; if (!sizes[1]) sub_init(); for (i = 0; i < SUB_BINS; i++) s->bin[i] = 0; +#endif s->a = a; } @@ -136,6 +132,19 @@ void subarena_create(subarena *s, arena *a) void subarena_destroy(subarena *s) { +#ifdef SUBARENA_TRIVIAL + + sub_link *l, *ll; + + for (l = s->bin[0]; l; l = ll) { + ll = l; + a_free(s->a, l->p); + a_free(s->a, l); + } + s->bin[0] = 0; + +#else + size_t i; for (i = 0; i < SUB_BINS; i++) { void *p = s->bin[i]; @@ -144,23 +153,48 @@ void subarena_destroy(subarena *s) p = *(void **)q; A_FREE(s->a, q); } + s->bin[i] = 0; } + +#endif } /* --- @subarena_alloc@ --- * * - * Arguments: @subarena *s@ = pointer to arena + * Arguments: @subarena *s@ = pointer to arena * @size_t s@ = size of chunk wanted * - * Returns: Pointer to a block at least as large as the one wanted. + * Returns: Pointer to a block at least as large as the one wanted. * - * Use: Allocates a small block of memory from the given pool. The + * Use: Allocates a small block of memory from the given pool. The * exception @EXC_NOMEM@ is raised if the underlying arena is * full. */ void *subarena_alloc(subarena *s, size_t sz) { +#ifdef SUBARENA_TRIVIAL + + sub_link *l; + void *p; + + if (!s->a) + subarena_create(s, arena_global); + + if ((l = a_alloc(s->a, sizeof(*l))) == 0) + return (0); + if ((p = a_alloc(s->a, sz)) == 0) { + a_free(s->a, l); + return (0); + } + l->p = p; + l->sz = sz; + l->next = s->bin[0]; + s->bin[0] = l; + return (p); + +#else + int bin; void *p; @@ -168,10 +202,10 @@ void *subarena_alloc(subarena *s, size_t sz) if (!s->a) subarena_create(s, arena_global); - bin = SUB_BIN(sz); /* --- Handle oversize blocks --- */ + bin = SUB_BIN(sz); if (bin >= SUB_BINS) { void *p = A_ALLOC(s->a, sz); if (!p) @@ -207,21 +241,39 @@ void *subarena_alloc(subarena *s, size_t sz) p = s->bin[bin]; s->bin[bin] = *(void **)p; return (p); + +#endif } /* --- @subarena_free@ --- * * - * Arguments: @subarena *s@ = pointer to arena + * Arguments: @subarena *s@ = pointer to arena * @void *p@ = address of block to free - * @size_t s@ = size of block + * @size_t s@ = size of block * - * Returns: --- + * Returns: --- * - * Use: Frees a block allocated by @subarena_alloc@. + * Use: Frees a block allocated by @subarena_alloc@. */ void subarena_free(subarena *s, void *p, size_t sz) { +#ifdef SUBARENA_TRIVIAL + + sub_link *lh = s->bin[0], **l, *ll; + + for (l = &lh; *l && (*l)->p != p; l = &(*l)->next) + ; + ll = *l; + assert(ll); + assert(ll->sz == sz); + *l = ll->next; + a_free(s->a, ll); + a_free(s->a, p); + s->bin[0] = lh; + +#else + int bin = SUB_BIN(sz); if (bin >= SUB_BINS) @@ -230,44 +282,47 @@ void subarena_free(subarena *s, void *p, size_t sz) *(void **)p = s->bin[bin]; s->bin[bin] = p; } + +#endif } /*----- Compatibility stuff -----------------------------------------------*/ /* --- @sub_alloc@ --- * * - * Arguments: @size_t s@ = size of chunk wanted + * Arguments: @size_t s@ = size of chunk wanted * - * Returns: Pointer to a block at least as large as the one wanted. + * Returns: Pointer to a block at least as large as the one wanted. * - * Use: Allocates a small block of memory from the @sub_global@ pool. + * Use: Allocates a small block of memory from the @sub_global@ pool. */ void *(sub_alloc)(size_t sz) { return sub_alloc(sz); } /* --- @sub_free@ --- * * - * Arguments: @void *p@ = address of block to free - * @size_t s@ = size of block + * Arguments: @void *p@ = address of block to free + * @size_t s@ = size of block * - * Returns: --- + * Returns: --- * - * Use: Frees a block allocated by @sub_alloc@. + * Use: Frees a block allocated by @sub_alloc@. */ void (sub_free)(void *p, size_t sz) { sub_free(p, sz); } /* --- @sub_init@ --- * * - * Arguments: --- + * Arguments: --- * - * Returns: --- + * Returns: --- * - * Use: Initializes the magic allocator. + * Use: Initializes the magic allocator. */ void sub_init(void) { +#ifndef SUBARENA_TRIVIAL int i; /* --- Initialize the sizes bins --- */ @@ -276,6 +331,7 @@ void sub_init(void) sizes[i] = ((SUB_CHUNK + SUB_BINSZ(i) - 1) / SUB_BINSZ(i) * SUB_BINSZ(i)); } +#endif } /*----- Debugging code ----------------------------------------------------*/