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 _heapchk() and _nheapchk(). |
||
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 | |||
39 | frlptr __nheapchk_current; |
||
40 | |||
41 | static int checkFreeList( size_t *free_size ) |
||
42 | { |
||
43 | frlptr p; |
||
44 | frlptr end; |
||
45 | size_t new_size; |
||
46 | size_t free_list_size = 0; |
||
47 | mheapptr mhp; |
||
48 | |||
49 | for( mhp = __nheapbeg; mhp != NULL; mhp = mhp ->next ) { |
||
50 | /* check that the free list is a doubly linked ring */ |
||
51 | __nheapchk_current = p = mhp->freehead.next; |
||
52 | /* make sure we start off on the right track */ |
||
53 | if( (p->prev == NULL) || |
||
54 | (p->prev < &(mhp->freehead)) || |
||
55 | (((PTR)p->prev) > (((PTR)mhp)+mhp->len)) ) { |
||
56 | return( _HEAPBADNODE ); |
||
57 | } |
||
58 | if( p->prev->next != p ) { |
||
59 | return( _HEAPBADNODE ); |
||
60 | } |
||
61 | end = p; |
||
62 | do { |
||
63 | /* loop invariant: p->prev->next == p */ |
||
64 | /* are we still in a ring if we move to p->next? */ |
||
65 | /* nb. this check is sufficient to ensure that we will |
||
66 | never cycle */ |
||
67 | if( (p->next == NULL) || |
||
68 | (p->next < &(mhp->freehead)) || |
||
69 | (((PTR)p->next) > (((PTR)mhp)+mhp->len)) ) { |
||
70 | return( _HEAPBADNODE ); |
||
71 | } |
||
72 | if( p->next->prev != p ) { |
||
73 | return( _HEAPBADNODE ); |
||
74 | } |
||
75 | /* is entry allocated? */ |
||
76 | if( p->len & 1 ) { |
||
77 | return( _HEAPBADNODE ); |
||
78 | } |
||
79 | new_size = free_list_size + p->len; |
||
80 | if( new_size < free_list_size ) { |
||
81 | /* this is a case where we do not know where memory |
||
82 | is corrupted */ |
||
83 | return( _HEAPBADNODE ); |
||
84 | } |
||
85 | free_list_size = new_size; |
||
86 | __nheapchk_current = p = p->next; |
||
87 | } while( p != end ); |
||
88 | } |
||
89 | *free_size = free_list_size; |
||
90 | return( _HEAPOK ); |
||
91 | } |
||
92 | |||
93 | static int checkFree( frlptr p ) |
||
94 | { |
||
95 | frlptr next; |
||
96 | frlptr prev; |
||
97 | frlptr next_next; |
||
98 | frlptr prev_prev; |
||
99 | |||
100 | __nheapchk_current = p; |
||
101 | if( p->len & 1 ) { |
||
102 | return( _HEAPBADNODE ); |
||
103 | } |
||
104 | next = p->next; |
||
105 | prev = p->prev; |
||
106 | if( next->prev != p || prev->next != p ) { |
||
107 | return( _HEAPBADNODE ); |
||
108 | } |
||
109 | next_next = next->next; |
||
110 | prev_prev = prev->prev; |
||
111 | if( next_next->prev != next || prev_prev->next != prev ) { |
||
112 | return( _HEAPBADNODE ); |
||
113 | } |
||
114 | if( next_next->prev != next || prev_prev->next != prev ) { |
||
115 | return( _HEAPBADNODE ); |
||
116 | } |
||
117 | return( _HEAPOK ); |
||
118 | } |
||
119 | |||
120 | #if defined(__SMALL_DATA__) |
||
121 | _WCRTLINK int _heapchk( void ) |
||
122 | { |
||
123 | return( _nheapchk() ); |
||
124 | } |
||
125 | #endif |
||
126 | |||
127 | _WCRTLINK int _nheapchk( void ) |
||
128 | { |
||
129 | struct _heapinfo hi; |
||
130 | int heap_status; |
||
131 | size_t free_size; |
||
132 | |||
133 | _AccessNHeap(); |
||
134 | heap_status = checkFreeList( &free_size ); |
||
135 | if( heap_status != _HEAPOK ) { |
||
136 | _ReleaseNHeap(); |
||
137 | return( heap_status ); |
||
138 | } |
||
139 | hi._pentry = NULL; |
||
140 | for(;;) { |
||
141 | heap_status = __NHeapWalk( &hi, __nheapbeg ); |
||
142 | if( heap_status != _HEAPOK ) |
||
143 | break; |
||
144 | if( hi._useflag == _FREEENTRY ) { |
||
145 | heap_status = checkFree( (frlptr) hi._pentry ); |
||
146 | if( heap_status != _HEAPOK ) |
||
147 | break; |
||
148 | free_size -= hi._size; |
||
149 | } |
||
150 | } |
||
151 | if( free_size != 0 ) { |
||
152 | heap_status = _HEAPBADNODE; |
||
153 | } else if( heap_status == _HEAPBADPTR ) { |
||
154 | heap_status = _HEAPBADNODE; |
||
155 | } else { |
||
156 | if( heap_status == _HEAPEND ) { |
||
157 | heap_status = _HEAPOK; |
||
158 | } |
||
159 | } |
||
160 | _ReleaseNHeap(); |
||
161 | return( heap_status ); |
||
162 | }>>> |