Annotation of qemu/roms/openbios/forth/bootstrap/memory.fs, revision 1.1

1.1     ! root        1: \ tag: forth memory allocation
        !             2: \ 
        !             3: \ Copyright (C) 2002-2003 Stefan Reinauer
        !             4: \ 
        !             5: \ See the file "COPYING" for further information about
        !             6: \ the copyright and warranty status of this work.
        !             7: \ 
        !             8: 
        !             9: \ 7.3.3.2 memory allocation
        !            10: 
        !            11: \ these need to be initialized by the forth kernel by now.
        !            12: variable start-mem 0 start-mem !       \ start of memory
        !            13: variable end-mem   0 end-mem   !       \ end of memory
        !            14: variable free-list 0 free-list !       \ free list head
        !            15: 
        !            16: \ initialize necessary variables and write a valid 
        !            17: \ free-list entry containing all of the memory.
        !            18: \   start-mem: pointer to start of memory.
        !            19: \   end-mem:   pointer to end of memory.
        !            20: \   free-list: head of linked free list
        !            21: 
        !            22: : init-mem ( start-addr size )
        !            23:   over dup
        !            24:   start-mem !          \ write start-mem 
        !            25:   free-list !          \ write first freelist entry
        !            26:   2dup /n - swap !     \ write 'len'  entry
        !            27:   over cell+ 0 swap !  \ write 'next' entry
        !            28:   + end-mem  !         \ write end-mem 
        !            29:   ;
        !            30:  
        !            31: \ --------------------------------------------------------------------
        !            32: 
        !            33: \ return pointer to smallest free block that contains 
        !            34: \ at least nb bytes and the block previous the the 
        !            35: \ actual block. On failure the pointer to the smallest
        !            36: \ free block is 0.
        !            37: 
        !            38: : smallest-free-block ( nb -- prev ptr | 0 0 )
        !            39:   0 free-list @
        !            40:   fffffff 0 0 >r >r >r
        !            41:   begin
        !            42:     dup
        !            43:   while
        !            44:     ( nb prev pp R: best_nb best_pp )
        !            45:     dup @ 3 pick r@ within if
        !            46:       ( nb prev pp )
        !            47:       r> r> r> 3drop            \ drop old smallest
        !            48:       2dup >r >r dup @ >r       \ new smallest
        !            49:     then
        !            50:     nip dup                     \ prev = pp
        !            51:     cell + @                    \ pp = pp->next
        !            52:   repeat
        !            53:   3drop r> drop r> r>
        !            54: ;
        !            55: 
        !            56: 
        !            57: \ --------------------------------------------------------------------
        !            58: 
        !            59: \ allocate size bytes of memory
        !            60: \ return pointer to memory (or throws an exception on failure).
        !            61: 
        !            62: : alloc-mem ( size -- addr )
        !            63: 
        !            64:   \ make it legal (and fast) to allocate 0 bytes
        !            65:   dup 0= if exit then
        !            66: 
        !            67:   aligned                      \ keep memory aligned.
        !            68:   dup smallest-free-block      \ look up smallest free block.
        !            69:   
        !            70:   dup 0= if 
        !            71:     \ 2drop
        !            72:     -15 throw \ out of memory
        !            73:   then
        !            74:   
        !            75:   ( al-size prev addr )
        !            76:   
        !            77:   \ If the smallest fitting block found is bigger than
        !            78:   \ the size of the requested block plus 2*cellsize we
        !            79:   \ can split the block in 2 parts. otherwise return a
        !            80:   \ slightly bigger block than requested.
        !            81: 
        !            82:   dup @ ( d->len ) 3 pick cell+ cell+ > if
        !            83:   
        !            84:     \ splitting the block in 2 pieces.
        !            85:     \ new block = old block + len field + size of requested mem
        !            86:     dup 3 pick cell+ + (  al-size prev addr nd )
        !            87: 
        !            88:     \ new block len = old block len - req. mem size - 1 cell
        !            89:     over @             ( al-size prev addr nd addr->len )
        !            90:     4 pick             ( ... al-size )
        !            91:     cell+ -            ( al-size prev addr nd nd nd->len )
        !            92:     over !             ( al-size prev addr nd )
        !            93: 
        !            94:     over cell+ @       ( al-size prev addr nd addr->next )
        !            95:                        \ write addr->next to nd->next
        !            96:     over cell+ !       ( al-size prev addr nd )
        !            97:     over 4 pick swap !
        !            98:   else
        !            99:     \ don't split the block, it's too small.
        !           100:     dup cell+ @
        !           101:   then
        !           102: 
        !           103:   ( al-size prev addr nd )
        !           104: 
        !           105:   \ If the free block we got is the first one rewrite free-list
        !           106:   \ pointer instead of the previous entry's next field.
        !           107:   rot dup 0= if drop free-list else cell+ then
        !           108:   ( al-size addr nd prev->next|fl )
        !           109:   !
        !           110:   nip cell+    \ remove al-size and skip len field of returned pointer
        !           111: 
        !           112:   ;
        !           113: 
        !           114: 
        !           115: \ --------------------------------------------------------------------
        !           116:   
        !           117: \ free block given by addr. The length of the
        !           118: \ given block is stored at addr - cellsize.
        !           119: \ 
        !           120: \ merge with blocks to the left and right 
        !           121: \ immediately, if they are free.
        !           122: 
        !           123: : free-mem ( addr len -- )
        !           124: 
        !           125:   \ we define that it is legal to free 0-byte areas
        !           126:   0= if drop exit then
        !           127:   ( addr )
        !           128:        
        !           129:   \ check if the address to free is somewhere within
        !           130:   \ our available memory. This fails badly on discontigmem
        !           131:   \ architectures. If we need more RAM than fits on one 
        !           132:   \ contiguous memory area we are too bloated anyways. ;)
        !           133:   
        !           134:   dup start-mem @ end-mem @ within 0= if
        !           135:  \   ." free-mem: no such memory: 0x" u. cr
        !           136:     exit
        !           137:   then
        !           138: 
        !           139:   /n -                         \ get real block address
        !           140:   0 free-list @                        ( addr prev l )
        !           141:   
        !           142:   begin                                \ now scan the free list
        !           143:     dup 0<> if                 \ only check len, if block ptr != 0
        !           144:       dup dup @ cell+ + 3 pick < 
        !           145:     else
        !           146:       false
        !           147:     then
        !           148:   while 
        !           149:     nip dup                    \ prev=l
        !           150:     cell+ @                    \ l=l->next
        !           151:   repeat
        !           152: 
        !           153:   ( addr prev l )
        !           154: 
        !           155:   dup 0<> if                           \ do we have free memory to merge with?
        !           156:   
        !           157:     dup dup @ cell+ + 3 pick  = if     \ hole hit. adding bytes.
        !           158:       \ freeaddr = end of current block -> merge
        !           159:       ( addr prev l )
        !           160:       rot @ cell+              ( prev l f->len+cellsize )
        !           161:       over @ +                 \ add l->len
        !           162:       over !                   ( prev l )
        !           163:       swap over cell+ @                \ f = l; l = l->next;
        !           164: 
        !           165:       \ The free list is sorted by addresses. When merging at the
        !           166:       \ start of our block we might also want to merge at the end
        !           167:       \ of it. Therefore we fall through to the next border check
        !           168:       \ instead of returning.
        !           169:       true                             \ fallthrough value
        !           170:     else
        !           171:       false                            \ no fallthrough
        !           172:     then
        !           173:     >r                                 \ store fallthrough on ret stack
        !           174:     
        !           175:     ( addr prev l )
        !           176: 
        !           177:     dup 3 pick dup @ cell+ + = if      \ hole hit. real merging.
        !           178:       \ current block starts where block to free ends.
        !           179:       \ end of free block addr = current block -> merge and exit
        !           180:                                        ( addr prev l )
        !           181:       2 pick dup @                     ( f f->len ) 
        !           182:       2 pick @ cell+ +                 ( f newlen )
        !           183:       swap !                           ( addr prev l )
        !           184:       3dup drop
        !           185:       0= if
        !           186:        free-list
        !           187:       else
        !           188:        2 pick cell+ 
        !           189:       then                             ( value prev->next|free-list )
        !           190:       !                                        ( addr prev l )
        !           191:       cell+ @ rot                      ( prev l->next addr )
        !           192:       cell+ ! drop
        !           193:       r> drop exit                     \ clean up return stack
        !           194:     then
        !           195: 
        !           196:     r> if 3drop exit then              \ fallthrough? -> exit
        !           197:   then
        !           198:   
        !           199:   \ loose block - hang it before current.
        !           200: 
        !           201:   ( addr prev l )
        !           202: 
        !           203:   \ hang block to free in front of the current entry.
        !           204:   dup 3 pick cell+ !                   \ f->next = l;
        !           205:   free-list @ = if                     \ is block to free new list head?
        !           206:     over free-list !
        !           207:   then
        !           208:   
        !           209:   ( addr prev )
        !           210:   dup 0<> if                           \ if (prev) prev->next=f
        !           211:     cell+ !
        !           212:   else 
        !           213:     2drop                              \ no fixup needed. clean up.
        !           214:   then
        !           215:     
        !           216:   ;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.