summaryrefslogtreecommitdiff
path: root/libc/bcc/heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bcc/heap.c')
-rw-r--r--libc/bcc/heap.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/libc/bcc/heap.c b/libc/bcc/heap.c
new file mode 100644
index 0000000..c5b2457
--- /dev/null
+++ b/libc/bcc/heap.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <errno.h>
+
+/****************************************************************************/
+
+#ifdef L_errno
+int errno = 0; /* libc error value */
+#endif
+
+/****************************************************************************/
+
+#ifdef __AS386_16__
+
+#ifdef L___brk_addr
+#asm
+.data
+export brk_addr
+brk_addr: .word __end ! This holds the current return for sbrk(0)
+.text
+#endasm
+#endif
+
+/****************************************************************************/
+
+#ifdef L_sbrk
+int sbrk(brk_off)
+int brk_off;
+{
+#asm
+ mov bx,sp
+#if !__FIRST_ARG_IN_AX__
+ mov ax,[bx+2] ! Fetch the requested value
+#endif
+ test ax,ax
+ jnz has_change
+ mov ax,[brk_addr] ! Simple one, read current - can`t fail.
+ jmp eof
+
+has_change:
+ js go_down
+ add ax,[brk_addr] ! Goin up!
+ jc Enomem
+ sub bx,#511 ! Safety space 512 bytes
+ cmp bx,ax ! Too close ?
+ jb Enomem
+
+sbrk_ok:
+#if !defined(__MSDOS__) && !defined(__STANDALONE__)
+ push ax ! MSDOS `kernel` doesn`t care
+ call ___brk ! Tell the kernel
+ test ax,ax
+ pop ax ! ASSUME ___brk doesn`t alter stack!
+ jnz Enomem ! Ugh! kernel didn`t like the idea!
+#endif
+ xchg [brk_addr],ax ! Save away new val
+ jmp eof ! Return it
+go_down:
+ add ax,[brk_addr]
+ jnc Enomem
+ cmp ax,#__end
+ jae sbrk_ok
+
+Enomem:
+ mov ax,#12 ! This should be ENOMEM not a magic.
+ mov [_errno],ax
+ mov ax,#-1
+eof:
+#endasm
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_brk
+int
+brk(new_brk)
+char * new_brk;
+{
+#asm
+ mov bx,sp
+#if !__FIRST_ARG_IN_AX__
+ mov ax,[bx+2] ! Fetch the requested value
+#endif
+ sub bx,#512 ! Safety space 512 bytes
+ cmp bx,ax ! Too close ?
+ jb Enomem
+ cmp ax,#__end
+ jae brk_ok
+Enomem:
+ mov ax,#12 ! This should be ENOMEM not a magic.
+ mov [_errno],ax
+ mov ax,#-1
+ ret
+brk_ok:
+#if !defined(__MSDOS__) && !defined(__STANDALONE__)
+ push ax
+ call ___brk ! Tell the kernel
+ test ax,ax
+ pop bx ! ASSUME ___brk doesn`t alter stack!
+ jnz Enomem ! Ugh! kernel didn`t like the idea!
+ mov [brk_addr],bx ! Save away new val
+#else
+ mov [brk_addr],ax ! MSDOS `kernel` doesn`t care
+ mov ax,#0
+#endif
+#endasm
+}
+#endif
+
+#endif
+
+/****************************************************************************/
+
+#ifdef __AS386_32__
+extern char * __brk_addr;
+extern char * __brk();
+
+#ifdef L___brk_addr
+char * __brk_addr = 0; /* This holds the current return for sbrk(0) */
+
+char *
+__brk(val)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov ebx,eax
+#else
+ mov ebx,[esp+4]
+#endif
+ mov eax,#45
+ int $80
+#endasm
+}
+
+__brk_addr_init()
+{
+ if( __brk_addr == 0 && (__brk_addr = __brk(0)) == 0 )
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#ifdef L_sbrk
+char *
+sbrk(brk_off)
+int brk_off;
+{
+ char * new_brk;
+ if( __brk_addr_init() ) return (char*)-1;
+ if( brk_off == 0 ) return __brk_addr;
+
+ new_brk = __brk_addr + brk_off;
+ __brk_addr = __brk(new_brk);
+ if( __brk_addr != new_brk )
+ {
+ errno = ENOMEM;
+ return (char*)-1;
+ }
+ return __brk_addr - brk_off;
+}
+#endif
+
+#ifdef L_brk
+int
+brk(new_brk)
+char * new_brk;
+{
+ if( __brk_addr_init() ) return -1;
+
+ __brk_addr = __brk(new_brk);
+ if( __brk_addr == new_brk ) return 0;
+ errno = ENOMEM;
+ return -1;
+}
+#endif
+
+#endif