From dd3c681c6a60f6f26125d6a7ce42f53c54a41101 Mon Sep 17 00:00:00 2001 From: "mostang.com!davidm" Date: Thu, 18 Jul 2002 03:58:34 +0000 Subject: [PATCH] (Logical change 1.19) --- src/mempool.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/mempool.h | 86 ++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) diff --git a/src/mempool.c b/src/mempool.c index e69de29b..083c75d9 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include + +#include + +#include "libunwind.h" +#include "mempool.h" + +#define SOSLOCK() /* XXX fix me */ +#define SOSUNLOCK() /* XXX fix me */ +#define LOCK(p) /* XXX fix me */ +#define UNLOCK(p) /* XXX fix me */ + +#define MAX_ALIGN (sizeof (long double)) +#define SOS_MEMORY_SIZE 16384 + +static char sos_memory[SOS_MEMORY_SIZE]; +static char *sos_memp = sos_memory; +static size_t pg_size = 0; + +void * +sos_alloc (size_t size) +{ + char *mem; + + size = (size + MAX_ALIGN - 1) & -MAX_ALIGN; + + mem = (char *) (((unsigned long) sos_memp + MAX_ALIGN - 1) + & -MAX_ALIGN); + if (mem + size >= sos_memory + sizeof (sos_memory)) + sos_memp = mem + size; + + if (!mem) + abort (); + + return mem; +} + +void +sos_free (void *ptr) +{ +} + +static void * +alloc_memory (size_t size) +{ + /* Hopefully, mmap() goes straight through to a system call stub... */ + void *mem = mmap (0, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem == MAP_FAILED) + return NULL; + + return mem; +} + +/* Must be called while holding the mempool lock. */ + +static void +free_object (struct mempool *pool, void *object) +{ + struct object *obj = object; + + obj->next = pool->free_list; + pool->free_list = obj; + ++pool->num_free; +} + +static void +add_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size) +{ + char *obj; + + for (obj = mem; obj + obj_size <= mem + size; obj += obj_size) + free_object (pool, obj); +} + +static void +expand (struct mempool *pool) +{ + size_t size; + char *mem; + + size = pool->chunk_size; + mem = alloc_memory (size); + if (!mem) + { + size = (pool->obj_size + pg_size - 1) & -pg_size; + mem = alloc_memory (size); + if (!mem) + { + /* last chance: try to allocate one object from the SOS memory */ + size = pool->obj_size; + mem = sos_alloc (size); + } + } + add_memory (pool, mem, size, pool->obj_size); +} + +void +mempool_init (struct mempool *pool, size_t obj_size, size_t reserve) +{ + if (pg_size == 0) + pg_size = getpagesize (); + + memset (pool, 0, sizeof (*pool)); + + /* round object-size up to integer multiple of MAX_ALIGN */ + obj_size = (obj_size + MAX_ALIGN - 1) & -MAX_ALIGN; + + if (!reserve) + { + reserve = pg_size / obj_size / 2; + if (!reserve) + reserve = 16; + } + + pool->obj_size = obj_size; + pool->reserve = reserve; + pool->chunk_size = (2*reserve*obj_size + pg_size - 1) & -pg_size; + + expand (pool); +} + +void * +mempool_alloc (struct mempool *pool) +{ + struct object *obj; + + LOCK(pool); + { + if (pool->num_free <= pool->reserve) + expand (pool); + + assert (pool->num_free > 0); + + --pool->num_free; + obj = pool->free_list; + pool->free_list = obj->next; + } + UNLOCK(pool); + return obj; +} + +void +mempool_free (struct mempool *pool, void *object) +{ + LOCK(pool); + free_object (pool, object); + UNLOCK(pool); +} diff --git a/src/mempool.h b/src/mempool.h index e69de29b..8afb2b4d 100644 --- a/src/mempool.h +++ b/src/mempool.h @@ -0,0 +1,86 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +libunwind is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +libunwind 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 General Public License for more details. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public +License. */ + +#ifndef mempool_h +#define mempool_h + +/* Memory pools provide simple memory management of fixed-size + objects. Memory pools are used for two purposes: + + o To ensure a stack can be unwound even when a process + is out of memory. + + o To ensure a stack can be unwound at any time in a + multi-threaded process (e.g., even at a time when the normal + malloc-lock is taken, possibly by the very thread that is + being unwind). + + + To achieve the second objective, memory pools allocate memory + directly via mmap() system call (or an equivalent facility). + + The first objective is accomplished by reserving memory ahead of + time. Since the memory requirements of stack unwinding generally + depends on the complexity of the procedures being unwind, there is + no absolute guarantee that unwinding will always work, but in + practice, this should not be a serious problem. */ + +#include + +#define IPREFIX UNW_PASTE(_UI,UNW_TARGET) +#define sos_alloc(s) UNW_PASTE(IPREFIX, _sos_alloc)(s) +#define sos_free(p) UNW_PASTE(IPREFIX, _sos_free)(p) +#define mempool_init(p,s,r) UNW_PASTE(IPREFIX, _mempool_init)(p,s,r) +#define mempool_alloc(p) UNW_PASTE(IPREFIX, _mempool_alloc)(p) +#define mempool_free(p,o) UNW_PASTE(IPREFIX, _mempool_free)(p,o) + +/* The mempool structure should be treated as an opaque object. It's + declared here only to enable static allocation of mempools. */ +struct mempool + { + size_t obj_size; /* object size (rounded up for alignment) */ + unsigned int reserve; /* minimum (desired) size of the free-list */ + size_t chunk_size; /* allocation granularity */ + unsigned int num_free; /* number of objects on the free-list */ + struct object + { + struct object *next; + } + *free_list; + }; + +/* Emergency allocation for one-time stuff that doesn't fit the memory + pool model. */ +extern void *sos_alloc (size_t size); +extern void sos_free (void *ptr); + +/* Initialize POOL for an object size of OBJECT_SIZE bytes. RESERVE + is the number of objects that should be reserved for use under + tight memory situations. If it is zero, mempool attempts to pick a + reasonable default value. */ +extern void mempool_init (struct mempool *pool, + size_t obj_size, size_t reserve); +extern void *mempool_alloc (struct mempool *pool); +extern void mempool_free (struct mempool *pool, void *object); + +#endif /* mempool_h */