5 #include <lwp_config.h>
10 u32
__lwp_heap_init(heap_cntrl
*theheap
,void *start_addr
,u32 size
,u32 pg_size
)
15 if(!__lwp_heap_pgsize_valid(pg_size
) || size
<HEAP_MIN_SIZE
) return 0;
17 _CPU_ISR_Disable(level
);
18 theheap
->pg_size
= pg_size
;
19 dsize
= (size
- HEAP_OVERHEAD
);
21 block
= (heap_block
*)start_addr
;
22 block
->back_flag
= HEAP_DUMMY_FLAG
;
23 block
->front_flag
= dsize
;
24 block
->next
= __lwp_heap_tail(theheap
);
25 block
->prev
= __lwp_heap_head(theheap
);
27 theheap
->start
= block
;
28 theheap
->first
= block
;
29 theheap
->perm_null
= NULL
;
30 theheap
->last
= block
;
32 block
= __lwp_heap_nextblock(block
);
33 block
->back_flag
= dsize
;
34 block
->front_flag
= HEAP_DUMMY_FLAG
;
35 theheap
->final
= block
;
36 _CPU_ISR_Restore(level
);
38 return (dsize
- HEAP_BLOCK_USED_OVERHEAD
);
41 void* __lwp_heap_allocate(heap_cntrl
*theheap
,u32 size
)
46 heap_block
*next_block
;
47 heap_block
*tmp_block
;
52 if(size
>=(-1-HEAP_BLOCK_USED_OVERHEAD
)) return NULL
;
54 _CPU_ISR_Disable(level
);
55 excess
= (size
% theheap
->pg_size
);
56 dsize
= (size
+ theheap
->pg_size
+ HEAP_BLOCK_USED_OVERHEAD
);
59 dsize
+= (theheap
->pg_size
- excess
);
61 if(dsize
<sizeof(heap_block
)) dsize
= sizeof(heap_block
);
63 for(block
=theheap
->first
;;block
=block
->next
) {
64 if(block
==__lwp_heap_tail(theheap
)) {
65 _CPU_ISR_Restore(level
);
68 if(block
->front_flag
>=dsize
) break;
71 if((block
->front_flag
-dsize
)>(theheap
->pg_size
+HEAP_BLOCK_USED_OVERHEAD
)) {
72 block
->front_flag
-= dsize
;
73 next_block
= __lwp_heap_nextblock(block
);
74 next_block
->back_flag
= block
->front_flag
;
76 tmp_block
= __lwp_heap_blockat(next_block
,dsize
);
77 tmp_block
->back_flag
= next_block
->front_flag
= __lwp_heap_buildflag(dsize
,HEAP_BLOCK_USED
);
79 ptr
= __lwp_heap_startuser(next_block
);
81 next_block
= __lwp_heap_nextblock(block
);
82 next_block
->back_flag
= __lwp_heap_buildflag(block
->front_flag
,HEAP_BLOCK_USED
);
84 block
->front_flag
= next_block
->back_flag
;
85 block
->next
->prev
= block
->prev
;
86 block
->prev
->next
= block
->next
;
88 ptr
= __lwp_heap_startuser(block
);
91 offset
= (theheap
->pg_size
- ((u32
)ptr
&(theheap
->pg_size
-1)));
93 *(((u32
*)ptr
)-1) = offset
;
94 _CPU_ISR_Restore(level
);
99 BOOL
__lwp_heap_free(heap_cntrl
*theheap
,void *ptr
)
102 heap_block
*next_block
;
103 heap_block
*new_next
;
104 heap_block
*prev_block
;
105 heap_block
*tmp_block
;
108 _CPU_ISR_Disable(level
);
110 block
= __lwp_heap_usrblockat(ptr
);
111 if(!__lwp_heap_blockin(theheap
,block
) || __lwp_heap_blockfree(block
)) {
112 _CPU_ISR_Restore(level
);
116 dsize
= __lwp_heap_blocksize(block
);
117 next_block
= __lwp_heap_blockat(block
,dsize
);
119 if(!__lwp_heap_blockin(theheap
,next_block
) || (block
->front_flag
!=next_block
->back_flag
)) {
120 _CPU_ISR_Restore(level
);
124 if(__lwp_heap_prev_blockfree(block
)) {
125 prev_block
= __lwp_heap_prevblock(block
);
126 if(!__lwp_heap_blockin(theheap
,prev_block
)) {
127 _CPU_ISR_Restore(level
);
131 if(__lwp_heap_blockfree(next_block
)) {
132 prev_block
->front_flag
+= next_block
->front_flag
+dsize
;
133 tmp_block
= __lwp_heap_nextblock(prev_block
);
134 tmp_block
->back_flag
= prev_block
->front_flag
;
135 next_block
->next
->prev
= next_block
->prev
;
136 next_block
->prev
->next
= next_block
->next
;
138 prev_block
->front_flag
= next_block
->back_flag
= prev_block
->front_flag
+dsize
;
140 } else if(__lwp_heap_blockfree(next_block
)) {
141 block
->front_flag
= dsize
+next_block
->front_flag
;
142 new_next
= __lwp_heap_nextblock(block
);
143 new_next
->back_flag
= block
->front_flag
;
144 block
->next
= next_block
->next
;
145 block
->prev
= next_block
->prev
;
146 next_block
->prev
->next
= block
;
147 next_block
->next
->prev
= block
;
149 if(theheap
->first
==next_block
) theheap
->first
= block
;
151 next_block
->back_flag
= block
->front_flag
= dsize
;
152 block
->prev
= __lwp_heap_head(theheap
);
153 block
->next
= theheap
->first
;
154 theheap
->first
= block
;
155 block
->next
->prev
= block
;
157 _CPU_ISR_Restore(level
);
162 u32
__lwp_heap_getinfo(heap_cntrl
*theheap
,heap_iblock
*theinfo
)
165 heap_block
*theblock
= NULL
;
166 heap_block
*nextblock
= NULL
;
168 theinfo
->free_blocks
= 0;
169 theinfo
->free_size
= 0;
170 theinfo
->used_blocks
= 0;
171 theinfo
->used_size
= 0;
173 if(!__sys_state_up(__sys_state_get())) return 1;
175 theblock
= theheap
->start
;
176 if(theblock
->back_flag
!=HEAP_DUMMY_FLAG
) return 2;
179 if(__lwp_heap_blockfree(theblock
)) {
180 theinfo
->free_blocks
++;
181 theinfo
->free_size
+= __lwp_heap_blocksize(theblock
);
183 theinfo
->used_blocks
++;
184 theinfo
->used_size
+= __lwp_heap_blocksize(theblock
);
187 if(theblock
->front_flag
!=HEAP_DUMMY_FLAG
) {
188 nextblock
= __lwp_heap_nextblock(theblock
);
189 if(theblock
->front_flag
!=nextblock
->back_flag
) return 2;
192 if(theblock
->front_flag
==HEAP_DUMMY_FLAG
)
195 theblock
= nextblock
;