Rev 553 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 553 | Rev 704 | ||
---|---|---|---|
1 | /**************************************************************************** |
1 | /**************************************************************************** |
2 | * |
2 | * |
3 | * Open Watcom Project |
3 | * Open Watcom Project |
4 | * |
4 | * |
5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. |
5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. |
6 | * |
6 | * |
7 | * ======================================================================== |
7 | * ======================================================================== |
8 | * |
8 | * |
9 | * This file contains Original Code and/or Modifications of Original |
9 | * This file contains Original Code and/or Modifications of Original |
10 | * Code as defined in and that are subject to the Sybase Open Watcom |
10 | * Code as defined in and that are subject to the Sybase Open Watcom |
11 | * Public License version 1.0 (the 'License'). You may not use this file |
11 | * Public License version 1.0 (the 'License'). You may not use this file |
12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO |
12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO |
13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is |
13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is |
14 | * provided with the Original Code and Modifications, and is also |
14 | * provided with the Original Code and Modifications, and is also |
15 | * available at www.sybase.com/developer/opensource. |
15 | * available at www.sybase.com/developer/opensource. |
16 | * |
16 | * |
17 | * The Original Code and all software distributed under the License are |
17 | * The Original Code and all software distributed under the License are |
18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM |
19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM |
20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF |
20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF |
21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR |
21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR |
22 | * NON-INFRINGEMENT. Please see the License for the specific language |
22 | * NON-INFRINGEMENT. Please see the License for the specific language |
23 | * governing rights and limitations under the License. |
23 | * governing rights and limitations under the License. |
24 | * |
24 | * |
25 | * ======================================================================== |
25 | * ======================================================================== |
26 | * |
26 | * |
27 | * Description: Heap growing routines - allocate near heap memory from OS. |
27 | * Description: Heap growing routines - allocate near heap memory from OS. |
28 | * |
28 | * |
29 | ****************************************************************************/ |
29 | ****************************************************************************/ |
30 | 30 | ||
31 | - | ||
32 | //#include "dll.h" // needs to be first |
31 | |
33 | #include "variety.h" |
32 | #include "variety.h" |
34 | #include |
33 | #include |
35 | #include |
34 | #include |
36 | #include |
35 | #include |
37 | #include "heapacc.h" |
36 | #include "heapacc.h" |
38 | #include "heap.h" |
37 | #include "heap.h" |
39 | #include |
38 | #include |
40 | #if defined(__DOS_EXT__) |
39 | #if defined(__DOS_EXT__) |
41 | // #include "extender.h" |
40 | // #include "extender.h" |
42 | // #include "tinyio.h" |
41 | // #include "tinyio.h" |
43 | #endif |
42 | #endif |
44 | #if defined(__CALL21__) |
43 | #if defined(__CALL21__) |
45 | // #include "tinyio.h" |
44 | // #include "tinyio.h" |
46 | #endif |
45 | #endif |
47 | #if defined(__WINDOWS_286__) || defined(__NT__) |
46 | #if defined(__WINDOWS_286__) || defined(__NT__) |
48 | void* _stdcall UserAlloc(int size); |
- | |
49 | - | ||
50 | // #include "windows.h" |
47 | #include "kolibri.h" |
51 | #endif |
48 | #endif |
52 | #if defined(__OS2__) |
49 | #if defined(__OS2__) |
53 | // #include |
50 | // #include |
54 | #endif |
51 | #endif |
55 | #if defined(__WINDOWS_386__) |
52 | #if defined(__WINDOWS_386__) |
56 | // extern void * pascal DPMIAlloc(unsigned long); |
53 | // extern void * pascal DPMIAlloc(unsigned long); |
57 | #endif |
54 | #endif |
58 | 55 | ||
59 | static frlptr __LinkUpNewMHeap( mheapptr ); |
56 | static frlptr __LinkUpNewMHeap( mheapptr ); |
60 | 57 | ||
61 | #if defined(__DOS_EXT__) |
58 | #if defined(__DOS_EXT__) |
62 | 59 | ||
63 | extern int SegmentLimit(); |
60 | extern int SegmentLimit(); |
64 | #pragma aux SegmentLimit = \ |
61 | #pragma aux SegmentLimit = \ |
65 | "xor eax,eax" \ |
62 | "xor eax,eax" \ |
66 | "mov ax,ds" \ |
63 | "mov ax,ds" \ |
67 | "lsl eax,ax" \ |
64 | "lsl eax,ax" \ |
68 | "inc eax" \ |
65 | "inc eax" \ |
69 | value [eax] \ |
66 | value [eax] \ |
70 | modify exact [eax]; |
67 | modify exact [eax]; |
71 | 68 | ||
72 | static void __unlink( mheapptr miniheapptr ) |
69 | static void __unlink( mheapptr miniheapptr ) |
73 | { |
70 | { |
74 | mheapptr prev_link; |
71 | mheapptr prev_link; |
75 | mheapptr next_link; |
72 | mheapptr next_link; |
76 | 73 | ||
77 | if( __nheapbeg == miniheapptr ) { |
74 | if( __nheapbeg == miniheapptr ) { |
78 | __nheapbeg = miniheapptr->next; |
75 | __nheapbeg = miniheapptr->next; |
79 | } |
76 | } |
80 | if( miniheapptr == __MiniHeapRover ) { |
77 | if( miniheapptr == __MiniHeapRover ) { |
81 | __MiniHeapRover = miniheapptr->prev; |
78 | __MiniHeapRover = miniheapptr->prev; |
82 | if( __MiniHeapRover == NULL ) { |
79 | if( __MiniHeapRover == NULL ) { |
83 | __MiniHeapRover = __nheapbeg; |
80 | __MiniHeapRover = __nheapbeg; |
84 | __LargestSizeB4MiniHeapRover = 0; |
81 | __LargestSizeB4MiniHeapRover = 0; |
85 | } |
82 | } |
86 | } |
83 | } |
87 | if( miniheapptr == __MiniHeapFreeRover ) { |
84 | if( miniheapptr == __MiniHeapFreeRover ) { |
88 | __MiniHeapFreeRover = 0; |
85 | __MiniHeapFreeRover = 0; |
89 | } |
86 | } |
90 | prev_link = miniheapptr->prev; |
87 | prev_link = miniheapptr->prev; |
91 | next_link = miniheapptr->next; |
88 | next_link = miniheapptr->next; |
92 | if( prev_link != NULL ) prev_link->next = next_link; |
89 | if( prev_link != NULL ) prev_link->next = next_link; |
93 | if( next_link != NULL ) next_link->prev = prev_link; |
90 | if( next_link != NULL ) next_link->prev = prev_link; |
94 | } |
91 | } |
95 | 92 | ||
96 | void __FreeDPMIBlocks() |
93 | void __FreeDPMIBlocks() |
97 | { |
94 | { |
98 | mheapptr mhp; |
95 | mheapptr mhp; |
99 | struct dpmi_hdr *dpmi; |
96 | struct dpmi_hdr *dpmi; |
100 | 97 | ||
101 | mhp = __nheapbeg; |
98 | mhp = __nheapbeg; |
102 | while( mhp != NULL ) { |
99 | while( mhp != NULL ) { |
103 | // see if the last free entry has the full size of |
100 | // see if the last free entry has the full size of |
104 | // the DPMI block ( - overhead). If it is then we can give this |
101 | // the DPMI block ( - overhead). If it is then we can give this |
105 | // DPMI block back to the DPMI host. |
102 | // DPMI block back to the DPMI host. |
106 | if( (mhp->freehead.prev)->len + sizeof(struct miniheapblkp) == |
103 | if( (mhp->freehead.prev)->len + sizeof(struct miniheapblkp) == |
107 | mhp->len ) { |
104 | mhp->len ) { |
108 | mheapptr pnext; |
105 | mheapptr pnext; |
109 | 106 | ||
110 | dpmi = ((struct dpmi_hdr *)mhp) - 1; |
107 | dpmi = ((struct dpmi_hdr *)mhp) - 1; |
111 | pnext = mhp->next; |
108 | pnext = mhp->next; |
112 | __unlink( mhp ); |
109 | __unlink( mhp ); |
113 | mhp = pnext; |
110 | mhp = pnext; |
114 | if( dpmi->dos_seg_value == 0 ) { // if DPMI block |
111 | if( dpmi->dos_seg_value == 0 ) { // if DPMI block |
115 | TinyDPMIFree( dpmi->dpmi_handle ); |
112 | TinyDPMIFree( dpmi->dpmi_handle ); |
116 | } else { // else DOS block below 1MB |
113 | } else { // else DOS block below 1MB |
117 | TinyFreeBlock( dpmi->dos_seg_value ); |
114 | TinyFreeBlock( dpmi->dos_seg_value ); |
118 | } |
115 | } |
119 | } else { |
116 | } else { |
120 | mhp = mhp->next; |
117 | mhp = mhp->next; |
121 | } |
118 | } |
122 | } |
119 | } |
123 | } |
120 | } |
124 | 121 | ||
125 | void *__ReAllocDPMIBlock( frlptr p1, unsigned req_size ) |
122 | void *__ReAllocDPMIBlock( frlptr p1, unsigned req_size ) |
126 | { |
123 | { |
127 | mheapptr mhp; |
124 | mheapptr mhp; |
128 | struct dpmi_hdr *dpmi; |
125 | struct dpmi_hdr *dpmi; |
129 | struct dpmi_hdr *prev_dpmi; |
126 | struct dpmi_hdr *prev_dpmi; |
130 | unsigned size; |
127 | unsigned size; |
131 | frlptr flp, flp2; |
128 | frlptr flp, flp2; |
132 | 129 | ||
133 | if( !__heap_enabled ) return( 0 ); |
130 | if( !__heap_enabled ) return( 0 ); |
134 | __FreeDPMIBlocks(); |
131 | __FreeDPMIBlocks(); |
135 | prev_dpmi = NULL; |
132 | prev_dpmi = NULL; |
136 | for( mhp = __nheapbeg; mhp; mhp = mhp->next ) { |
133 | for( mhp = __nheapbeg; mhp; mhp = mhp->next ) { |
137 | if( ((PTR)mhp + sizeof(struct miniheapblkp) == (PTR)p1) |
134 | if( ((PTR)mhp + sizeof(struct miniheapblkp) == (PTR)p1) |
138 | && (mhp->numalloc == 1) ) { |
135 | && (mhp->numalloc == 1) ) { |
139 | // The mini-heap contains only this memblk |
136 | // The mini-heap contains only this memblk |
140 | __unlink( mhp ); |
137 | __unlink( mhp ); |
141 | dpmi = ((struct dpmi_hdr *)mhp) - 1; |
138 | dpmi = ((struct dpmi_hdr *)mhp) - 1; |
142 | if( dpmi->dos_seg_value != 0 ) return( NULL ); |
139 | if( dpmi->dos_seg_value != 0 ) return( NULL ); |
143 | size = mhp->len + sizeof(struct dpmi_hdr) + TAG_SIZE; |
140 | size = mhp->len + sizeof(struct dpmi_hdr) + TAG_SIZE; |
144 | size += ( req_size - (p1->len-TAG_SIZE) ); |
141 | size += ( req_size - (p1->len-TAG_SIZE) ); |
145 | size += 0x0fff; |
142 | size += 0x0fff; |
146 | size &= ~0x0fff; |
143 | size &= ~0x0fff; |
147 | prev_dpmi = dpmi; |
144 | prev_dpmi = dpmi; |
148 | dpmi = TinyDPMIRealloc( dpmi, size ); |
145 | dpmi = TinyDPMIRealloc( dpmi, size ); |
149 | if( dpmi == NULL ) { |
146 | if( dpmi == NULL ) { |
150 | dpmi = prev_dpmi; |
147 | dpmi = prev_dpmi; |
151 | return( NULL ); // indicate resize failed |
148 | return( NULL ); // indicate resize failed |
152 | } |
149 | } |
153 | dpmi->dos_seg_value = 0; |
150 | dpmi->dos_seg_value = 0; |
154 | mhp = (mheapptr)( dpmi + 1 ); |
151 | mhp = (mheapptr)( dpmi + 1 ); |
155 | mhp->len = size - sizeof(struct dpmi_hdr) - TAG_SIZE; |
152 | mhp->len = size - sizeof(struct dpmi_hdr) - TAG_SIZE; |
156 | flp = __LinkUpNewMHeap( mhp ); |
153 | flp = __LinkUpNewMHeap( mhp ); |
157 | mhp->numalloc = 1; |
154 | mhp->numalloc = 1; |
158 | 155 | ||
159 | // round up to even number |
156 | // round up to even number |
160 | req_size = (req_size + 1) & ~1; |
157 | req_size = (req_size + 1) & ~1; |
161 | size = flp->len - req_size; |
158 | size = flp->len - req_size; |
162 | if( size >= FRL_SIZE ) { // Enough to spare a free block |
159 | if( size >= FRL_SIZE ) { // Enough to spare a free block |
163 | flp->len = req_size | 1;// adjust size and set allocated bit |
160 | flp->len = req_size | 1;// adjust size and set allocated bit |
164 | // Make up a free block at the end |
161 | // Make up a free block at the end |
165 | flp2 = (frlptr)((PTR)flp + req_size); |
162 | flp2 = (frlptr)((PTR)flp + req_size); |
166 | flp2->len = size | 1; |
163 | flp2->len = size | 1; |
167 | ++mhp->numalloc; |
164 | ++mhp->numalloc; |
168 | mhp->largest_blk = 0; |
165 | mhp->largest_blk = 0; |
169 | _nfree( (PTR)flp2 + TAG_SIZE ); |
166 | _nfree( (PTR)flp2 + TAG_SIZE ); |
170 | } else { |
167 | } else { |
171 | flp->len |= 1; // set allocated bit |
168 | flp->len |= 1; // set allocated bit |
172 | } |
169 | } |
173 | return( flp ); |
170 | return( flp ); |
174 | } |
171 | } |
175 | } |
172 | } |
176 | return( NULL ); |
173 | return( NULL ); |
177 | } |
174 | } |
178 | #endif |
175 | #endif |
179 | 176 | ||
180 | static frlptr __LinkUpNewMHeap( mheapptr p1 ) // originally __AddNewHeap() |
177 | static frlptr __LinkUpNewMHeap( mheapptr p1 ) // originally __AddNewHeap() |
181 | { |
178 | { |
182 | mheapptr p2; |
179 | mheapptr p2; |
183 | mheapptr p2_prev; |
180 | mheapptr p2_prev; |
184 | tag *last_tag; |
181 | tag *last_tag; |
185 | unsigned amount; |
182 | unsigned amount; |
186 | 183 | ||
187 | /* insert into ordered heap list (14-jun-91 AFS) */ |
184 | /* insert into ordered heap list (14-jun-91 AFS) */ |
188 | /* logic wasn't inserting heaps in proper ascending order */ |
185 | /* logic wasn't inserting heaps in proper ascending order */ |
189 | /* (09-nov-93 Fred) */ |
186 | /* (09-nov-93 Fred) */ |
190 | p2_prev = NULL; |
187 | p2_prev = NULL; |
191 | for( p2 = __nheapbeg; p2 != NULL; p2 = p2->next ) { |
188 | for( p2 = __nheapbeg; p2 != NULL; p2 = p2->next ) { |
192 | if( p1 < p2 ) break; |
189 | if( p1 < p2 ) break; |
193 | p2_prev = p2; |
190 | p2_prev = p2; |
194 | } |
191 | } |
195 | /* ascending order should be: p2_prev < p1 < p2 */ |
192 | /* ascending order should be: p2_prev < p1 < p2 */ |
196 | /* except for special cases when p2_prev and/or p2 are NULL */ |
193 | /* except for special cases when p2_prev and/or p2 are NULL */ |
197 | p1->prev = p2_prev; |
194 | p1->prev = p2_prev; |
198 | p1->next = p2; |
195 | p1->next = p2; |
199 | if( p2_prev != NULL ) { |
196 | if( p2_prev != NULL ) { |
200 | p2_prev->next = p1; |
197 | p2_prev->next = p1; |
201 | } else { /* add p1 to beginning of heap */ |
198 | } else { /* add p1 to beginning of heap */ |
202 | __nheapbeg = p1; |
199 | __nheapbeg = p1; |
203 | } |
200 | } |
204 | if( p2 != NULL ) { |
201 | if( p2 != NULL ) { |
205 | /* insert before 'p2' (list is non-empty) */ |
202 | /* insert before 'p2' (list is non-empty) */ |
206 | p2->prev = p1; |
203 | p2->prev = p1; |
207 | } |
204 | } |
208 | amount = p1->len - sizeof( struct miniheapblkp ); |
205 | amount = p1->len - sizeof( struct miniheapblkp ); |
209 | /* Fill out the new miniheap descriptor */ |
206 | /* Fill out the new miniheap descriptor */ |
210 | p1->freehead.len = 0; |
207 | p1->freehead.len = 0; |
211 | p1->freehead.prev = &p1->freehead; |
208 | p1->freehead.prev = &p1->freehead; |
212 | p1->freehead.next = &p1->freehead; |
209 | p1->freehead.next = &p1->freehead; |
213 | p1->rover = &p1->freehead; |
210 | p1->rover = &p1->freehead; |
214 | p1->b4rover = 0; |
211 | p1->b4rover = 0; |
215 | p1->numalloc = 0; |
212 | p1->numalloc = 0; |
216 | p1->numfree = 0; |
213 | p1->numfree = 0; |
217 | p1++; |
214 | p1++; |
218 | ((frlptr)p1)->len = amount; |
215 | ((frlptr)p1)->len = amount; |
219 | /* fix up end of heap links */ |
216 | /* fix up end of heap links */ |
220 | last_tag = (tag *) ( (PTR)p1 + amount ); |
217 | last_tag = (tag *) ( (PTR)p1 + amount ); |
221 | *last_tag = END_TAG; |
218 | *last_tag = END_TAG; |
222 | return( (frlptr) p1 ); |
219 | return( (frlptr) p1 ); |
223 | } |
220 | } |
224 | 221 | ||
225 | #if ! ( defined(__WINDOWS_286__) || \ |
222 | #if ! ( defined(__WINDOWS_286__) || \ |
226 | defined(__WINDOWS_386__) || \ |
223 | defined(__WINDOWS_386__) || \ |
227 | defined(__WARP__) || \ |
224 | defined(__WARP__) || \ |
228 | defined(__NT__) \ |
225 | defined(__NT__) \ |
229 | ) |
226 | ) |
230 | size_t __LastFree( void ) /* used by nheapgrow to know about adjustment */ |
227 | size_t __LastFree( void ) /* used by nheapgrow to know about adjustment */ |
231 | { |
228 | { |
232 | frlptr p1; |
229 | frlptr p1; |
233 | unsigned brk_value; |
230 | unsigned brk_value; |
234 | 231 | ||
235 | if( __nheapbeg == NULL ) { /* no heap? can't have free blocks */ |
232 | if( __nheapbeg == NULL ) { /* no heap? can't have free blocks */ |
236 | return( 0 ); |
233 | return( 0 ); |
237 | } |
234 | } |
238 | p1 = __nheapbeg->freehead.prev; /* point to last free block */ |
235 | p1 = __nheapbeg->freehead.prev; /* point to last free block */ |
239 | brk_value = (unsigned)((PTR)p1 + p1->len + TAG_SIZE ); |
236 | brk_value = (unsigned)((PTR)p1 + p1->len + TAG_SIZE ); |
240 | #if defined(__DOS_EXT__) |
237 | #if defined(__DOS_EXT__) |
241 | if( _IsPharLap() && !__X32VM) _curbrk = SegmentLimit(); /*19-feb-94*/ |
238 | if( _IsPharLap() && !__X32VM) _curbrk = SegmentLimit(); /*19-feb-94*/ |
242 | #endif |
239 | #endif |
243 | if( brk_value == _curbrk ) { /* if last free block is at the end */ |
240 | if( brk_value == _curbrk ) { /* if last free block is at the end */ |
244 | return( p1->len ); |
241 | return( p1->len ); |
245 | } |
242 | } |
246 | return( 0 ); |
243 | return( 0 ); |
247 | } |
244 | } |
248 | #endif |
245 | #endif |
249 | 246 | ||
250 | #if ! defined(__CALL21__) |
247 | #if ! defined(__CALL21__) |
251 | #if defined(__DOS_EXT__) |
248 | #if defined(__DOS_EXT__) |
252 | static void *RationalAlloc( size_t size ) |
249 | static void *RationalAlloc( size_t size ) |
253 | { |
250 | { |
254 | struct dpmi_hdr *dpmi; |
251 | struct dpmi_hdr *dpmi; |
255 | mheapptr mhp; |
252 | mheapptr mhp; |
256 | tiny_ret_t save_DOS_block; |
253 | tiny_ret_t save_DOS_block; |
257 | tiny_ret_t DOS_block; |
254 | tiny_ret_t DOS_block; |
258 | 255 | ||
259 | __FreeDPMIBlocks(); |
256 | __FreeDPMIBlocks(); |
260 | /* size is a multiple of 4k */ |
257 | /* size is a multiple of 4k */ |
261 | dpmi = TinyDPMIAlloc( size ); |
258 | dpmi = TinyDPMIAlloc( size ); |
262 | if( dpmi != NULL ) { |
259 | if( dpmi != NULL ) { |
263 | mhp = (mheapptr)( dpmi + 1 ); |
260 | mhp = (mheapptr)( dpmi + 1 ); |
264 | mhp->len = size - sizeof( struct dpmi_hdr ); |
261 | mhp->len = size - sizeof( struct dpmi_hdr ); |
265 | dpmi->dos_seg_value = 0; // indicate DPMI block |
262 | dpmi->dos_seg_value = 0; // indicate DPMI block |
266 | return( (void *)mhp ); |
263 | return( (void *)mhp ); |
267 | } |
264 | } |
268 | if( __minreal & 0xfff00000 ) { |
265 | if( __minreal & 0xfff00000 ) { |
269 | /* checks for users that want >1M real memory saved */ |
266 | /* checks for users that want >1M real memory saved */ |
270 | __minreal = 0xfffff; |
267 | __minreal = 0xfffff; |
271 | } |
268 | } |
272 | if( size > 0x00010000 ) { |
269 | if( size > 0x00010000 ) { |
273 | /* cannot allocate more than 64k from DOS real memory */ |
270 | /* cannot allocate more than 64k from DOS real memory */ |
274 | return( NULL ); |
271 | return( NULL ); |
275 | } |
272 | } |
276 | save_DOS_block = TinyAllocBlock(( __minreal >> 4 ) | 1 ); |
273 | save_DOS_block = TinyAllocBlock(( __minreal >> 4 ) | 1 ); |
277 | if( TINY_OK( save_DOS_block ) ) { |
274 | if( TINY_OK( save_DOS_block ) ) { |
278 | DOS_block = TinyAllocBlock( size >> 4 ); |
275 | DOS_block = TinyAllocBlock( size >> 4 ); |
279 | TinyFreeBlock( save_DOS_block ); |
276 | TinyFreeBlock( save_DOS_block ); |
280 | if( TINY_OK( DOS_block ) ) { |
277 | if( TINY_OK( DOS_block ) ) { |
281 | dpmi = (struct dpmi_hdr *) TinyDPMIBase( DOS_block ); |
278 | dpmi = (struct dpmi_hdr *) TinyDPMIBase( DOS_block ); |
282 | dpmi->dos_seg_value = DOS_block; |
279 | dpmi->dos_seg_value = DOS_block; |
283 | mhp = (mheapptr)( dpmi + 1 ); |
280 | mhp = (mheapptr)( dpmi + 1 ); |
284 | mhp->len = size - sizeof( struct dpmi_hdr ); |
281 | mhp->len = size - sizeof( struct dpmi_hdr ); |
285 | return( (void *)mhp ); |
282 | return( (void *)mhp ); |
286 | } |
283 | } |
287 | } |
284 | } |
288 | return( NULL ); |
285 | return( NULL ); |
289 | } |
286 | } |
290 | #endif |
287 | #endif |
291 | #endif |
288 | #endif |
292 | 289 | ||
293 | static int __AdjustAmount( unsigned *amount ) |
290 | static int __AdjustAmount( unsigned *amount ) |
294 | { |
291 | { |
295 | unsigned old_amount = *amount; |
292 | unsigned old_amount = *amount; |
296 | unsigned amt; |
293 | unsigned amt; |
297 | #if ! ( defined(__WINDOWS_286__) || \ |
294 | #if ! ( defined(__WINDOWS_286__) || \ |
298 | defined(__WINDOWS_386__) || \ |
295 | defined(__WINDOWS_386__) || \ |
299 | defined(__WARP__) || \ |
296 | defined(__WARP__) || \ |
300 | defined(__NT__) \ |
297 | defined(__NT__) \ |
301 | ) |
298 | ) |
302 | unsigned last_free_amt; |
299 | unsigned last_free_amt; |
303 | #endif |
300 | #endif |
304 | 301 | ||
305 | amt = old_amount; |
302 | amt = old_amount; |
306 | amt = ( amt + TAG_SIZE + ROUND_SIZE) & ~ROUND_SIZE; |
303 | amt = ( amt + TAG_SIZE + ROUND_SIZE) & ~ROUND_SIZE; |
307 | if( amt < old_amount ) { |
304 | if( amt < old_amount ) { |
308 | return( 0 ); |
305 | return( 0 ); |
309 | } |
306 | } |
310 | #if ! ( defined(__WINDOWS_286__) || \ |
307 | #if ! ( defined(__WINDOWS_286__) || \ |
311 | defined(__WINDOWS_386__) || \ |
308 | defined(__WINDOWS_386__) || \ |
312 | defined(__WARP__) || \ |
309 | defined(__WARP__) || \ |
313 | defined(__NT__) \ |
310 | defined(__NT__) \ |
314 | ) |
311 | ) |
315 | #if defined(__DOS_EXT__) |
312 | #if defined(__DOS_EXT__) |
316 | if( _IsRationalZeroBase() || _IsCodeBuilder() ) { |
313 | if( _IsRationalZeroBase() || _IsCodeBuilder() ) { |
317 | // Allocating extra to identify the dpmi block |
314 | // Allocating extra to identify the dpmi block |
318 | amt += sizeof(struct dpmi_hdr); |
315 | amt += sizeof(struct dpmi_hdr); |
319 | } else { |
316 | } else { |
320 | #else |
317 | #else |
321 | { |
318 | { |
322 | #endif |
319 | #endif |
323 | last_free_amt = __LastFree(); /* adjust for last free block */ |
320 | last_free_amt = __LastFree(); /* adjust for last free block */ |
324 | if( last_free_amt >= amt ) { |
321 | if( last_free_amt >= amt ) { |
325 | amt = 0; |
322 | amt = 0; |
326 | } else { |
323 | } else { |
327 | amt -= last_free_amt; |
324 | amt -= last_free_amt; |
328 | } |
325 | } |
329 | } |
326 | } |
330 | #endif |
327 | #endif |
331 | /* amount is even here */ |
328 | /* amount is even here */ |
332 | /* |
329 | /* |
333 | extra amounts (22-feb-91 AFS) |
330 | extra amounts (22-feb-91 AFS) |
334 | 331 | ||
335 | (1) adding a new heap needs: |
332 | (1) adding a new heap needs: |
336 | frl free block req'd for _nmalloc request |
333 | frl free block req'd for _nmalloc request |
337 | (frl is the MINIMUM because the block |
334 | (frl is the MINIMUM because the block |
338 | may be freed) |
335 | may be freed) |
339 | tag end of miniheap descriptor |
336 | tag end of miniheap descriptor |
340 | struct miniheapblkp start of miniheap descriptor |
337 | struct miniheapblkp start of miniheap descriptor |
341 | (2) extending heap needs: |
338 | (2) extending heap needs: |
342 | tag free block req'd for _nmalloc request |
339 | tag free block req'd for _nmalloc request |
343 | */ |
340 | */ |
344 | *amount = amt; |
341 | *amount = amt; |
345 | amt += ( (TAG_SIZE) + sizeof(frl) + sizeof(struct miniheapblkp) ); |
342 | amt += ( (TAG_SIZE) + sizeof(frl) + sizeof(struct miniheapblkp) ); |
346 | if( amt < *amount ) return( 0 ); |
343 | if( amt < *amount ) return( 0 ); |
347 | if( amt < _amblksiz ) { |
344 | if( amt < _amblksiz ) { |
348 | /* |
345 | /* |
349 | _amblksiz may not be even so round down to an even number |
346 | _amblksiz may not be even so round down to an even number |
350 | nb. pathological case: where _amblksiz == 0xffff, we don't |
347 | nb. pathological case: where _amblksiz == 0xffff, we don't |
351 | want the usual round up to even |
348 | want the usual round up to even |
352 | */ |
349 | */ |
353 | amt = _amblksiz & ~1u; |
350 | amt = _amblksiz & ~1u; |
354 | } |
351 | } |
355 | #if defined(__WINDOWS_386__) || \ |
352 | #if defined(__WINDOWS_386__) || \ |
356 | defined(__WARP__) || \ |
353 | defined(__WARP__) || \ |
357 | defined(__NT__) || \ |
354 | defined(__NT__) || \ |
358 | defined(__CALL21__) || \ |
355 | defined(__CALL21__) || \ |
359 | defined(__DOS_EXT__) |
356 | defined(__DOS_EXT__) |
360 | /* make sure amount is a multiple of 4k */ |
357 | /* make sure amount is a multiple of 4k */ |
361 | *amount = amt; |
358 | *amount = amt; |
362 | amt += 0x0fff; |
359 | amt += 0x0fff; |
363 | if( amt < *amount ) return( 0 ); |
360 | if( amt < *amount ) return( 0 ); |
364 | amt &= ~0x0fff; |
361 | amt &= ~0x0fff; |
365 | #endif |
362 | #endif |
366 | *amount = amt; |
363 | *amount = amt; |
367 | return( *amount != 0 ); |
364 | return( *amount != 0 ); |
368 | } |
365 | } |
369 | 366 | ||
370 | #if defined(__WINDOWS_286__) || \ |
367 | #if defined(__WINDOWS_286__) || \ |
371 | defined(__WINDOWS_386__) || \ |
368 | defined(__WINDOWS_386__) || \ |
372 | defined(__WARP__) || \ |
369 | defined(__WARP__) || \ |
373 | defined(__NT__) || \ |
370 | defined(__NT__) || \ |
374 | defined(__CALL21__) || \ |
371 | defined(__CALL21__) || \ |
375 | defined(__DOS_EXT__) |
372 | defined(__DOS_EXT__) |
376 | static int __CreateNewNHeap( unsigned amount ) |
373 | static int __CreateNewNHeap( unsigned amount ) |
377 | { |
374 | { |
378 | mheapptr p1; |
375 | mheapptr p1; |
379 | frlptr flp; |
376 | frlptr flp; |
380 | unsigned brk_value; |
377 | unsigned brk_value; |
381 | 378 | ||
382 | if( !__heap_enabled ) return( 0 ); |
379 | if( !__heap_enabled ) return( 0 ); |
383 | if( _curbrk == ~1u ) return( 0 ); |
380 | if( _curbrk == ~1u ) return( 0 ); |
384 | if( __AdjustAmount( &amount ) == 0 ) return( 0 ); |
381 | if( __AdjustAmount( &amount ) == 0 ) return( 0 ); |
385 | #if defined(__WINDOWS_286__) |
382 | #if defined(__WINDOWS_286__) |
386 | brk_value = (unsigned) LocalAlloc( LMEM_FIXED, amount ); |
383 | brk_value = (unsigned) LocalAlloc( LMEM_FIXED, amount ); |
387 | if( brk_value == 0 ) { |
384 | if( brk_value == 0 ) { |
388 | return( 0 ); |
385 | return( 0 ); |
389 | } |
386 | } |
390 | #elif defined(__WINDOWS_386__) |
387 | #elif defined(__WINDOWS_386__) |
391 | brk_value = (unsigned) DPMIAlloc( amount ); |
388 | brk_value = (unsigned) DPMIAlloc( amount ); |
392 | if( brk_value == 0 ) { |
389 | if( brk_value == 0 ) { |
393 | return( 0 ); |
390 | return( 0 ); |
394 | } |
391 | } |
395 | #elif defined(__WARP__) |
392 | #elif defined(__WARP__) |
396 | { |
393 | { |
397 | PBYTE p; |
394 | PBYTE p; |
398 | 395 | ||
399 | if( DosAllocMem( &p, amount, PAG_COMMIT|PAG_READ|PAG_WRITE ) ) { |
396 | if( DosAllocMem( &p, amount, PAG_COMMIT|PAG_READ|PAG_WRITE ) ) { |
400 | return( 0 ); |
397 | return( 0 ); |
401 | } |
398 | } |
402 | brk_value = (unsigned)p; |
399 | brk_value = (unsigned)p; |
403 | } |
400 | } |
404 | #elif defined(__NT__) |
401 | #elif defined(__NT__) |
405 | // brk_value = (unsigned) VirtualAlloc( NULL, amount, MEM_COMMIT, |
402 | // brk_value = (unsigned) VirtualAlloc( NULL, amount, MEM_COMMIT, |
406 | // PAGE_EXECUTE_READWRITE ); |
403 | // PAGE_EXECUTE_READWRITE ); |
407 | brk_value = (unsigned) UserAlloc (amount ); |
404 | brk_value = (unsigned) user_alloc(amount ); |
408 | 405 | ||
409 | //brk_value = (unsigned) LocalAlloc( LMEM_FIXED, amount ); |
406 | //brk_value = (unsigned) LocalAlloc( LMEM_FIXED, amount ); |
410 | if( brk_value == 0 ) { |
407 | if( brk_value == 0 ) { |
411 | return( 0 ); |
408 | return( 0 ); |
412 | } |
409 | } |
413 | #elif defined(__CALL21__) |
410 | #elif defined(__CALL21__) |
414 | { |
411 | { |
415 | tag _WCNEAR *tmp_tag; |
412 | tag _WCNEAR *tmp_tag; |
416 | 413 | ||
417 | tmp_tag = (tag _WCNEAR *)TinyMemAlloc( amount ); |
414 | tmp_tag = (tag _WCNEAR *)TinyMemAlloc( amount ); |
418 | if( tmp_tag == NULL ) { |
415 | if( tmp_tag == NULL ) { |
419 | return( 0 ); |
416 | return( 0 ); |
420 | } |
417 | } |
421 | /* make sure it will not look like the end of a heap */ |
418 | /* make sure it will not look like the end of a heap */ |
422 | tmp_tag[0] = ! END_TAG; |
419 | tmp_tag[0] = ! END_TAG; |
423 | brk_value = (unsigned) &tmp_tag[2]; |
420 | brk_value = (unsigned) &tmp_tag[2]; |
424 | amount -= 2 * TAG_SIZE; // 11-jun-95, subtract extra tag |
421 | amount -= 2 * TAG_SIZE; // 11-jun-95, subtract extra tag |
425 | } |
422 | } |
426 | #elif defined(__DOS_EXT__) |
423 | #elif defined(__DOS_EXT__) |
427 | // if( _IsRationalZeroBase() || _IsCodeBuilder() ) { |
424 | // if( _IsRationalZeroBase() || _IsCodeBuilder() ) { |
428 | { |
425 | { |
429 | tag *tmp_tag; |
426 | tag *tmp_tag; |
430 | 427 | ||
431 | if( _IsRational() ) { |
428 | if( _IsRational() ) { |
432 | tmp_tag = RationalAlloc( amount ); |
429 | tmp_tag = RationalAlloc( amount ); |
433 | if( tmp_tag ) amount = *tmp_tag; |
430 | if( tmp_tag ) amount = *tmp_tag; |
434 | } else { /* CodeBuilder */ |
431 | } else { /* CodeBuilder */ |
435 | tmp_tag = TinyCBAlloc( amount ); |
432 | tmp_tag = TinyCBAlloc( amount ); |
436 | amount -= TAG_SIZE; |
433 | amount -= TAG_SIZE; |
437 | } |
434 | } |
438 | if( tmp_tag == NULL ) { |
435 | if( tmp_tag == NULL ) { |
439 | return( 0 ); |
436 | return( 0 ); |
440 | } |
437 | } |
441 | brk_value = (unsigned) tmp_tag; |
438 | brk_value = (unsigned) tmp_tag; |
442 | } |
439 | } |
443 | // Pharlap, RSI/non-zero can never call this function |
440 | // Pharlap, RSI/non-zero can never call this function |
444 | #endif |
441 | #endif |
445 | if( amount - TAG_SIZE > amount ) { |
442 | if( amount - TAG_SIZE > amount ) { |
446 | return( 0 ); |
443 | return( 0 ); |
447 | } else { |
444 | } else { |
448 | amount -= TAG_SIZE; |
445 | amount -= TAG_SIZE; |
449 | } |
446 | } |
450 | if( amount < sizeof( struct miniheapblkp ) + sizeof( frl ) ) { |
447 | if( amount < sizeof( struct miniheapblkp ) + sizeof( frl ) ) { |
451 | /* there isn't enough for a heap block (struct miniheapblkp) and |
448 | /* there isn't enough for a heap block (struct miniheapblkp) and |
452 | one free block (frl) */ |
449 | one free block (frl) */ |
453 | return( 0 ); |
450 | return( 0 ); |
454 | } |
451 | } |
455 | /* we've got a new heap block */ |
452 | /* we've got a new heap block */ |
456 | p1 = (mheapptr) brk_value; |
453 | p1 = (mheapptr) brk_value; |
457 | p1->len = amount; |
454 | p1->len = amount; |
458 | // Now link it up |
455 | // Now link it up |
459 | flp = __LinkUpNewMHeap( p1 ); |
456 | flp = __LinkUpNewMHeap( p1 ); |
460 | amount = flp->len; |
457 | amount = flp->len; |
461 | /* build a block for _nfree() */ |
458 | /* build a block for _nfree() */ |
462 | flp->len = amount | 1; |
459 | flp->len = amount | 1; |
463 | ++p1->numalloc; /* 28-dec-90 */ |
460 | ++p1->numalloc; /* 28-dec-90 */ |
464 | p1->largest_blk = 0; |
461 | p1->largest_blk = 0; |
465 | _nfree( (PTR)flp + TAG_SIZE ); |
462 | _nfree( (PTR)flp + TAG_SIZE ); |
466 | return( 1 ); |
463 | return( 1 ); |
467 | } |
464 | } |
468 | #endif |
465 | #endif |
469 | 466 | ||
470 | int __ExpandDGROUP( unsigned amount ) |
467 | int __ExpandDGROUP( unsigned amount ) |
471 | { |
468 | { |
472 | #if defined(__WINDOWS_286__) || \ |
469 | #if defined(__WINDOWS_286__) || \ |
473 | defined(__WINDOWS_386__) || \ |
470 | defined(__WINDOWS_386__) || \ |
474 | defined(__WARP__) || \ |
471 | defined(__WARP__) || \ |
475 | defined(__NT__) || \ |
472 | defined(__NT__) || \ |
476 | defined(__CALL21__) |
473 | defined(__CALL21__) |
477 | // first try to free any available storage |
474 | // first try to free any available storage |
478 | _nheapshrink(); |
475 | _nheapshrink(); |
479 | return( __CreateNewNHeap( amount ) ); |
476 | return( __CreateNewNHeap( amount ) ); |
480 | #else |
477 | #else |
481 | mheapptr p1; |
478 | mheapptr p1; |
482 | frlptr flp; |
479 | frlptr flp; |
483 | unsigned brk_value; |
480 | unsigned brk_value; |
484 | tag *last_tag; |
481 | tag *last_tag; |
485 | unsigned new_brk_value; |
482 | unsigned new_brk_value; |
486 | void _WCNEAR *brk_ret; |
483 | void _WCNEAR *brk_ret; |
487 | 484 | ||
488 | #if defined(__DOS_EXT__) |
485 | #if defined(__DOS_EXT__) |
489 | if( ( _IsRationalZeroBase() || _IsCodeBuilder() ) ) { |
486 | if( ( _IsRationalZeroBase() || _IsCodeBuilder() ) ) { |
490 | return( __CreateNewNHeap( amount ) ); // Won't slice either |
487 | return( __CreateNewNHeap( amount ) ); // Won't slice either |
491 | } |
488 | } |
492 | // Rational non-zero based system should go through. |
489 | // Rational non-zero based system should go through. |
493 | #endif |
490 | #endif |
494 | if( !__heap_enabled ) return( 0 ); |
491 | if( !__heap_enabled ) return( 0 ); |
495 | if( _curbrk == ~1u ) return( 0 ); |
492 | if( _curbrk == ~1u ) return( 0 ); |
496 | if( __AdjustAmount( &amount ) == 0 ) return( 0 ); |
493 | if( __AdjustAmount( &amount ) == 0 ) return( 0 ); |
497 | #if defined(__DOS_EXT__) |
494 | #if defined(__DOS_EXT__) |
498 | if( _IsPharLap() && !__X32VM ) { /* 19-feb-94 */ |
495 | if( _IsPharLap() && !__X32VM ) { /* 19-feb-94 */ |
499 | _curbrk = SegmentLimit(); |
496 | _curbrk = SegmentLimit(); |
500 | } |
497 | } |
501 | #endif |
498 | #endif |
502 | new_brk_value = amount + _curbrk; |
499 | new_brk_value = amount + _curbrk; |
503 | if( new_brk_value < _curbrk ) { |
500 | if( new_brk_value < _curbrk ) { |
504 | new_brk_value = ~1u; |
501 | new_brk_value = ~1u; |
505 | } |
502 | } |
506 | brk_ret = __brk( new_brk_value ); |
503 | brk_ret = __brk( new_brk_value ); |
507 | if( brk_ret == (void _WCNEAR *) -1 ) { |
504 | if( brk_ret == (void _WCNEAR *) -1 ) { |
508 | return( 0 ); |
505 | return( 0 ); |
509 | } |
506 | } |
510 | brk_value = (unsigned) brk_ret; |
507 | brk_value = (unsigned) brk_ret; |
511 | if( brk_value > /*0xfff8*/ ~7u ) { |
508 | if( brk_value > /*0xfff8*/ ~7u ) { |
512 | return( 0 ); |
509 | return( 0 ); |
513 | } |
510 | } |
514 | if( new_brk_value <= brk_value ) { |
511 | if( new_brk_value <= brk_value ) { |
515 | return( 0 ); |
512 | return( 0 ); |
516 | } |
513 | } |
517 | amount = new_brk_value - brk_value; |
514 | amount = new_brk_value - brk_value; |
518 | if( amount - TAG_SIZE > amount ) { |
515 | if( amount - TAG_SIZE > amount ) { |
519 | return( 0 ); |
516 | return( 0 ); |
520 | } else { |
517 | } else { |
521 | amount -= TAG_SIZE; |
518 | amount -= TAG_SIZE; |
522 | } |
519 | } |
523 | for( p1 = __nheapbeg; p1 != NULL; p1 = p1->next ) { |
520 | for( p1 = __nheapbeg; p1 != NULL; p1 = p1->next ) { |
524 | if( p1->next == NULL ) break; |
521 | if( p1->next == NULL ) break; |
525 | if( (unsigned)p1 <= brk_value && |
522 | if( (unsigned)p1 <= brk_value && |
526 | ((unsigned)p1)+p1->len+TAG_SIZE >= brk_value ) break; |
523 | ((unsigned)p1)+p1->len+TAG_SIZE >= brk_value ) break; |
527 | } |
524 | } |
528 | if( (p1 != NULL) && |
525 | if( (p1 != NULL) && |
529 | ((brk_value - TAG_SIZE) == (unsigned)( (PTR)p1 + p1->len) ) ) { |
526 | ((brk_value - TAG_SIZE) == (unsigned)( (PTR)p1 + p1->len) ) ) { |
530 | /* we are extending the previous heap block (slicing) */ |
527 | /* we are extending the previous heap block (slicing) */ |
531 | /* nb. account for the end-of-heap tag */ |
528 | /* nb. account for the end-of-heap tag */ |
532 | brk_value -= TAG_SIZE; |
529 | brk_value -= TAG_SIZE; |
533 | amount += TAG_SIZE; |
530 | amount += TAG_SIZE; |
534 | flp = (frlptr) brk_value; |
531 | flp = (frlptr) brk_value; |
535 | /* adjust current entry in heap list */ |
532 | /* adjust current entry in heap list */ |
536 | p1->len += amount; |
533 | p1->len += amount; |
537 | /* fix up end of heap links */ |
534 | /* fix up end of heap links */ |
538 | last_tag = (tag *) ( (PTR)flp + amount ); |
535 | last_tag = (tag *) ( (PTR)flp + amount ); |
539 | last_tag[0] = END_TAG; |
536 | last_tag[0] = END_TAG; |
540 | } else { |
537 | } else { |
541 | if( amount < sizeof( struct miniheapblkp ) + sizeof( frl ) ) { |
538 | if( amount < sizeof( struct miniheapblkp ) + sizeof( frl ) ) { |
542 | /* there isn't enough for a heap block (struct miniheapblkp) and |
539 | /* there isn't enough for a heap block (struct miniheapblkp) and |
543 | one free block (frl) */ |
540 | one free block (frl) */ |
544 | return( 0 ); |
541 | return( 0 ); |
545 | } |
542 | } |
546 | // Initializing the near heap if __nheapbeg == NULL, |
543 | // Initializing the near heap if __nheapbeg == NULL, |
547 | // otherwise, a new mini-heap is getting linked up |
544 | // otherwise, a new mini-heap is getting linked up |
548 | p1 = (mheapptr) brk_value; |
545 | p1 = (mheapptr) brk_value; |
549 | p1->len = amount; |
546 | p1->len = amount; |
550 | flp = __LinkUpNewMHeap( p1 ); |
547 | flp = __LinkUpNewMHeap( p1 ); |
551 | amount = flp->len; |
548 | amount = flp->len; |
552 | } |
549 | } |
553 | /* build a block for _nfree() */ |
550 | /* build a block for _nfree() */ |
554 | flp->len = amount | 1; |
551 | flp->len = amount | 1; |
555 | ++p1->numalloc; /* 28-dec-90 */ |
552 | ++p1->numalloc; /* 28-dec-90 */ |
556 | p1->largest_blk = ~0; /* set to largest value to be safe */ |
553 | p1->largest_blk = ~0; /* set to largest value to be safe */ |
557 | _nfree( (PTR)flp + TAG_SIZE ); |
554 | _nfree( (PTR)flp + TAG_SIZE ); |
558 | return( 1 ); |
555 | return( 1 ); |
559 | #endif |
556 | #endif |
560 | }>=>=>>>>>>>>>> |
557 | }>=>=>>>>>>>>>> |