Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7538 leency 1
;MM_ = MemoryManager
2
;Этот модуль позволяет выделять память маленькими кусочками, оптимально используя
3
;страницы памяти
4
;Блоки - это одна или несколько страниц, которые имеют запись
5
;в MM_BlockInfo и которые в конце имеют стекообразную структуру(в смысле
6
;растёт к меньшим адресам), заканчивающейся dword 0. В начале блока
7
;находятся данные. В структуре находятся пары dword'ов: начало
8
;участков, их конец(посл. байт+1). Эти пары всегда сортируются по
9
;расположению описываемых
10
;участков в обратном порядке, т.е. в самом конце блока будет пара данных
11
;на самый первый участок. Для выделения памяти нужно найти блок, в котором
12
;достаточно места (причём необходимое место = запрашиваемый объём + место
13
;под пару с данными в конце блока) и вставить пару с нужными данными.
14
;Для удаления участка нужно только убрать из пар пару с нужным участком
15
;и поправить расположение остальных пар.
16
;begData1.....endData1,begData2...endData2,.......0,beg2,end2,beg1,end1
17
 
18
 
19
;выделяет память
20
;return eax = указатель на выделеный блок
21
;proc MM_AllocMem stdcall,Size:DWORD
22
 
23
;БАГ в выделении крупных кусков: всегда выделяет новую страницу
24
 
25
 
26
 
27
align 4
28
MM_AllocMem:
29
	Size equ ebp+8
30
	begFree equ ebp-8 ;начало
31
	endFree equ ebp-4 ;и конец свободного места от конца инфы до
32
	endArea equ ebp-12
33
	push	ebp
34
	mov	ebp,esp
35
	add	esp,-4*3
36
	push	ebx edi esi
37
;dps 'MEM: '
38
;dph [Size]
39
;dps ' '
40
				;начала пар записей
41
	mov	edx,[MM_NBlocks]
42
	cmp	edx,0
43
	jne	.BegTestBlocks	       ;если блоков нет, то добавить новый
44
	mov	ecx,[Size]
45
	call	AddBlock
46
	jmp	.return
47
align 4
48
 .BegTestBlocks:
49
 
50
 
51
	xor	ebx,ebx
52
	mov	ecx,edx
53
align 4
54
  .TestBlock:	 ;проверка блока
55
		   ;проверка: есть ли место для ещё одной пары
56
	mov	edi,[MM_BlocksInfo+ebx]
57
	add	edi,[MM_BlocksInfo+ebx+4]
58
	mov	[endArea], edi
59
	sub	edi,4
60
 
61
	cmp	dword[edi],0	 ;если в блоке нет ни одной записи
62
	jne	.NoEmptyBlock
63
	mov	eax,[MM_BlocksInfo+ebx]
64
	mov	dword[edi-4],eax
65
	mov	dword[edi],eax
66
	mov	edx,[Size]
67
	add	dword[edi],edx
68
	mov	dword[edi-8],0
69
	jmp	.return
70
align 4
71
 .NoEmptyBlock:
72
	xor	eax,eax
73
	push	ecx
74
	or	ecx,-1
75
	std
76
	repne	scasd
77
	cld
78
	pop	ecx
79
	mov	eax,[edi+12] ;конец посл участка
80
	add	eax,4
81
	cmp	eax,edi
82
	jb	@f
83
 
84
	add	ebx,8
85
	dec	ecx
86
	jnz	.TestBlock
87
 
88
	mov	ecx,[Size]
89
	call	AddBlock
90
	jmp	.return
91
     @@:
92
 
93
 
94
	mov	[begFree],eax  ;eax = конец посл. участка + 4
95
	mov	[endFree],edi  ;edi = указатель на конец посл участка - 12
96
	sub	dword[begFree],4
97
	add	dword[endFree],12
98
 
99
   ;проверка перед всеми участками
100
	mov	edi,[MM_BlocksInfo+ebx]
101
	mov	eax,[endArea]
102
	mov	eax,[eax-8]
103
	sub	eax,[MM_BlocksInfo+ebx]
104
	cmp	eax,[Size]
105
	ja	.AddInBegBlock
106
 
107
   ;проверка между участками
108
	mov	eax,[endArea]
109
	cmp	dword[eax-12],0
110
	je	.EndTest ;если в блоке только 1 участок
111
 
112
	sub	eax,4
113
     @@:
114
	mov	edi,[eax-12]
115
	sub	edi,[eax]
116
	cmp	edi,[Size]
117
	jae	.AddInMiddle
118
	sub	eax,8
119
	cmp	dword[eax-8],0
120
	jne	@b
121
 
122
   .EndTest:
123
 
124
   ;проверка после всех блоков
125
	mov	eax,[begFree]
126
	mov	edi,[endFree]
127
	lea	esi,[edi-8]    ;8 - место под запись
128
	sub	esi,eax
129
 
130
	cmp	esi,[Size]
131
	ja	.AddInEnd
132
 
133
	add	ebx,8
134
	dec	ecx
135
	jnz	.TestBlock
136
 
137
	mov	ecx,[Size]
138
	call	AddBlock
139
 
140
	jmp	.return
141
align 4
142
  .AddInBegBlock: ;Добавить в начало. В edi начало блока
143
	;pop     eax
144
 
145
	mov	eax,edi
146
	add	eax,[MM_BlocksInfo+ebx+4]
147
	sub	eax,4
