/
/ PDP-11 C.
/ Standard Library.
/
/ Dynamic space management.
/
 
	.globl	alloc
	.globl	free
	.globl	calloc
	.globl	cfree
	.globl	_alloc
	.globl	_free
	.globl	_avail
	.globl	exttsk
	.globl	deny
	.globl	getpar
	.globl	_mul
	.globl	_asr
 
SLOP	=	8.		/Fuzz factor for space allocation
 
_avail:	.word	0,0		/Free list

hi:	.word	0		/Top of partition (0 if not set)
pb:	.blkw	4		/For getpar()
lim:	.limit			/Load limits
 
/
/ These routines provide the user's interface
/ to the allocator.
/ Note that `free' and `cfree' are the same routine.
/
/ alloc(nbytes)
/ calloc(n, nbytes)
/ free(p)
/ cfree(p)
/

alloc:
	mov	2(sp),r0
	br	0f

calloc:
	call	_mul		/multiply the two arguments
0:
	callr	_alloc

free:
cfree:
	mov	2(sp),r0
	callr	_free
 
/
/ _alloc
/ Allocate space (internal interface).
/
/ This routine allocates a block of memory from the global free
/ list.  This list is automatically  set up by `_alloc'  on the
/ first call.
/
/ If there is insufficient space to allocate the block and task
/ extension has failed, `_alloc' returns whatever the  function
/ `deny' (of 0 arguments) returns.  The default `deny'  returns
/ -1.
/
/ r0=size of the desired block.
/ r0=return pointer.
/
 
_alloc:
	mov	r3,-(sp)	/Save registers
	mov	r2,-(sp)
 
	tst	hi		/Is this the first call
	bne	1f		/Br if not
	mov	r0,-(sp)	/Save size requested
	mov	$pb,-(sp)	/Get partition parameters
	call	getpar
	tst	(sp)+
	mov	pb+4,r1		/Compute size
	asl	r1
	asl	r1
	asl	r1
	asl	r1
	asl	r1
	asl	r1
	add	pb+2,r1
	mov	r1,hi
	mov	lim+2,r0	/Compute size of core hole
	add	$3,r0
	bic	$3,r0
	sub	r0,r1
	cmp	r1,$4		/If very small core hole
	blo	0f		/It cannot be freed
	mov	r1,(r0)+	/Otherwise free it
	call	_free
0:
	mov	(sp)+,r0	/Get request size back
 
1:
	add	$2+1,r0		/1 control word + rounding
	bic	$1,r0
	cmp	r0,$4		/Check for bad call
	blo	4f		/Abort if allocating zero words
	mov	r0,r1		/Save rounded size
 
1:
	mov	$_avail,r3	/Point at free list

0:
	mov	(r3),r2		/mov LINK(r3),r2
	beq	2f		/No space on the free list
	cmp	2(r2),r0	/Is it usable
	bhis	0f
	mov	r2,r3		/No, continue the search
	br	0b
 
0:
	neg	r0		/Compute leftover
	add	2(r2),r0
	cmp	r0,$SLOP	/Use it all
	bhis	0f		/No
	mov	(r2),(r3)	/Yes, unlink the block
	mov	r2,r0		/Setup for return
	mov	2(r2),(r0)+
	br	3f
 
0:
	mov	r0,2(r2)	/Adjust size in the block
	add	r2,r0		/Get pointer to the space to return
	mov	r1,(r0)+	/Put size in it
	br	3f		/Return
 
/
/ Out of space.
/ Try to extend the task.
/ In RSX-11M V02, just die.
/
 
2:
	add	$77,r0		/Get grow increment
	bic	$77,r0
	mov	r0,r2		/Save it, then
	mov	r1,-(sp)	/save r1
	mov	$6,-(sp)	/shift count
	mov	r0,-(sp)	/stuff to be shifted
	call	_asr		/convert to 32 word blocks
	tst	(sp)+		/clean stack
	tst	(sp)+		/clean stack
	mov	(sp)+,r1	/restore r1
	mov	r0,-(sp)	/Try to grow
	call	exttsk
	tst	(sp)+
	cmp	r0,$-1
	beq	0f		/Failed
	mov	hi,r0		/Return new block to free list
	add	r2,hi
	mov	r2,(r0)+
	call	_free
	mov	r1,r0		/Setup size again, and
	br	1b		/Try again (must work)
 0:
 
	call	deny		/No space
 
3:
	mov	(sp)+,r2	/Return
	mov	(sp)+,r3
	return
 
4:
	iot			/Allocating zero words
 
/
/ _free
/ Free space (internal interface).
/
/ This routine returns a block of memory, previously obtained
/ from `_alloc', to the free pool.
/ Needless to say,  grave disorder will result if some random
/ integer  is passed to `_free',  or you try to `_free'  some
/ space twice.
/
/ r0=pointer to the block to free.
/
/ Uses: r0
/
 
_free:
	mov	r4,-(sp)	/Save some registers
	mov	r3,-(sp)
	mov	r2,-(sp)
	mov	r1,-(sp)
 
	mov	-(r0),r1	/Fix pointer, get size
	mov	$_avail,r3	/Free list pointer

0:
	mov	(r3),r2		/Walk down the list until
	beq	1f		/The end
	cmp	r2,r0		/Or the correct place is found
	bhi	0f
	mov	r2,r3
	br	0b
 
0:
	mov	r0,r4		/Test for collapse top end
	add	r1,r4
	cmp	r4,r2		/If they hit
	bne	1f
	add	2(r2),r1	/Join them together
	mov	(r2),(r0)
	br	0f
 
1:
	mov	r2,(r0)		/Otherwise just link it in
 
0:
	mov	r3,r4		/Test for collapse bottom end
	add	2(r3),r4
	cmp	r4,r0
	bne	1f
	add	r1,2(r3)	/Merge them
	mov	(r0),(r3)
	br	0f
 
1:
	mov	r0,(r3)		/Otherwise finish linking it in
	mov	r1,2(r0)
 
0:
	mov	(sp)+,r1	/Return
	mov	(sp)+,r2
	mov	(sp)+,r3
	mov	(sp)+,r4
	return
