data-stack.c revision 86c99183534cba2ab402136f5cce0756aafe57b2
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* @UNSAFE: whole file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* Initial stack size - this should be kept in a size that doesn't exceed
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi in a normal use to avoid extra malloc()ing. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* unsigned char data[]; */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#define SIZEOF_MEMBLOCK MEM_ALIGN(sizeof(struct stack_block))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* current_frame_block contains last t_push()ed frames. After that new
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stack_frame_block is created and it's ->prev is set to
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi current_frame_block. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiunsigned int data_stack_frame = 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic int frame_pos = BLOCK_FRAME_COUNT-1; /* in current_frame_block */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic struct stack_frame_block *current_frame_block;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic struct stack_frame_block *unused_frame_blocks;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic struct stack_block *current_block; /* block now used for allocation */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic struct stack_block *unused_block; /* largest unused block is kept here */
unsigned int t_push(void)
frame_pos++;
if (data_stack_frame == 0) {
frame_pos = 0;
return t_push();
frame_pos = 0;
#ifndef USE_GC
return data_stack_frame++;
if (clean_after_pop)
#ifndef USE_GC
#ifndef USE_GC
#ifdef DEBUG
static void t_pop_verify(void)
pos = 0;
unsigned int t_pop(void)
int popped_frame_pos;
#ifdef DEBUG
t_pop_verify();
if (clean_after_pop) {
if (frame_pos > 0)
frame_pos--;
return --data_stack_frame;
*id = 0;
#ifndef USE_GC
if (outofmem) {
abort();
#ifdef DEBUG
return block;
void *ret;
#ifdef DEBUG
#ifndef DEBUG
if (permanent)
#ifdef DEBUG
if (permanent)
#ifdef DEBUG
if (warn) {
#ifdef DEBUG
return ret;
void *mem;
return mem;
return TRUE;
return FALSE;
void *ret;
return ret;
void *new_buffer;
return buffer;
return new_buffer;
void t_buffer_alloc_last_full(void)
#ifndef DEBUG
void data_stack_init(void)
#ifdef DEBUG
if (data_stack_frame == 0) {
last_buffer_size = 0;
t_push();
void data_stack_deinit(void)
t_pop();
#ifndef USE_GC