void lib_init(void) { struct timeval tv; /* standard way to get rand() return different values. */ if (gettimeofday(&tv, NULL) < 0) i_fatal("gettimeofday(): %m"); srand((unsigned int) (tv.tv_sec ^ tv.tv_usec ^ getpid())); data_stack_init(); hostpid_init(); }
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; data_stack_init(); return t_push(); } frame_pos = 0; if (unused_frame_blocks == NULL) { /* allocate new block */ #ifndef USE_GC frame_block = calloc(sizeof(*frame_block), 1); #else frame_block = GC_malloc(sizeof(*frame_block)); #endif if (frame_block == NULL) { i_fatal_status(FATAL_OUTOFMEM, "t_push(): Out of memory"); } } else { /* use existing unused frame_block */ frame_block = unused_frame_blocks; unused_frame_blocks = unused_frame_blocks->prev; } frame_block->prev = current_frame_block; current_frame_block = frame_block; } data_stack_last_buffer_reset(FALSE); /* mark our current position */ current_frame_block->block[frame_pos] = current_block; current_frame_block->block_space_used[frame_pos] = current_block->left; current_frame_block->last_alloc_size[frame_pos] = 0; return data_stack_frame++; }
static void *t_malloc_real(size_t size, bool permanent) { struct stack_block *block; void *ret; size_t alloc_size; #ifdef DEBUG bool warn = FALSE; #endif if (unlikely(size == 0 || size > SSIZE_T_MAX)) i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size); if (unlikely(data_stack_frame == 0)) { /* kludgy, but allow this before initialization */ data_stack_init(); } /* allocate only aligned amount of memory so alignment comes always properly */ #ifndef DEBUG alloc_size = MEM_ALIGN(size); #else alloc_size = MEM_ALIGN(sizeof(size)) + MEM_ALIGN(size + SENTRY_COUNT); #endif data_stack_last_buffer_reset(TRUE); /* used for t_try_realloc() */ current_frame_block->last_alloc_size[frame_pos] = alloc_size; if (current_block->left >= alloc_size) { /* enough space in current block, use it */ ret = STACK_BLOCK_DATA(current_block) + (current_block->size - current_block->left); if (current_block->left - alloc_size < current_block->lowwater) { current_block->lowwater = current_block->left - alloc_size; } if (permanent) current_block->left -= alloc_size; } else { /* current block is full, see if we can use the unused_block */ if (unused_block != NULL && unused_block->size >= alloc_size) { block = unused_block; unused_block = NULL; } else { block = mem_block_alloc(alloc_size); #ifdef DEBUG warn = TRUE; #endif } block->left = block->size; if (block->left - alloc_size < block->lowwater) block->lowwater = block->left - alloc_size; if (permanent) block->left -= alloc_size; block->next = NULL; current_block->next = block; current_block = block; ret = STACK_BLOCK_DATA(current_block); #ifdef DEBUG if (warn && getenv("DEBUG_SILENT") == NULL) { /* warn after allocation, so if i_warning() wants to allocate more memory we don't go to infinite loop */ i_warning("Growing data stack with: %"PRIuSIZE_T, block->size); } #endif } #ifdef DEBUG memcpy(ret, &size, sizeof(size)); ret = PTR_OFFSET(ret, MEM_ALIGN(sizeof(size))); /* make sure the sentry contains CLEAR_CHRs. it might not if we had used t_buffer_get(). */ memset(PTR_OFFSET(ret, size), CLEAR_CHR, MEM_ALIGN(size + SENTRY_COUNT) - size); #endif return ret; }