data-stack.c revision 8afe3f0e832b8b3483b692205bbd59c0110a20fd
/* Copyright (c) 2002-2003 Timo Sirainen */
/* @UNSAFE: whole file */
#include "lib.h"
#include "data-stack.h"
#include <stdlib.h>
#ifdef HAVE_GC_GC_H
# include <gc.h>
#endif
/* Use malloc() and free() for all memory allocations. Useful for debugging
memory corruption. */
/* #define DISABLE_DATA_STACK */
#ifndef DISABLE_DATA_STACK
/* Initial stack size - this should be kept in a size that doesn't exceed
in a normal use to avoid extra malloc()ing. */
#ifdef DEBUG
#else
#endif
#ifdef DEBUG
# define CLEAR_CHR 0xde
# define CLEAR_CHR 0
#endif
struct stack_block {
struct stack_block *next;
/* unsigned char data[]; */
};
#define STACK_BLOCK_DATA(block) \
((char *) (block) + SIZEOF_MEMBLOCK)
/* current_frame_block contains last t_push()ed frames. After that new
stack_frame_block is created and it's ->prev is set to
current_frame_block. */
#define BLOCK_FRAME_COUNT 32
struct stack_frame_block {
struct stack_frame_block *prev;
};
unsigned int data_stack_frame = 0;
static struct stack_frame_block *current_frame_block;
static struct stack_frame_block *unused_frame_blocks;
static struct stack_block *last_buffer_block;
static size_t last_buffer_size;
unsigned int t_push(void)
{
struct stack_frame_block *frame_block;
frame_pos++;
if (frame_pos == BLOCK_FRAME_COUNT) {
/* frame block full */
if (data_stack_frame == 0) {
/* kludgy, but allow this before initialization */
frame_pos = 0;
return t_push();
}
frame_pos = 0;
if (unused_frame_blocks == NULL) {
/* allocate new block */
#ifndef USE_GC
#else
#endif
if (frame_block == NULL) {
"t_push(): Out of memory");
}
} else {
/* use existing unused frame_block */
}
}
/* mark our current position */
return data_stack_frame++;
}
#ifndef USE_GC
{
struct stack_block *next;
/* free all the blocks, except if any of them is bigger than
unused_block, replace it */
} else {
}
}
}
#endif
unsigned int t_pop(void)
{
struct stack_frame_block *frame_block;
int popped_frame_pos;
if (frame_pos < 0)
i_panic("t_pop() called with empty stack");
/* update the current block */
#ifdef CLEAR_CHR
#endif
/* free unused blocks */
#ifndef USE_GC
#endif
}
if (frame_pos > 0)
frame_pos--;
else {
/* frame block is now unused, add it to unused list */
}
return --data_stack_frame;
}
{
struct stack_block *block;
#ifndef USE_GC
#else
#endif
"Out of memory when allocating %"PRIuSIZE_T
}
return block;
}
{
struct stack_block *block;
void *ret;
#ifdef DEBUG
#endif
if (data_stack_frame == 0) {
/* kludgy, but allow this before initialization */
}
/* reset t_buffer_get() mark - not really needed but makes it easier
to notice if t_malloc() is called between t_buffer_get() and
t_buffer_alloc() */
/* allocate only aligned amount of memory so alignment comes
always properly */
/* used for t_try_realloc() */
/* enough space in current block, use it */
if (permanent)
return ret;
}
/* current block is full, see if we can use the unused_block */
unused_block = NULL;
} else {
#ifdef DEBUG
#endif
}
if (permanent)
#ifdef DEBUG
if (warn) {
/* warn later, so that if i_warning() wants to allocate more
memory we don't go to infinite loop */
}
#endif
return ret;
}
{
}
{
void *mem;
return mem;
}
{
/* see if we're trying to grow the memory we allocated last */
if (STACK_BLOCK_DATA(current_block) +
last_alloc_size) == mem) {
/* yeah, see if we have space to grow */
/* just shrink the available size */
return TRUE;
}
}
return FALSE;
}
{
void *ret;
return ret;
}
{
void *new_buffer;
return buffer;
if (new_buffer != buffer)
return new_buffer;
}
{
/* we've already reserved the space, now we just mark it used */
}
void data_stack_init(void)
{
if (data_stack_frame == 0) {
data_stack_frame = 1;
last_buffer_size = 0;
}
t_push();
}
void data_stack_deinit(void)
{
t_pop();
i_panic("Missing t_pop() call");
#ifndef USE_GC
while (unused_frame_blocks != NULL) {
}
#endif
unused_block = NULL;
}
#else
#ifdef USE_GC
#endif
struct stack_frame {
struct stack_frame *next;
struct frame_alloc *allocs;
};
struct frame_alloc {
struct frame_alloc *next;
void *mem;
};
unsigned int data_stack_frame;
static struct stack_frame *current_frame;
static void *buffer_mem;
unsigned int t_push(void)
{
struct stack_frame *frame;
i_panic("t_push(): Out of memory");
return data_stack_frame++;
}
unsigned int t_pop(void)
{
struct stack_frame *frame;
struct frame_alloc *alloc;
}
return --data_stack_frame;
}
{
struct frame_alloc *alloc;
i_panic("add_alloc(): Out of memory");
if (buffer_mem != NULL) {
buffer_mem = NULL;
}
}
{
void *mem;
i_panic("t_malloc(): Out of memory");
return mem;
}
{
void *mem;
i_panic("t_malloc0(): Out of memory");
return mem;
}
{
return FALSE;
}
{
if (buffer_mem == NULL)
i_panic("t_buffer_get(): Out of memory");
return buffer_mem;
}
{
if (buffer_mem == NULL)
i_panic("t_buffer_reget(): Out of memory");
return buffer_mem;
}
{
void *mem;
i_panic("t_buffer_alloc(): Out of memory");
buffer_mem = NULL;
}
void data_stack_init(void)
{
data_stack_frame = 0;
buffer_mem = NULL;
t_push();
}
void data_stack_deinit(void)
{
t_pop();
if (data_stack_frame != 0)
i_panic("Missing t_pop() call");
}
#endif