/* -*-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.
*
* 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
/* --- ANSI headers --- */
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "exc.h"
#include "sub.h"
+/*----- Configuration tweaks ----------------------------------------------*/
+
+/* #define SUBARENA_TRIVIAL */
+
/*----- Static variables --------------------------------------------------*/
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@ --- *
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;
}
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];
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;
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)
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)
*(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 --- */
sizes[i] = ((SUB_CHUNK + SUB_BINSZ(i) - 1) /
SUB_BINSZ(i) * SUB_BINSZ(i));
}
+#endif
}
/*----- Debugging code ----------------------------------------------------*/