148
	push	eax
149
	call	MoveRecordsLeft
150
	pop	eax
151
	mov	[eax-4],edi
152
	push	edi
153
	add	edi,[Size]
154
	mov	[eax],edi
155
	pop	eax
156
 
157
	jmp	.return
158
align 4
159
  .AddInMiddle:  ;Добавить между участками, еах=конец участка перед свободным местом
160
 
161
	;pop     ecx   ;add     esp,4
162
	push	eax
163
	sub	eax,8
164
	call	MoveRecordsLeft
165
	pop	eax
166
 
167
	mov	edx,[eax]
168
	mov	[eax-12],edx
169
	add	edx,[Size]
170
	mov	[eax-8],edx
171
	mov	eax,[eax]
172
	jmp	.return
173
align 4
174
  .AddInEnd:  ;Добавить после участков. еdi=указатель на 2ой элем пары с инфой о посл участке
175
 
176
	;add     esp,4
177
	mov	eax,[edi]
178
	mov	[edi-12],eax
179
	push	eax
180
	add	eax,[Size]
181
	mov	[edi-8],eax
182
	pop	eax
183
 
184
.return:
185
 
186
	pop	esi edi ebx
187
	leave
188
	ret 4
189
 
190
restore Xren
191
restore Size
192
restore begFree
193
restore endFree
194
 
195
 
196
 
197
;eax - первый сдвигаемый dword
198
;сдвигает пары dword'ов на 8B назад включая dword 0
199
align 4
200
proc MoveRecordsLeft
201
local	var1:DWORD,\
202
	var2:DWORD
203
 
204
	p2p	[var1],[eax]
205
	p2p	[var2],[eax-4]
206
 
207
     @@:
208
	sub	eax,8
209
	cmp	dword[var1],0
210
	je	@f
211
 
212
	push	dword[eax]
213
	p2p	[eax],[var1]
214
	pop	dword[var1]
215
 
216
	push	dword[eax-4]
217
	p2p	[eax-4],[var2]
218
	pop	dword[var2]
219
	jmp	@b
220
      @@:
221
 
222
	mov	dword[eax],0
223
	ret
224
endp
225
 
226
;ecx = размер требуемого участка
227
;добавляет блок и создаёт в нём участок размером ecx
228
align 4
229
proc AddBlock
230
	mov	edx,[MM_NBlocks]
231
	inc	edx
232
	cmp	edx,MM_MAX_BLOCKS
233
	ja	.ErrAlloc
234
 
235
	push	ecx
236
	add	ecx,12
237
 
238
	test	ecx,0FFFh	   ;округляем до большей границы страницы
239
	jz	@f
240
	add	ecx,1000h
241
	and	ecx,0FFFFF000h
242
      @@:
243
 
244
	mcall	68,12,ecx
245
	mov	[MM_NBlocks],edx     ;заполнение данных о блоке
246
	mov	[edx*4*2-4*2+MM_BlocksInfo],eax  ;begin
247
	mov	[edx*4*2-4+MM_BlocksInfo],ecx	 ;size
248
;dps 'Block '
249
;dph eax
250
;dps ' '
251
;dph ecx
252
;dnl
253
	mov	edx,eax
254
	add	edx,ecx
255
	mov	[edx-8],eax
256
	pop	dword[edx-4]
257
	add	[edx-4],eax
258
	mov	dword[edx-12],0
259
	ret
260
 
261
 .ErrAlloc:
262
	pop	ecx
263
	xor	eax,eax
264
	ret
265
endp
266
;-------------------------------------------------------------------------------
267
 
268
 
269
;удаляет  память
270
;proc MM_DelMem Pointer:DWORD
271
align 4
272
MM_DelMem:
273
	Pointer equ ebp+8
274
	push	ebp
275
	mov	ebp,esp
276
; int3
277
	push	ebx
278
	mov	ecx,[MM_NBlocks]
279
	test	ecx,ecx
280
	jnz	@f
281
	xor	eax,eax
282
	pop	ebx
283
	leave
284
	ret 4
285
      @@:
286
 
287
	mov	eax,[Pointer]
288
	xor	ebx,ebx ;ebx - (номер блока)*8
289
   .TestBlocks:
290
	mov	edx,[MM_BlocksInfo+ebx]
291
	add	edx,[MM_BlocksInfo+ebx+4]
292
	sub	edx,8	      ;edx - указатель на 1ую пару
293
 
294
     .TestMems:
295
	cmp	[edx],eax
296
	je	.FoundMem
297
 
298
	sub	edx,8
299
	cmp	dword[edx+4],0
300
	jne	.TestMems
301
 
302
	add	ebx,4
303
	loop	.TestBlocks
304
 
305
	xor	eax,eax
306
	pop	ebx
307
	leave
308
	ret 4
309
 
310
   .FoundMem:
311
	cmp	dword[edx-4],0
312
	jz	.EndDelMem
313
 
314
   .NextMoveMem:
315
	p2p    [edx+4],[edx-4]
316
	p2p    [edx],[edx-8]
317
	sub	edx,8
318
	cmp	dword[edx-4],0
319
	jnz	.NextMoveMem
320
 
321
    .EndDelMem:
322
	mov	dword[edx+4],0
323
	mov	dword[edx],0
324
 
325
	mov	eax,1
326
	pop	ebx
327
	leave
328
	ret 4
329
 
330
restore Pointer