/* -*-c-*-
*
- * $Id: sub.c,v 1.6 2000/06/17 10:35:51 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.
+ *
* Revision 1.6 2000/06/17 10:35:51 mdw
* Major overhaul for arena support.
*
/* --- 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@ --- *
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@ --- *
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 -----------------------------------------------*/
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 ----------------------------------------------------*/