Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
553 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:  Near heap expansion routines.
28
*
29
****************************************************************************/
30
 
31
 
32
//#include "dll.h"        // needs to be first
33
#include "variety.h"
34
#include 
35
#include 
36
#include "heap.h"
37
#include "heapacc.h"
38
#if defined(__DOS_EXT__)
39
 #include "extender.h"
40
#endif
41
 
42
#if defined(__SMALL_DATA__)
43
 
44
_WCRTLINK void *_expand( void *stg, size_t amount )
45
{
46
    return( _nexpand( stg, amount ) );
47
}
48
 
49
#endif
50
 
51
#if defined(__AXP__) || defined(__PPC__)
52
    #define _SEGMENT int
53
#else
54
    #define _SEGMENT __segment
55
#endif
56
 
57
int __HeapManager_expand( _SEGMENT seg,
58
                          unsigned offset,
59
                          size_t req_size,
60
                          size_t *growth_size )
61
{
62
    #if defined(M_I86)
63
        typedef struct freelistp __based(seg) *fptr;
64
        typedef char __based(void) *cptr;
65
 
66
        struct miniheapblkp __based(seg) *hblk;
67
    #else
68
        typedef struct freelistp _WCNEAR *fptr;
69
        typedef char _WCNEAR *cptr;
70
 
71
        mheapptr hblk;
72
    #endif
73
    fptr        p1;
74
    fptr        p2;
75
    fptr        pnext;
76
    fptr        pprev;
77
    size_t      new_size;
78
    size_t      old_size;
79
    size_t      free_size;
80
 
81
    /* round (new_size + tag) to multiple of pointer size */
82
    new_size = (req_size + TAG_SIZE + ROUND_SIZE) & ~ROUND_SIZE;
83
    if( new_size < req_size ) new_size = ~0; //go for max
84
    if( new_size < FRL_SIZE ) {
85
        new_size = FRL_SIZE;
86
    }
87
    p1 = (fptr) ((cptr)offset - TAG_SIZE);
88
    old_size = p1->len & ~1;
89
    if( new_size > old_size ) {
90
        /* enlarging the current allocation */
91
        p2 = (fptr) ((cptr)p1 + old_size);
92
        *growth_size = new_size - old_size;
93
        for(;;) {
94
            free_size = p2->len;
95
            if( p2->len == END_TAG ) {
96
                return( __HM_TRYGROW );
97
            } else if( free_size & 1 ) { /* next piece is allocated */
98
                break;
99
            } else {
100
                pnext = p2->next;
101
                pprev = p2->prev;
102
 
103
                if( seg == _DGroup() ) { // near heap
104
                    for( hblk = __nheapbeg; hblk->next; hblk = hblk->next ) {
105
                        if( (fptr)hblk <= (fptr)offset &&
106
                            (fptr)((PTR)hblk+hblk->len) > (fptr)offset ) break;
107
                    }
108
                }
109
                #if defined(M_I86)
110
                    else {      // Based heap
111
                        hblk = 0;
112
                    }
113
                #endif
114
 
115
                if( hblk->rover == p2 ) { /* 09-feb-91 */
116
                    hblk->rover = p2->prev;
117
                }
118
                if( free_size < *growth_size  ||
119
                    free_size - *growth_size < FRL_SIZE ) {
120
                    /* unlink small free block */
121
                    pprev->next = pnext;
122
                    pnext->prev = pprev;
123
                    p1->len += free_size;
124
                    hblk->numfree--;
125
                    if( free_size >= *growth_size ) {
126
                        return( __HM_SUCCESS );
127
                    }
128
                    *growth_size -= free_size;
129
                    p2 = (fptr) ((cptr)p2 + free_size);
130
                } else {
131
                    p2 = (fptr) ((cptr)p2 + *growth_size);
132
                    p2->len = free_size - *growth_size;
133
                    p2->prev = pprev;
134
                    p2->next = pnext;
135
                    pprev->next = p2;
136
                    pnext->prev = p2;
137
                    p1->len += *growth_size;
138
                    return( __HM_SUCCESS );
139
                }
140
            }
141
        }
142
        /* no suitable free blocks behind, have to move block */
143
        return( __HM_FAIL );
144
    } else {
145
        /* shrinking the current allocation */
146
        if( old_size - new_size >= FRL_SIZE ) {
147
            /* block big enough to split */
148
            p1->len = new_size | 1;
149
            p1 = (fptr) ((cptr)p1 + new_size);
150
            p1->len = (old_size - new_size) | 1;
151
            if( seg == _DGroup() ) { // near heap
152
                for( hblk = __nheapbeg; hblk->next; hblk = hblk->next ) {
153
                    if( (fptr)hblk <= (fptr)offset &&
154
                        (fptr)((PTR)hblk+hblk->len) > (fptr)offset ) break;
155
                }
156
            }
157
            #if defined(M_I86)
158
                else    // Based heap
159
                    hblk = 0;
160
            #endif
161
            /* _bfree will decrement 'numalloc' 08-jul-91 */
162
            hblk->numalloc++;
163
            #if defined(M_I86)
164
                _bfree( seg, (cptr)p1 + TAG_SIZE );
165
                /* free the top portion */
166
            #else
167
                _nfree( (cptr)p1 + TAG_SIZE );
168
            #endif
169
        }
170
    }
171
    return( __HM_SUCCESS );
172
}
173
 
174
 
175
_WCRTLINK void _WCNEAR *_nexpand( void _WCNEAR *stg, size_t req_size )
176
    {
177
        struct {
178
            unsigned expanded : 1;
179
        } flags;
180
        int retval;
181
        size_t growth_size;
182
 
183
        flags.expanded = 0;
184
        _AccessNHeap();
185
        for( ;; ) {
186
            retval = __HeapManager_expand( _DGroup(),
187
                                           (unsigned) stg,
188
                                           req_size,
189
                                           &growth_size );
190
            if( retval == __HM_SUCCESS ) {
191
                _ReleaseNHeap();
192
                return( stg );
193
            }
194
            if( retval == __HM_FAIL || !__IsCtsNHeap() ) break;
195
            if( retval == __HM_TRYGROW ) {
196
                if( flags.expanded ) break;
197
                if( __ExpandDGROUP( growth_size ) == 0 ) {
198
                    break;
199
                }
200
                flags.expanded = 1;
201
            }
202
        }
203
        _ReleaseNHeap();
204
        return( NULL );
205
    }