/* * $Id: ram-smalloc.c,v 0.24 1998/07/08 13:42:00 ceder Exp $ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Lysator Academic Computer Association. * * This file is part of the LysKOM server. * * LysKOM 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 1, or (at your option) * any later version. * * LysKOM 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. * * You should have received a copy of the GNU General Public License * along with LysKOM; see the file COPYING. If not, write to * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * * Please mail bug reports to bug-lyskom@lysator.liu.se. */ /* * smalloc.c * * Contains memory allocator routines * * TEST VERSION by ceder */ /* * Define DEBUG_MALLOC to get traces from smalloc, srealloc and sfree. * Run the resulting lyskomd under gdb. Source trace-mem.gdb. Run * M-x resolve-trace (from handle-malloc-dump.el) on the resulting output. */ /* #define DEBUG_MALLOC */ static const char * rcsid = "$Id: ram-smalloc.c,v 0.24 1998/07/08 13:42:00 ceder Exp $"; #include "rcs.h" USE(rcsid); #ifdef USE_GNU_MALLOC # include "malloc.h" #else # ifdef HAVE_STDLIB_H # include # endif #endif #include #include #include "exp.h" #include "s-string.h" #include "kom-types.h" #include "lyskomd.h" #include "server/smalloc.h" static int no_of_allocated_blocks = 0; #ifdef DEBUG_MALLOC static void trace_smalloc(size_t size, void *result) { printf("smalloc:\nArg: 0x%lx\nRes: 0x%lx\n", (long)size, (long)result); printf("==== end ====\n"); } #endif /* * "safe" malloc. Handles the case when malloc returns NULL. * smalloc cannot fail. */ EXPORT void * smalloc(size_t size) { unsigned int *p; p = (unsigned int *) malloc(size + 2*sizeof(unsigned int) + 2); if (p == NULL) restart_kom("Can't allocate %lu bytes.\n", (unsigned long)size); ++no_of_allocated_blocks; *p++ = SMALLOC_MAGIC_ALLOC; *p++ = size; ((unsigned char *) p)[size] = 0x89; ((unsigned char *) p)[size+1] = 0xA7; #ifdef DEBUG_MALLOC trace_smalloc(size, p); #endif return (void *) p; } #ifdef DEBUG_MALLOC static void trace_free(void *block) { printf("sfree:\nArg: 0x%lx\n", (long)block); printf("==== end ====\n"); } #endif EXPORT void sfree(void * ptr) /* it is legal to sfree a NULL pointer */ { unsigned int *ip; if ( ptr != NULL ) { #ifdef DEBUG_MALLOC trace_free(ptr); #endif ip = (unsigned int *) ptr; ip -= 2; switch (*ip) { case SMALLOC_MAGIC_ALLOC: if (((unsigned char *) (ip+2))[ip[1]] != 0x89 || ((unsigned char *) (ip+2))[ip[1]+1] != 0xA7) restart_kom("SFREE: Buffer overflow, bsize = %ul\n", ip[1]); --no_of_allocated_blocks; *ip = SMALLOC_MAGIC_FREE; free( ip ); break; case SMALLOC_MAGIC_FREE: restart_kom("SFREE: Trying to free already freed block\n"); default: restart_kom("SFREE: Illegal magic number\n"); } } } #ifdef DEBUG_MALLOC static void trace_srealloc(size_t size, void *arg, void *result) { printf("srealloc:\nSize: 0x%lx\nArg: 0x%lx\nRes: 0x%lx\n", (long)size, (long)arg, (long)result); printf("==== end ====\n"); } #endif EXPORT void * srealloc(void * ptr, size_t size) /* Never fails. It is legal to */ { /* realloc the NULL ptr. */ unsigned int * ip; unsigned int * new_ptr; if ( ptr == NULL ) return smalloc(size); ip = (unsigned int *) ptr; ip -= 2; switch (*ip) { case SMALLOC_MAGIC_ALLOC: break; case SMALLOC_MAGIC_FREE: restart_kom("SREALLOC: Trying to realloc freed block\n"); default: restart_kom("SREALLOC: Illegal magic number\n"); } if (((unsigned char *) (ip+2))[ip[1]] != 0x89 || ((unsigned char *) (ip+2))[ip[1]+1] != 0xA7) restart_kom("SREALLOC: Buffer overflow, osize = %ul, nsize = %lu.\n", ip[1], (unsigned long)size); *ip = SMALLOC_MAGIC_FREE; if ( (new_ptr = (unsigned int *) realloc((void *) ip, size+2*sizeof(unsigned int)+2) ) == NULL ) { restart_kom("Out of memory - can't realloc. ptr = %lu size = %lu.\n", (unsigned long)ptr, (unsigned long)size); } *new_ptr++ = SMALLOC_MAGIC_ALLOC; *new_ptr++ = size; ((unsigned char *) new_ptr)[size] = 0x89; ((unsigned char *) new_ptr)[size+1] = 0xA7; #ifdef DEBUG_MALLOC trace_srealloc(size, ptr, new_ptr); #endif return (void *) new_ptr; } /* * Allocate temporary memory, which is automatically freed after this * atomic call. */ static void **tmp_alloc_table = NULL; static int tmp_alloc_table_size = 0; /* Size */ static int tmp_alloc_table_use = 0; /* Used size */ EXPORT void * tmp_alloc(unsigned long size) { if ( tmp_alloc_table_size <= tmp_alloc_table_use ) { /* Need to increas table. */ tmp_alloc_table = srealloc (tmp_alloc_table, ((++tmp_alloc_table_size) * sizeof (void *))); } return (tmp_alloc_table[ tmp_alloc_table_use++ ] = smalloc (size)); } /* * Free all core which is allocated with tmp_alloc(). This is called from * end_of_atomic(). */ EXPORT void free_tmp(void) { int i; for ( i = 0; i < tmp_alloc_table_use; i++ ) { sfree ( tmp_alloc_table[ i ] ); tmp_alloc_table[ i ] = NULL; } tmp_alloc_table_use = 0; } EXPORT void free_all_tmp(void) { free_tmp(); sfree( tmp_alloc_table ); tmp_alloc_table = NULL; tmp_alloc_table_size = 0; } EXPORT void dump_smalloc_counts(FILE *stat_file) { fprintf(stat_file, "---ram-smalloc.c:\n%s%d\n", "\tAllocated blocks (grand total): ", no_of_allocated_blocks); }