spinix-hive/lerner/cmalloc.spin

209 lines
8.2 KiB
Plaintext

'******************************************************************************
' C malloc written in Spin
' Author: Dave Hein
' Copyright (c) 2010
' See end of file for terms of use.
'******************************************************************************
'******************************************************************************
' Revison History
' v1.0 - 4/2/2010 First official release
'******************************************************************************
{
This object contains the malloc, free and calloc routines used by clib.
}
OBJ
sys : "sysdefs"
CON
NEXT_BLK = 0
BLK_SIZE = 1
HDR_SIZE = 4
'RAM_SIZE = $8000
RAM_SIZE = sys#rendezvous
CHECKWORD = $dead1eaf
DAT
locknum long 0
memfreelist long 0
malloclist long 0
laststackaddr long 0
PUB CheckStackSpace | addr
repeat addr from laststackaddr to 0 step 4
if long[addr] <> CHECKWORD
quit
result++
PUB GetMallocList
return malloclist
PUB GetFreeList
return memfreelist
PUB mallocinit(stacksize) | currblk, addr
'' Initialize the malloc heap "stacksize" longs after the current stack pointer
'' Allocate a lock and return the lock number plus one if successful, or zero if not
locknum := locknew + 1
currblk := @stacksize + (stacksize << 2)
'Fill stack with checkword
laststackaddr := currblk - 4
longfill(@stacksize + 40, CHECKWORD, stacksize - 10)
memfreelist := currblk
malloclist := 0
word[currblk]{NEXT_BLK} := 0
word[currblk][BLK_SIZE] := RAM_SIZE - currblk
return locknum
PUB malloc(size) | prevblk, currblk, nextblk, prevblk0, currblk0, size0
'' Allocate a memory block of "size" bytes. Return a pointer to the clock if
'' successful, or zero if a large enough memory block could not be found
'ser.dbprintf1(string("malloc: %d\n"), size)
prevblk := 0
prevblk0 := 0
currblk0 := 0
if (size =< 0)
return 0
repeat until not lockset(locknum - 1)
currblk := memfreelist
' Adjust size to nearest long plus the header size
size := ((size + 3) & (!3)) + HDR_SIZE
' Search for a block of memory
repeat while (currblk)
if (word[currblk][BLK_SIZE] => size)
prevblk0 := prevblk
currblk0 := currblk
prevblk := currblk
currblk := word[currblk]{NEXT_BLK}
currblk := currblk0
prevblk := prevblk0
' Return null if block not found
if (currblk == 0)
lockclr(locknum - 1)
return 0
' Split block if larger than needed
size0 := word[currblk][BLK_SIZE] - size
if (size0 => HDR_SIZE + 4)
word[currblk][BLK_SIZE] := size0
currblk += size0
word[currblk][BLK_SIZE] := size
' Otherwise, use space without splitting and remove from memfreelist
else
nextblk := word[currblk]{NEXT_BLK}
if (prevblk)
word[prevblk]{NEXT_BLK} := nextblk
else
memfreelist := nextblk
' Add to the beginning of the malloc list
word[currblk]{NEXT_BLK} := malloclist
malloclist := currblk
lockclr(locknum - 1)
return currblk + HDR_SIZE
PUB freeraw(ptr, size)
repeat until not lockset(locknum - 1)
word[ptr][BLK_SIZE] := size
meminsert(ptr)
lockclr(locknum - 1)
return 1
PUB free(ptr) | prevblk, currblk, nextblk
'' Return the memory block at "ptr" to the free list. Return a value of one
'' if successful, or zero if the memory block was not on the allocate list.
prevblk := 0
repeat until not lockset(locknum - 1)
nextblk := malloclist
currblk := ptr - HDR_SIZE
' Search the malloclist for the currblk pointer
repeat while (nextblk)
if (currblk == nextblk)
' Remove from the malloc list
if (prevblk)
word[prevblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
else
malloclist := word[nextblk]{NEXT_BLK}
' Add to the free list
meminsert(nextblk)
lockclr(locknum - 1)
return 1
prevblk := nextblk
nextblk := word[nextblk]{NEXT_BLK}
' Return a NULL value if not found
lockclr(locknum - 1)
return 0
PRI meminsert(currblk) | prevblk, nextblk
'' Insert a memory block back into the free list. Merge blocks together if
'' the memory block is contiguous with other blocks on the list.
prevblk := 0
nextblk := memfreelist
' Find Insertion Point
repeat while (nextblk)
if ((currblk => prevblk) and (currblk =< nextblk))
quit
prevblk := nextblk
nextblk := word[nextblk]{NEXT_BLK}
' Merge with the previous block if contiguous
if (prevblk and (prevblk + word[prevblk][BLK_SIZE] == currblk))
word[prevblk][BLK_SIZE] += word[currblk][BLK_SIZE]
' Also merge with next block if contiguous
if (prevblk + word[prevblk][BLK_SIZE] == nextblk)
word[prevblk][BLK_SIZE] += word[nextblk][BLK_SIZE]
word[prevblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
' Merge with the next block if contiguous
elseif (nextblk and (currblk + word[currblk][BLK_SIZE] == nextblk))
word[currblk][BLK_SIZE] += word[nextblk][BLK_SIZE]
word[currblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
if (prevblk)
word[prevblk]{NEXT_BLK} := currblk
else
memfreelist := currblk
' Insert in the middle of the free list if not contiguous
elseif (prevblk)
word[prevblk]{NEXT_BLK} := currblk
word[currblk]{NEXT_BLK} := nextblk
' Otherwise, insert at beginning of the free list
else
memfreelist := currblk
word[currblk]{NEXT_BLK} := nextblk
PUB calloc(size) | ptr
'' Allocate a memory block of "size" bytes and initialize to zero. Return
'' a pointer to the memory block if successful, or zero if a large enough
'' memory block could not be found.
ptr := malloc(size)
if (ptr)
longfill(ptr, 0, (size + 3) >> 2)
return ptr
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}