Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
359 serge 1
/****************************************************************************
2
*
3
*                            Open Watcom Project
4
*
5
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
6
*
7
*  ========================================================================
8
*
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
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
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
15
*    available at www.sybase.com/developer/opensource.
16
*
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
19
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
20
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
21
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
22
*    NON-INFRINGEMENT. Please see the License for the specific language
23
*    governing rights and limitations under the License.
24
*
25
*  ========================================================================
26
*
27
* Description:  Implementation of near _heapmin() and _nheapmin().
28
*
29
****************************************************************************/
30
 
31
 
32
//#include "dll.h"        // needs to be first
33
#include "variety.h"
34
#include 
35
#include 
36
#include 
37
#include "heap.h"
38
#include "heapacc.h"
39
#if defined(__DOS_EXT__)
40
// #include "extender.h"
41
#endif
42
#if defined(__WINDOWS_286__) || defined(__NT__)
43
int _stdcall UserFree(void* p);
44
// #include "windows.h"
45
#endif
46
#if defined(__OS2__)
47
// #include 
48
#endif
49
#if defined(__WINDOWS_386__)
50
// extern int __pascal DPMIFree(unsigned long);   // windows extender function
51
#endif
52
#if defined(__CALL21__)
53
// #include "tinyio.h"
54
#endif
55
 
56
#if defined(__SMALL_DATA__)
57
 
58
_WCRTLINK int _heapshrink( void )
59
{
60
    return( _nheapshrink() );
61
}
62
 
63
_WCRTLINK int _heapmin( void )
64
{
65
    return( _nheapshrink() );
66
}
67
 
68
#endif
69
 
70
_WCRTLINK int _nheapmin( void )
71
{
72
    return( _nheapshrink() );
73
}
74
 
75
#if defined(__WARP__)        || \
76
    defined(__WINDOWS_286__) || \
77
    defined(__WINDOWS_386__) || \
78
    defined(__NT__)          || \
79
    defined(__CALL21__)
80
static int __ReturnMemToSystem( mheapptr mhp )
81
{
82
        mheapptr pnext;
83
 
84
        pnext = mhp->next;
85
#if defined(__WARP__)
86
        if( DosFreeMem( (PBYTE)mhp ) ) return( -1 );
87
#elif defined(__NT__)
88
        //if( LocalFree( (HLOCAL)mhp ) != NULL ) return( -1 );
89
//        if (!VirtualFree(mhp, 0, MEM_RELEASE))
90
//            return -1;
91
        if(!UserFree(mhp))
92
          return -1;
93
 
94
#elif defined(__WINDOWS_386__)
95
        if( DPMIFree( (unsigned long)mhp ) != 0 ) return( -1 );
96
#elif defined(__WINDOWS_286__)
97
        if( LocalFree( (HLOCAL)mhp ) != NULL ) return( -1 );
98
#elif defined(__CALL21__)
99
        // No way to free storage under OSI
100
        if( mhp ) return( -1 );
101
#endif
102
        if( __MiniHeapRover == mhp ) {  // Update rovers
103
            if( pnext ) {
104
                __MiniHeapRover = pnext;
105
            } else {
106
                __MiniHeapRover = __nheapbeg;
107
                __LargestSizeB4MiniHeapRover = 0;
108
            }
109
        }
110
        if( __MiniHeapFreeRover == mhp ) {
111
            __MiniHeapFreeRover = 0;
112
        }
113
        return( 0 ); // success
114
}
115
 
116
static void __ReleaseMiniHeap( mheapptr mhp )
117
{
118
    mheapptr pprev;
119
    mheapptr pnext;
120
 
121
    pprev = mhp->prev;
122
    pnext = mhp->next;
123
    if( __ReturnMemToSystem( mhp ) == 0 ) {
124
        if( pprev == NULL ) {
125
            __nheapbeg = pnext;
126
        } else {
127
            pprev->next = pnext;
128
        }
129
        if( pnext != NULL )  pnext->prev = pprev;
130
    } //else: do not unlink if the memory cannot be freed successfully
131
}
132
 
133
#endif
134
 
