; ; suballoc.s ; ; Handling of requests for small link blocks ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Dynamic Linking System (SDLS) ; ; SDLS 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 2, or (at your option) ; any later version. ; ; SDLS 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 SDLS. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:swis GET libs:header ;----- External dependencies ------------------------------------------------ GET sh.wSpace GET sh.linkblock ;----- Word to the wise ----------------------------------------------------- ; ; The DLink manager requires lots of small blocks for linked lists and ; things. To avoid mangling the RMA, we allocate very big blocks and then ; split them up into littler ones. The format of the very big blocks is as ; follows: ; ; +0 link to next one ; +4 [data] ; ; The data blocks are allocated such that they are just big enough for the ; data -- the caller must specify the actual size of the block when freeing. ; Freed blocks are *not* returned to the OS. There isn't much point -- it ; would take ages, and they're only going to be allocated again anyway. All ; big blocks are returned to the OS when the module quits. ;----- Magic numbers -------------------------------------------------------- bigBlockSize EQU 1024*lk_strSize+4 ;Allocate 1024 small blocks ;at a time ;----- Main code ------------------------------------------------------------ AREA |DLLM$$Code|,CODE,READONLY GBLL debug debug SETL {FALSE} ; --- sub_alloc --- ; ; On entry: -- ; On exit: R0 == pointer to block allocated, or 0 if no memory ; EXPORT sub_alloc sub_alloc ROUT STMFD R13!,{R1-R4,R14} LDR R0,sub__free ;Get the free list offset CMP R0,#0 ;Are there any free blocks? BEQ %01sub_alloc ;No -- better allocate some 00sub_alloc LDR R2,[R0] ;Get next pointer from block STR R2,sub__free ;This is now first free block LDMFD R13!,{R1-R4,PC}^ ;Restore registers and return 01sub_alloc MOV R0,#6 ;Allocate some more from RMA LDR R3,=bigBlockSize ;Allocate correct size SWI XOS_Module ;Allocate the block LDMVSFD R13!,{R1-R4,PC} ;Return on an error LDR R4,sub__blocks ;Load the pointer STR R4,[R2] ;Store in next ptr of new blk STR R2,sub__blocks ;And link new block into list MOV R0,#0 ;Next free pointer start at 0 SUB R3,R3,#lk_strSize ;Offset to next field of sub 02sub_alloc STR R0,[R2,R3] ;Store in next field ADD R0,R2,R3 ;Point to that block SUBS R3,R3,#lk_strSize ;Point to previous block BGT %02sub_alloc ;If more to do, continue... B %00sub_alloc ;Then allocate as normal LTORG ; --- sub_free --- ; ; On entry: R0 == pointer to block ; On exit: R0 corrupted EXPORT sub_free sub_free ROUT STMFD R13!,{R14} ;Preserve registers LDR R14,sub__free ;Get current first block STR R14,[R0] ;Store in newly freed block STR R0,sub__free ;And insert new block in list LDMFD R13!,{PC}^ ;Oh, and return to caller LTORG ; --- sub_die --- ; ; On entry: -- ; On exit: R0 corrupted EXPORT sub_die sub_die ROUT STMFD R13!,{R1-R3,R14} ;Preserve used registers MOV R3,#0 ;No errors yet LDR R2,sub__blocks ;Point to list of blocks MOV R0,#0 ;Blank out bigblock pointer STR R0,sub__blocks ;In case it fails a bit STR R0,sub__free 00sub_die CMP R2,#0 ;Are we at the end? BEQ %01sub_die ;Yes -- leave the loop LDR R1,[R2] ;Get next pointer right now MOV R0,#7 ;Free memory SWI XOS_Module ;Free the block up MOVVS R3,R0 ;Remember the error, if any MOV R2,R1 ;Move on to next block B %00sub_die ;And try again 01sub_die MOVS R0,R3 ;Copy the error pointer back LDMFD R13!,{R1-R3,R14} ;Restore the other registers ORRNES PC,R14,#V_flag ;Set error indicator if reqd BICS PC,R14,#V_flag ;Otherwise clear it LTORG ;----- That's all folks ----------------------------------------------------- END