root/lib/libsa/alloc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. alloc
  2. free

    1 /*      $OpenBSD: alloc.c,v 1.9 2003/08/11 06:23:09 deraadt Exp $       */
    2 /*      $NetBSD: alloc.c,v 1.6 1997/02/04 18:36:33 thorpej Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
    6  * Copyright (c) 1996
    7  *      Matthias Drochner.  All rights reserved.
    8  * Copyright (c) 1993
    9  *      The Regents of the University of California.  All rights reserved.
   10  *
   11  * This code is derived from software contributed to Berkeley by
   12  * The Mach Operating System project at Carnegie-Mellon University.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)alloc.c     8.1 (Berkeley) 6/11/93
   39  *
   40  *
   41  * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
   42  * All Rights Reserved.
   43  *
   44  * Author: Alessandro Forin
   45  *
   46  * Permission to use, copy, modify and distribute this software and its
   47  * documentation is hereby granted, provided that both the copyright
   48  * notice and this permission notice appear in all copies of the
   49  * software, derivative works or modified versions, and any portions
   50  * thereof, and that both notices appear in supporting documentation.
   51  *
   52  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   53  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   54  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   55  *
   56  * Carnegie Mellon requests users of this software to return to
   57  *
   58  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   59  *  School of Computer Science
   60  *  Carnegie Mellon University
   61  *  Pittsburgh PA 15213-3890
   62  *
   63  * any improvements or extensions that they make and grant Carnegie the
   64  * rights to redistribute these changes.
   65  */
   66 
   67 /*
   68  * Dynamic memory allocator.
   69  *
   70  * Compile options:
   71  *
   72  *      ALLOC_TRACE     enable tracing of allocations/deallocations
   73  *
   74  *      ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than
   75  *                      the default best-fit algorithm.
   76  *
   77  *      HEAP_LIMIT      heap limit address (defaults to "no limit").
   78  *
   79  *      HEAP_START      start address of heap (defaults to '&end').
   80  *
   81  *      DEBUG           enable debugging sanity checks.
   82  */
   83 
   84 #include <sys/param.h>
   85 
   86 /*
   87  * Each block actually has ALIGN(unsigned) + ALIGN(size) bytes allocated
   88  * to it, as follows:
   89  *
   90  * 0 ... (sizeof(unsigned) - 1)
   91  *      allocated or unallocated: holds size of user-data part of block.
   92  *
   93  * sizeof(unsigned) ... (ALIGN(sizeof(unsigned)) - 1)
   94  *      allocated: unused
   95  *      unallocated: depends on packing of struct fl
   96  *
   97  * ALIGN(sizeof(unsigned)) ... (ALIGN(sizeof(unsigned)) + ALIGN(data size) - 1)
   98  *      allocated: user data
   99  *      unallocated: depends on packing of struct fl
  100  *
  101  * 'next' is only used when the block is unallocated (i.e. on the free list).
  102  * However, note that ALIGN(sizeof(unsigned)) + ALIGN(data size) must
  103  * be at least 'sizeof(struct fl)', so that blocks can be used as structures
  104  * when on the free list.
  105  */
  106 
  107 #include "stand.h"
  108 
  109 struct fl {
  110         unsigned        size;
  111         struct fl       *next;
  112 } *freelist = (struct fl *)0;
  113 
  114 #ifdef HEAP_START
  115 static char *top = (char *)HEAP_START;
  116 #else
  117 extern char end[];
  118 static char *top = end;
  119 #endif
  120 
  121 void *
  122 alloc(unsigned int size)
  123 {
  124         struct fl **f = &freelist, **bestf = NULL;
  125 #ifndef ALLOC_FIRST_FIT
  126         unsigned bestsize = 0xffffffff; /* greater than any real size */
  127 #endif
  128         char *help;
  129         int failed;
  130 
  131 #ifdef ALLOC_TRACE
  132         printf("alloc(%u)", size);
  133 #endif
  134 
  135 #ifdef ALLOC_FIRST_FIT
  136         while (*f != (struct fl *)0 && (*f)->size < size)
  137                 f = &((*f)->next);
  138         bestf = f;
  139         failed = (*bestf == (struct fl *)0);
  140 #else
  141         /* scan freelist */
  142         while (*f) {
  143                 if ((*f)->size >= size) {
  144                         if ((*f)->size == size) /* exact match */
  145                                 goto found;
  146 
  147                         if ((*f)->size < bestsize) {
  148                                 /* keep best fit */
  149                                 bestf = f;
  150                                 bestsize = (*f)->size;
  151                         }
  152                 }
  153                 f = &((*f)->next);
  154         }
  155 
  156         /* no match in freelist if bestsize unchanged */
  157         failed = (bestsize == 0xffffffff);
  158 #endif
  159 
  160         if (failed) { /* nothing found */
  161                 /*
  162                  * allocate from heap, keep chunk len in
  163                  * first word
  164                  */
  165                 help = top;
  166 
  167                 /* make _sure_ the region can hold a struct fl. */
  168                 if (size < ALIGN(sizeof (struct fl *)))
  169                         size = ALIGN(sizeof (struct fl *));
  170                 top += ALIGN(sizeof(unsigned)) + ALIGN(size);
  171 #ifdef HEAP_LIMIT
  172                 if (top > (char *)HEAP_LIMIT)
  173                         panic("heap full (0x%lx+%u)", help, size);
  174 #endif
  175                 *(unsigned *)help = ALIGN(size);
  176 #ifdef ALLOC_TRACE
  177                 printf("=%p\n", help + ALIGN(sizeof(unsigned)));
  178 #endif
  179                 return(help + ALIGN(sizeof(unsigned)));
  180         }
  181 
  182         /* we take the best fit */
  183         f = bestf;
  184 
  185 #ifndef ALLOC_FIRST_FIT
  186 found:
  187 #endif
  188         /* remove from freelist */
  189         help = (char *)*f;
  190         *f = (*f)->next;
  191 #ifdef ALLOC_TRACE
  192         printf("=%p (origsize %u)\n", help + ALIGN(sizeof(unsigned)),
  193             *(unsigned *)help);
  194 #endif
  195         return(help + ALIGN(sizeof(unsigned)));
  196 }
  197 
  198 void
  199 free(void *ptr, unsigned int size)
  200 {
  201         struct fl *f = (struct fl *)((char *)ptr -
  202             ALIGN(sizeof(unsigned)));
  203 
  204 #ifdef ALLOC_TRACE
  205         printf("free(%p, %u) (origsize %u)\n", ptr, size, f->size);
  206 #endif
  207 #ifdef DEBUG
  208         if (size > f->size)
  209                 printf("free %u bytes @%p, should be <=%u\n",
  210                     size, ptr, f->size);
  211 #ifdef HEAP_START
  212         if (ptr < (void *)HEAP_START)
  213 #else
  214         if (ptr < (void *)end)
  215 #endif
  216                 printf("free: %lx before start of heap.\n", (u_long)ptr);
  217 
  218 #ifdef HEAP_LIMIT
  219         if (ptr > (void *)HEAP_LIMIT)
  220                 printf("free: %lx beyond end of heap.\n", (u_long)ptr);
  221 #endif
  222 #endif /* DEBUG */
  223         /* put into freelist */
  224         f->next = freelist;
  225         freelist = f;
  226 }

/* [<][>][^][v][top][bottom][index][help] */