Main Page | Modules | Data Structures | File List | Data Fields | Globals

bmalloc.c

Go to the documentation of this file.
00001 /* BeeOS v0.1. Created: 2003/08/10 Modified: 2004/03/03
00002  * Copyright (C) 2004 Paul Harvey - ROMA, Australia.
00003  * csirac@users.sourceforge.net
00004  */
00005 
00006 /*   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation; either version 2 of the License, or
00009  *   (at your option) any later version.
00010  * 
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  * 
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with this program; if not, write to the Free Software
00018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00023 #include "../include/beeos.h"
00024 #include "../include/bbit.h"
00025 #define IN_BMEM                 /* "internal" globals, for splint */
00026 #include "../include/bmalloc.h"
00027 #include "../include/bstring.h" /* for bmemset(). */
00028 #include "../include/arch/param.h"  /* for SRAM_SIZE */
00029 /* TEMPRY */
00030 #include <stdarg.h>
00031 #include "../include/bprintf.h"
00032 
00033 #ifdef HOSTED_BUILD
00034 #include <malloc.h>
00035 #endif
00036 #ifdef BMEM_DEBUG
00037 /* #include <stdio.h> */
00038 #endif
00039 
00040 /* GLOBALS OF EVIL */
00041 #ifndef HOSTED_BUILD
00042     /*@-isoreserved@*/
00043     extern char _end;   /* set by linker: start of "free" data segment */
00044     /*@=isoreserved@*/
00045 #endif
00046 
00050 static char /*@exposed@*/ /*@null@*/ *bheap = NULL;
00055 static uchar bheap_bitmap[SRAM_NUMBLOCKS/8 + 1];    
00056 static bool lk_bmalloc; 
00057 static bool lk_bfree;       
00058 /* END GLOBALS OF EVIL */
00059 
00065 /*@external@*/ 
00066 void bmallocinit(void) 
00067     /*@globals bheap_bitmap, undef bheap@*/
00068     /*@modifies bheap@*/
00069 {   
00073 #ifndef HOSTED_BUILD
00074     bheap = (char *) &_end; 
00076 #else
00077     bheap = malloc((size_t) SRAM_NUMBLOCKS*SRAM_BLOCKSIZE);
00078 #endif
00079     /* About the line below.... not sure _end is supposed to be modified. */
00080     /*_end += (SRAM_NUMBLOCKS*SRAM_BLOCKSIZE);*/ /* update _end to after bheap*/
00081     bmemset(bheap, '\0', (ushort)SRAM_NUMBLOCKS*SRAM_BLOCKSIZE);
00082     bmemset((char *)bheap_bitmap, '\0', (ushort)SRAM_NUMBLOCKS/8);
00083     lk_bfree = false;
00084     lk_bmalloc = false;
00085 #ifdef BMEM_DEBUG
00086     /*@-nullptrarith@*/
00087     bprintf(20, "bminit: bheap %x, frm %p to %p.\r\n", 
00088         (sshort) SRAM_NUMBLOCKS*SRAM_BLOCKSIZE, (sshort) bheap, 
00089         (sshort) bheap + SRAM_NUMBLOCKS*SRAM_BLOCKSIZE);
00090     /*@=nullptrarith@*/
00091 #endif
00092     
00093     return;
00094 }
00095 
00103 /*@-redef@*/ /*@-exportlocal@*/
00104 /*@external@*/
00105 void bfree(char /*@null@*/ *addr)
00106 /*@=redef@*/ /*@-exportlocal@*/
00107 {   
00121     uchar i = (uchar) SRAM_ADDR2BLOCK(addr);
00122 /*@-nullptrarith@*/
00123     uchar end_block = 0;
00124     
00125 #ifdef BMEM_DEBUG
00126     bprintf(20, "bfr: Free %i blks @%p.\r\n", (sshort)ALLOC_NUMBLOCKS(addr), 
00127         (sshort) addr);
00128 #endif
00129 /*@=nullptrarith@*/
00130     while (lk_bfree);   /* Wait for other thread's bfree() call to finish */
00131     lk_bfree = true;
00132     end_block = (uchar) i + (uchar) ALLOC_NUMBLOCKS(addr);
00133     for (; i < end_block; i++) SRAM_BITCLR(i);
00134     lk_bfree = false;
00135     
00136     return;
00137 }
00138 
00148 /*@-redef@*/
00149 /*@null@*/ /*@exposed@*/ /*@external@*/
00150 char *bmalloc(ushort size, char /*@exposed@*/ /*@null@*/ *pExist)
00151     /*@globals bheap, bheap_bitmap@*/
00152     /*@modifies *bheap, *pExist@*/
00153 /*@=redef@*/
00154 {   
00192     char *pMem = NULL;
00193     bool tagged_a_block = false;
00194     bool blockused = false;
00195     /*NB:div. truncated so +1 */
00196     uchar reqrd_blocks = (uchar)(size + 1)/(uchar)SRAM_BLOCKSIZE;
00197     uchar i = 0, tagged_block = 0;
00198     uchar exist_block, exist_blocks;
00199 
00200     while (lk_bmalloc); /* Wait for other thread's bmalloc() call to finish. */
00201     lk_bmalloc = true;
00202     /* NB: reqrd_blocks++ if alloc. accounting byte won't fit with req. size */
00203 /*@-type@*/ /*(char) i++ non-numeric?*/
00204     if (((size + 1) % SRAM_BLOCKSIZE) != 0) reqrd_blocks++;
00205 /*@=type@*/
00206 #ifdef BREALLOC
00207     /* Deal with existing alloc'd address (IE. resize alloc. request) */
00208     if (NULL != pExist) {
00209         exist_blocks = ALLOC_NUMBLOCKS(pExist);
00210         exist_block = (uchar)SRAM_ADDR2BLOCK(pExist);
00211         if (exist_blocks == reqrd_blocks) return pExist;
00212         else if (exist_blocks < reqrd_blocks) {
00213             /* This code allows bmalloc() to reduce a previous alloc */
00214             i = (exist_blocks - reqrd_blocks);
00215             /*@-nullptrarith@*/
00216             pMem = (char *) SRAM_BLOCK2ADDR((int)exist_block + (int)i);
00217             /*@=nullptrarith@*/
00218             *((uchar *)pMem) = i;
00219             bfree(pMem + 1);
00220             ALLOC_NUMBLOCKS(pExist) = reqrd_blocks;
00221             return pExist;
00222         } else { /* This code allows bmalloc() to increase a previous alloc. */
00223             /* Start free block scan just after currently alloc'd blocks */
00224             i = exist_block + exist_blocks;
00225             tagged_block = exist_block;
00226             tagged_a_block = true;
00227         }
00228 #   ifdef BMEM_DEBUG
00229         bprintf(20, "bmal: REA: was %i, need %i.\r\n", (sshort)exist_blocks, 
00230             (sshort)reqrd_blocks);
00231 #   endif
00232     }
00233 #endif
00234     /* Loop until enough contiguous blocks are found to satisfy size required */
00235     while (i < (uchar)SRAM_NUMBLOCKS) {
00236         blockused = SRAM_BITCHECK(i);   /* Consult bitmap: check block i used */
00237         if (tagged_a_block) { /*Below, LHS: +1:include zero diff*/
00238             if ((i - tagged_block + 1) >= (ushort) reqrd_blocks) {
00239                 /* finished searching, enough blocks found*/
00240                 for (i = tagged_block; i < ((uchar) reqrd_blocks + tagged_block); i++)
00241                     SRAM_BITSET(i);     /* Mark bitmap accordingly */
00242 /*@-nullptrarith@*/
00243                 pMem = (char *) SRAM_BLOCK2ADDR(tagged_block);
00244 /*@=nullptrarith@*/
00245                 *pMem = reqrd_blocks;   /* Set accounting byte */
00246                 pMem++;                 /* The next byte is alloc'd heap space*/
00247                 break;
00248             } else if (blockused) tagged_a_block = false;   /*not enough blocks,*/
00249         } else if (!blockused) {        /* ...reset tagged_a_block, start again */
00250             tagged_a_block = true;      /* if block is free (!blockused), and */
00251             tagged_block = i;           /* haven't tagged_a_block yet, tag it */
00252         }
00253         i++;
00254     }
00255 
00256 #ifdef BMEM_DEBUG
00257     bprintf(20, "bmal: ONRET: Tag blk %i (%p) for %i blks.\r\n", 
00258         (sshort)tagged_block, (sshort) pMem, (sshort) reqrd_blocks);
00259     bprintf(20, "bmal: alc sz @ %p: %i blks = %i.\r\n", 
00260         pMem - 1, ALLOC_NUMBLOCKS(pMem), ALLOC_NUMBLOCKS(pMem)*SRAM_BLOCKSIZE);
00261     bprintf(20, "bmal: A2B tst: %i, B2A tst: %p.\r\n", 
00262         (sshort) SRAM_ADDR2BLOCK(pMem), (sshort) SRAM_BLOCK2ADDR(tagged_block));
00263     for (i = 0; (i < 10) && (i < SRAM_NUMBLOCKS); i++) {
00264         /*bsnprintf(tempry, 39, "\tbitmap: %08'B.\r\n", (char) bheap_bitmap[i]);*/
00265         bprintf(20, "\tbmp: 0x%x.\r\n", (sshort) ((char) bheap_bitmap[i]));
00266         /*bputs(tempry);*/
00267     }   /* This code causes badness. */
00268 #endif
00269     lk_bmalloc = false;
00270     
00271     return pMem;
00272 }
00273 
00274 #ifdef BREMALLOC
00275 
00281 /*@-redef@*/
00282 /*@null@*/ /*@exposed@*/ /*@external@*/
00283 char *bremalloc(ushort size, char /*@exposed@*/ /*@returned@*/ *pExist)
00284     /*@globals bheap@*/
00285     /*@modifies *bheap, bheap_bitmap, pExist@*/
00286 /*@=redef@*/
00287 {   
00302     char /*@exposed@*/ *pMem;
00303     uchar oldsize, newsize;
00304 
00305 #   ifdef BMEM_DEBUG
00306     oldsize = 0;    /* ... so that printf() says something sane. */
00307     newsize = 0;
00308 #   endif
00309     
00310     pMem = bmalloc(size, pExist);
00311     if (NULL != pMem) {
00312         /*newsize ..as opposed to requested */
00313         newsize = (uchar) ALLOC_NUMBLOCKS(( (uchar *)pMem ))*SRAM_BLOCKSIZE;
00314         if (NULL != pExist) {
00315             /* oldsize: actual currently alloc'd bytes.. */
00316             oldsize = (uchar) (ALLOC_NUMBLOCKS(( (uchar *)pExist ))*(uchar)SRAM_BLOCKSIZE);
00317             if (newsize > oldsize)
00318                 bmemset(pMem + oldsize, '\0', newsize - oldsize);   /* clear */
00319             if (pMem != pExist) {                           
00320                 bmemcpy(pMem, pExist, oldsize);                 /* copy */
00321             }
00322             bfree(pExist);                                      /* free */
00323         } else {
00324             bmemset(pMem, '\0', newsize);   /* newsize, clear ALL granted bytes */
00325         }
00326     }
00327 
00328 #   ifdef BMEM_DEBUG
00329 /*@-usedef@*/   /* oldsize/newsize may not be defined. Note to self: yes it is */
00330     bprintf(20, "brem: ONRET: oldsz %i, newsz %i, pMem %p, pExist %p.\r\n"
00331         , (sshort) oldsize, (sshort) newsize, (sshort) pMem, (sshort) pExist);
00332 /*@=usedef@*/
00333 #   endif
00334 
00335     return pMem;
00336 /*@-mustmod@*/  /*... splint reckons bheap_bitmap isn't modified */
00337 }
00338 /*@=mustmod@*/
00339 #endif

Generated on Sat Apr 10 17:08:02 2004 for BeeOS by doxygen 1.3.6-20040222