data-stack.c revision c9fae156bb2dd1f4d1e2632cb396d630a9efb0c1
/*
data-stack.c : Data stack implementation
Copyright (c) 2001-2002 Timo Sirainen
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "lib.h"
#include "data-stack.h"
#include <stdlib.h>
/* Use malloc() and free() for all memory allocations. Useful for debugging
memory corruption. */
/* #define DISABLE_DATA_STACK */
#ifndef DISABLE_DATA_STACK
/* Max. number of bytes to even try to allocate. This is done just to avoid
allocating less memory than was actually requested because of integer
overflows. */
#define MAX_ALLOC_SIZE SSIZE_T_MAX
/* Initial stack size - this should be kept in a size that doesn't exceed
in a normal use to avoid extra malloc()ing. */
typedef struct _StackBlock StackBlock;
typedef struct _StackFrameBlock StackFrameBlock;
struct _StackBlock {
/* unsigned char data[]; */
};
#define STACK_BLOCK_DATA(block) \
((char *) (block) + SIZEOF_MEMBLOCK)
/* current_frame_block contains last t_push()ed frames. After that new
StackFrameBlock is created and it's ->prev is set to current_frame_block. */
#define BLOCK_FRAME_COUNT 32
struct _StackFrameBlock {
};
unsigned int data_stack_frame;
static int frame_pos; /* current frame position current_frame_block */
static StackBlock *last_buffer_block;
static size_t last_buffer_size;
unsigned int t_push(void)
{
frame_pos++;
if (frame_pos == BLOCK_FRAME_COUNT) {
/* frame block full */
frame_pos = 0;
if (unused_frame_blocks == NULL) {
/* allocate new block */
if (frame_block == NULL)
i_panic("t_push(): Out of memory");
} else {
/* use existing unused frame_block */
}
}
/* mark our current position */
return data_stack_frame++;
}
{
/* free all the blocks, except if any of them is bigger than
unused_block, replace it */
} else {
}
}
}
unsigned int t_pop(void)
{
int popped_frame_pos;
if (frame_pos < 0)
i_panic("t_pop() called with empty stack");
/* update the current block */
/* free unused blocks */
}
if (frame_pos > 0)
frame_pos--;
else {
/* frame block is now unused, add it to unused list */
}
return --data_stack_frame;
}
{
i_panic("mem_block_alloc(): "
}
return block;
}
{
void *ret;
if (size == 0)
return NULL;
if (size > MAX_ALLOC_SIZE)
i_panic("Trying to allocate too much memory");
/* 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 {
}
if (permanent)
return STACK_BLOCK_DATA(current_block);
}
{
}
{
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)
{
data_stack_frame = 0;
t_push();
last_buffer_size = 0;
}
void data_stack_deinit(void)
{
t_pop();
i_panic("Missing t_pop() call");
while (unused_frame_blocks != NULL) {
}
}
#else
typedef struct _StackFrame StackFrame;
typedef struct _FrameAlloc FrameAlloc;
struct _StackFrame {
};
struct _FrameAlloc {
void *mem;
};
static StackFrame *current_frame;
static void *buffer_mem;
unsigned int t_push(void)
{
i_panic("t_push(): Out of memory");
return data_stack_frame++;
}
unsigned int t_pop(void)
{
}
return --data_stack_frame;
}
{
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;
}
{
void *new_mem;
return TRUE;
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