summaryrefslogtreecommitdiff
path: root/libc/bcc/heap.c
blob: 2cab16ecd5704c5a1d887faedb65cbf4a5d41df4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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:
#ifndef __MSDOS__
  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:
#ifndef __MSDOS__
  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