135
_WCRTLINK int _nheapshrink( void )
136
{
137
    mheapptr mhp;
138
#if !defined(__WARP__)        && \
139
    !defined(__WINDOWS_286__) && \
140
    !defined(__WINDOWS_386__) && \
141
    !defined(__NT__)          && \
142
    !defined(__CALL21__)
143
    // Shrink by adjusting _curbrk
144
 
145
    frlptr last_free;
146
    frlptr end_tag;
147
    unsigned new_brk;
148
 
149
    _AccessNHeap();
150
    #if defined(__DOS_EXT__)
151
    if( !_IsRationalZeroBase() && !_IsCodeBuilder() ) {
152
    #endif
153
        if( __nheapbeg == NULL ) {
154
            _ReleaseNHeap();
155
            return( 0 ); // No near heap, can't shrink
156
        }
157
        /* Goto the end of miniheaplist (if there's more than 1 blk) */
158
        for( mhp = __nheapbeg; mhp->next; mhp = mhp->next );
159
        /* check that last free block is at end of heap */
160
        last_free = mhp->freehead.prev;
161
        end_tag = (frlptr) ( (PTR)last_free + last_free->len );
162
        if( end_tag->len != END_TAG ) {
163
            _ReleaseNHeap();
164
            return( 0 );
165
        }
166
        if( end_tag != (frlptr) ((PTR)mhp + mhp->len ) ) {
167
            _ReleaseNHeap();
168
            return( 0 );
169
        }
170
        #if defined(__DOS_EXT__)
171
        // only shrink if we can shave off at least 4k
172
        if( last_free->len < 0x1000 ) {
173
            _ReleaseNHeap();
174
            return( 0 );
175
        }
176
        #else
177
        if( last_free->len <= sizeof( frl ) ) {
178
            _ReleaseNHeap();
179
            return( 0 );
180
        }
181
        #endif
182
        /* make sure there hasn't been an external change in _curbrk */
183
        if( sbrk( 0 ) != &(end_tag->prev) ) {
184
            _ReleaseNHeap();
185
            return( 0 );
186
        }
187
        /* calculate adjustment factor */
188
        if( mhp->len-last_free->len > sizeof( struct miniheapblkp ) ) {
189
            // this miniheapblk is still being used
190
            #if defined(__DOS_EXT__)
191
                frlptr new_last_free;
192
                new_last_free = (frlptr)((((unsigned)last_free + 0xfff) & ~0xfff) - TAG_SIZE);
193
                if( new_last_free == last_free ) {
194
            #endif
195
                    // remove entire entry
196
                    mhp->len -= last_free->len;
197
                    --mhp->numfree;
198
                    // Relink the freelist entries, and update the rover
199
                    mhp->freehead.prev = last_free->prev;
200
                    last_free->prev->next = &mhp->freehead;
201
                    if( mhp->rover == last_free ) mhp->rover = last_free->prev;
202
            #if defined(__DOS_EXT__)
203
                } else {
204
                    // just shrink the last free entry
205
                    mhp->len -= last_free->len;
206
                    last_free->len = (PTR)new_last_free - (PTR)last_free;
207
                    mhp->len += last_free->len;
208
                    last_free = new_last_free;
209
                }
210
            #endif
211
            last_free->len = END_TAG;
212
            new_brk = (unsigned) ((PTR)last_free + TAG_SIZE );
213
        } else {
214
            // we can remove this miniheapblk
215
            if( mhp->prev ) { // Not the first miniheapblk
216
                mhp->prev->next = NULL;
217
                new_brk = (unsigned)mhp;//->prev + (unsigned)mhp->prev->len;
218
            } else { // Is the first miniheapblk
219
                new_brk = (unsigned)__nheapbeg;
220
                __nheapbeg = NULL;
221
            }
222
            // Update rover info
223
            if( __MiniHeapRover == mhp ) {
224
                __MiniHeapRover = __nheapbeg;
225
                __LargestSizeB4MiniHeapRover = 0;
226
            }
227
        }
228
 
229
        if( __brk( new_brk ) == (void _WCNEAR *) -1 ) {
230
            _ReleaseNHeap();
231
            return( -1 );
232
        }
233
        _ReleaseNHeap();
234
        return( 0 );
235
    #if defined(__DOS_EXT__)
236
    }
237
    __FreeDPMIBlocks(); // For RSI/zero-base and Intel CB
238
    _ReleaseNHeap();
239
    return( 0 );
240
    #endif
241
#else
242
    // Shrink by releasing mini-heaps
243
    {
244
        mheapptr pnext;
245
 
246
        _AccessNHeap();
247
        for( mhp = __nheapbeg; mhp; mhp = pnext ) {
248
            pnext = mhp->next;
249
            if( mhp->len - sizeof(struct miniheapblkp) ==
250
                (mhp->freehead.prev)->len ) __ReleaseMiniHeap( mhp );
251
        }
252
        _ReleaseNHeap();
253
        return( 0 );
254
    }
255
#endif
256
}