Subversion Repositories Kolibri OS

Rev

Rev 1159 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 983 $
9
 
10
 
11
struc MEM_BLOCK
12
{  .next_block	dd ?
13
   .prev_block	dd ? ;+4
14
   .list_fd	dd ? ;+8
15
   .list_bk	dd ? ;+12
16
   .base	dd ? ;+16
17
   .size	dd ? ;+20
18
   .flags	dd ? ;+24
19
   .handle	dd ? ;+28
20
}
21
 
22
MEM_LIST_OFFSET equ  8
23
FREE_BLOCK	equ  4
24
USED_BLOCK	equ  8
25
DONT_FREE_BLOCK equ  10h
26
 
27
virtual at 0
28
  MEM_BLOCK MEM_BLOCK
29
end virtual
30
 
31
MEM_BLOCK_SIZE equ 8*4
32
 
33
block_next   equ MEM_BLOCK.next_block
34
block_prev   equ MEM_BLOCK.prev_block
35
list_fd      equ MEM_BLOCK.list_fd
36
list_bk      equ MEM_BLOCK.list_bk
37
block_base   equ MEM_BLOCK.base
38
block_size   equ MEM_BLOCK.size
39
block_flags  equ MEM_BLOCK.flags
40
 
41
macro calc_index op
42
{	   shr op, 12
43
	   dec op
44
	   cmp op, 63
45
	   jna @f
46
	   mov op, 63
47
@@:
48
}
49
 
50
macro remove_from_list op
51
{	   mov edx, [op+list_fd]
52
	   mov ecx, [op+list_bk]
53
	   test edx, edx
54
	   jz @f
55
	   mov [edx+list_bk], ecx
56
@@:
57
	   test ecx, ecx
58
	   jz @f
59
	   mov [ecx+list_fd], edx
60
@@:
61
	   mov [op+list_fd],0
62
	   mov [op+list_bk],0
63
}
64
 
65
macro remove_from_free op
66
{
67
	   remove_from_list op
68
 
69
	   mov eax, [op+block_size]
70
	   calc_index eax
71
	   cmp [mem_block_list+eax*4], op
72
	   jne @f
73
	   mov [mem_block_list+eax*4], edx
74
@@:
75
	   cmp [mem_block_list+eax*4], 0
76
	   jne @f
77
	   btr [mem_block_mask], eax
78
@@:
79
}
80
 
81
macro remove_from_used op
82
{
83
	   mov edx, [op+list_fd]
84
	   mov ecx, [op+list_bk]
85
	   mov [edx+list_bk], ecx
86
	   mov [ecx+list_fd], edx
87
	   mov [op+list_fd], 0
88
	   mov [op+list_bk], 0
89
}
90
 
91
align 4
92
proc init_kernel_heap
93
 
94
	   mov ecx, 64/4
95
	   mov edi, mem_block_list
96
	   xor eax, eax
97
	   cld
98
	   rep stosd
99
 
100
	   mov ecx, 512/4
101
	   mov edi, mem_block_map
102
	   not eax
103
	   rep stosd
104
 
105
	   mov [mem_block_start], mem_block_map
106
	   mov [mem_block_end], mem_block_map+512
107
	   mov [mem_block_arr], HEAP_BASE
108
 
109
	   mov eax, mem_used.fd-MEM_LIST_OFFSET
110
	   mov [mem_used.fd], eax
111
	   mov [mem_used.bk], eax
112
 
113
	   stdcall alloc_pages, dword 32
114
	   mov ecx, 32
115
	   mov edx, eax
116
	   mov edi, HEAP_BASE
117
.l1:
118
	   stdcall map_page,edi,edx,PG_SW
119
	   add edi, 0x1000
120
	   add edx, 0x1000
121
	   dec ecx
122
	   jnz .l1
123
 
124
	   mov edi, HEAP_BASE
125
	   mov ebx, HEAP_BASE+MEM_BLOCK_SIZE
126
	   xor eax, eax
127
	   mov [edi+block_next], ebx
128
	   mov [edi+block_prev], eax
129
	   mov [edi+list_fd], eax
130
	   mov [edi+list_bk], eax
131
	   mov [edi+block_base], HEAP_BASE
132
	   mov [edi+block_size], 4096*MEM_BLOCK_SIZE
133
	   mov [edi+block_flags], USED_BLOCK
134
 
135
	   mov [ebx+block_next], eax
136
	   mov [ebx+block_prev], eax
137
	   mov [ebx+list_fd], eax
138
	   mov [ebx+list_bk], eax
139
	   mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
140
 
141
	   mov ecx, [MEM_AMOUNT]
142
	   sub ecx, (HEAP_BASE - OS_BASE + 4096*MEM_BLOCK_SIZE)
143
	   mov [heap_size], ecx
144
	   mov [heap_free], ecx
145
	   mov [ebx+block_size], ecx
146
	   mov [ebx+block_flags], FREE_BLOCK
147
 
148
	   mov [mem_block_mask], eax
149
	   mov [mem_block_mask+4],0x80000000
150
 
151
	   mov [mem_block_list+63*4], ebx
152
	   mov byte [mem_block_map], 0xFC
153
	   and [heap_mutex], 0
154
	   mov [heap_blocks], 4095
155
	   mov [free_blocks], 4095
156
	   ret
157
endp
158
 
159
; param
160
;  eax= required size
161
;
162
; retval
163
;  edi= memory block descriptor
164
;  ebx= descriptor index
165
 
166
align 4
167
get_small_block:
168
	   mov ecx, eax
169
	   shr ecx, 12
170
	   dec ecx
171
	   cmp ecx, 63
172
	   jle .get_index
173
	   mov ecx, 63
174
.get_index:
175
	   lea esi, [mem_block_mask]
176
	   xor ebx, ebx
177
	   or edx, -1
178
 
179
	   cmp ecx, 32
180
	   jb .bit_test
181
 
182
	   sub ecx, 32
183
	   add ebx, 32
184
	   add esi, 4
185
.bit_test:
186
	   shl edx, cl
187
	   and edx, [esi]
188
.find:
189
	   bsf edi, edx
190
	   jz .high_mask
191
	   add ebx, edi
192
	   mov edi, [mem_block_list+ebx*4]
193
.check_size:
194
	   cmp eax, [edi+block_size]
195
	   ja .next
196
	   ret
197
 
198
.high_mask:
199
	   add esi, 4
200
	   cmp esi, mem_block_mask+8
201
	   jae .err
202
	   add ebx, 32
203
	   mov edx, [esi]
204
	   jmp .find
205
.next:
206
	   mov edi, [edi+list_fd]
207
	   test edi, edi
208
	   jnz .check_size
209
.err:
210
	   xor edi, edi
211
	   ret
212
 
213
align 4
214
alloc_mem_block:
215
 
216
	   mov ebx, [mem_block_start]
217
	   mov ecx, [mem_block_end]
218
.l1:
219
	   bsf eax,[ebx];
220
	   jnz found
221
	   add ebx,4
222
	   cmp ebx, ecx
223
	   jb .l1
224
	   xor eax,eax
225
	   ret
226
 
227
found:
228
	   btr [ebx], eax
229
	   mov [mem_block_start],ebx
230
	   sub ebx, mem_block_map
231
	   lea eax,[eax+ebx*8]
232
	   shl eax, 5
233
	   add eax, [mem_block_arr]
234
	   dec [free_blocks]
235
	   ret
236
align 4
237
free_mem_block:
238
	   mov dword [eax], 0
239
	   mov dword [eax+4], 0
240
	   mov dword [eax+8], 0
241
	   mov dword [eax+12], 0
242
	   mov dword [eax+16], 0
243
;           mov dword [eax+20], 0
244
	   mov dword [eax+24], 0
245
	   mov dword [eax+28], 0
246
 
247
	   sub eax, [mem_block_arr]
248
	   shr eax, 5
249
 
250
	   mov ebx, mem_block_map
251
	   bts [ebx], eax
252
	   inc [free_blocks]
253
	   shr eax, 3
254
	   and eax, not 3
255
	   add eax, ebx
256
	   cmp [mem_block_start], eax
257
	   ja @f
258
	   ret
259
@@:
260
	   mov [mem_block_start], eax
261
	   ret
262
.err:
263
	   xor eax, eax
264
	   ret
265
 
266
align 4
267
proc alloc_kernel_space stdcall, size:dword
268
	   local block_ind:DWORD
269
 
270
	   push ebx
271
	   push esi
272
	   push edi
273
 
274
	   mov eax, [size]
275
	   add eax, 4095
276
	   and eax, not 4095
277
	   mov [size], eax
278
 
279
	   mov ebx, heap_mutex
280
	   call wait_mutex    ;ebx
281
 
282
	   cmp eax, [heap_free]
283
	   ja .error
284
 
285
	   call get_small_block ; eax
286
	   test edi, edi
287
	   jz .error
288
 
289
	   cmp [edi+block_flags], FREE_BLOCK
290
	   jne .error
291
 
292
	   mov [block_ind], ebx   ;index of allocated block
293
 
294
	   mov eax, [edi+block_size]
295
	   cmp eax, [size]
296
	   je .m_eq_size
297
 
298
	   call alloc_mem_block
299
	   and eax, eax
300
	   jz .error
301
 
302
	   mov esi, eax 	  ;esi - splitted block
303
 
304
	   mov [esi+block_next], edi
305
	   mov eax, [edi+block_prev]
306
	   mov [esi+block_prev], eax
307
	   mov [edi+block_prev], esi
308
	   mov [esi+list_fd], 0
309
	   mov [esi+list_bk], 0
310
	   and eax, eax
311
	   jz @f
312
	   mov [eax+block_next], esi
313
@@:
314
	   mov ebx, [edi+block_base]
315
	   mov [esi+block_base], ebx
316
	   mov edx, [size]
317
	   mov [esi+block_size], edx
318
	   add [edi+block_base], edx
319
	   sub [edi+block_size], edx
320
 
321
	   mov eax, [edi+block_size]
322
	   shr eax, 12
323
	   sub eax, 1
324
	   cmp eax, 63
325
	   jna @f
326
	   mov eax, 63
327
@@:
328
	   cmp eax, [block_ind]
329
	   je .m_eq_ind
330
 
331
	   remove_from_list edi
332
 
333
	   mov ecx, [block_ind]
334
	   mov [mem_block_list+ecx*4], edx
335
 
336
	   test edx, edx
337
	   jnz @f
338
	   btr [mem_block_mask], ecx
339
@@:
340
	   mov edx, [mem_block_list+eax*4]
341
	   mov [edi+list_fd], edx
342
	   test edx, edx
343
	   jz @f
344
	   mov [edx+list_bk], edi
345
@@:
346
	   mov [mem_block_list+eax*4], edi
347
	   bts [mem_block_mask], eax
348
.m_eq_ind:
349
	   mov ecx, mem_used.fd-MEM_LIST_OFFSET
350
	   mov edx, [ecx+list_fd]
351
	   mov [esi+list_fd], edx
352
	   mov [esi+list_bk], ecx
353
	   mov [ecx+list_fd], esi
354
	   mov [edx+list_bk], esi
355
 
356
	   mov [esi+block_flags], USED_BLOCK
357
	   mov eax, [esi+block_base]
358
	   mov ebx, [size]
359
	   sub [heap_free], ebx
360
	   and [heap_mutex], 0
361
	   pop edi
362
	   pop esi
363
	   pop ebx
364
	   ret
365
.m_eq_size:
366
	   remove_from_list edi
367
	   mov [mem_block_list+ebx*4], edx
368
	   and edx, edx
369
	   jnz @f
370
	   btr [mem_block_mask], ebx
371
@@:
372
	   mov ecx, mem_used.fd-MEM_LIST_OFFSET
373
	   mov edx, [ecx+list_fd]
374
	   mov [edi+list_fd], edx
375
	   mov [edi+list_bk], ecx
376
	   mov [ecx+list_fd], edi
377
	   mov [edx+list_bk], edi
378
 
379
	   mov [edi+block_flags], USED_BLOCK
380
	   mov eax, [edi+block_base]
381
	   mov ebx, [size]
382
	   sub [heap_free], ebx
383
	   and [heap_mutex], 0
384
	   pop edi
385
	   pop esi
386
	   pop ebx
387
	   ret
388
.error:
389
	   xor eax, eax
390
	   mov [heap_mutex], eax
391
	   pop edi
392
	   pop esi
393
	   pop ebx
394
	   ret
395
endp
396
 
397
align 4
398
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
399
	   push ebx
400
	   push esi
401
	   push edi
402
	   mov ebx, heap_mutex
403
	   call wait_mutex    ;ebx
404
 
405
	   mov eax, [base]
406
	   mov esi, [mem_used.fd]
407
@@:
408
	   cmp esi, mem_used.fd-MEM_LIST_OFFSET
409
	   je .fail
410
 
411
	   cmp [esi+block_base], eax
412
	   je .found
413
	   mov esi, [esi+list_fd]
414
	   jmp @b
415
.found:
416
	   cmp [esi+block_flags], USED_BLOCK
417
	   jne .fail
418
 
419
	   mov eax, [esi+block_size]
420
	   add [heap_free], eax
421
 
422
	   mov edi, [esi+block_next]
423
	   test edi, edi
424
	   jz .prev
425
 
426
	   cmp [edi+block_flags], FREE_BLOCK
427
	   jne .prev
428
 
429
	   remove_from_free edi
430
 
431
	   mov edx, [edi+block_next]
432
	   mov [esi+block_next], edx
433
	   test edx, edx
434
	   jz @f
435
 
436
	   mov [edx+block_prev], esi
437
@@:
438
	   mov ecx, [edi+block_size]
439
	   add [esi+block_size], ecx
440
 
441
	   mov eax, edi
442
	   call free_mem_block
443
.prev:
444
	   mov edi, [esi+block_prev]
445
	   test edi, edi
446
	   jz .insert
447
 
448
	   cmp [edi+block_flags], FREE_BLOCK
449
	   jne .insert
450
 
451
	   remove_from_used esi
452
 
453
	   mov edx, [esi+block_next]
454
	   mov [edi+block_next], edx
455
	   test edx, edx
456
	   jz @f
457
	   mov [edx+block_prev], edi
458
@@:
459
	   mov eax, esi
460
	   call free_mem_block
461
 
462
	   mov ecx, [edi+block_size]
463
	   mov eax, [esi+block_size]
464
	   add eax, ecx
465
	   mov [edi+block_size], eax
466
 
467
	   calc_index eax
468
	   calc_index ecx
469
	   cmp eax, ecx
470
	   je .m_eq
471
 
472
	   push ecx
473
	   remove_from_list edi
474
	   pop ecx
475
 
476
	   cmp [mem_block_list+ecx*4], edi
477
	   jne @f
478
	   mov [mem_block_list+ecx*4], edx
479
@@:
480
	   cmp [mem_block_list+ecx*4], 0
481
	   jne @f
482
	   btr [mem_block_mask], ecx
483
@@:
484
	   mov esi, [mem_block_list+eax*4]
485
	   mov [mem_block_list+eax*4], edi
486
	   mov [edi+list_fd], esi
487
	   test esi, esi
488
	   jz @f
489
	   mov [esi+list_bk], edi
490
@@:
491
	   bts [mem_block_mask], eax
492
.m_eq:
493
	   xor eax, eax
494
	   mov [heap_mutex], eax
495
	   dec eax
496
	   pop edi
497
	   pop esi
498
	   pop ebx
499
	   ret
500
.insert:
501
	   remove_from_used esi
502
 
503
	   mov eax, [esi+block_size]
504
	   calc_index eax
505
 
506
	   mov edi, [mem_block_list+eax*4]
507
	   mov [mem_block_list+eax*4], esi
508
	   mov [esi+list_fd], edi
509
	   test edi, edi
510
	   jz @f
511
	   mov [edi+list_bk], esi
512
@@:
513
	   bts [mem_block_mask], eax
514
	   mov [esi+block_flags],FREE_BLOCK
515
	   xor eax, eax
516
	   mov [heap_mutex], eax
517
	   dec eax
518
	   pop edi
519
	   pop esi
520
	   pop ebx
521
	   ret
522
.fail:
523
	   xor eax, eax
524
	   mov [heap_mutex], eax
525
	   pop edi
526
	   pop esi
527
	   pop ebx
528
	   ret
529
endp
530
 
531
align 4
532
proc kernel_alloc stdcall, size:dword
533
	   locals
534
	     lin_addr	 dd ?
535
	     pages_count dd ?
536
	   endl
537
 
538
	   push ebx
539
	   push edi
540
	   push edx
541
 
542
	   mov eax, [size]
543
	   add eax, 4095
544
	   and eax, not 4095;
545
	   mov [size], eax
546
	   and eax, eax
547
	   jz .err
548
	   mov ebx, eax
549
	   shr ebx, 12
550
	   mov [pages_count], ebx
551
 
552
	   stdcall alloc_kernel_space, eax
553
	   test eax, eax
554
	   jz .err
555
	   mov [lin_addr], eax
556
 
557
	   mov ecx, [pages_count]
558
	   mov edx, eax
559
	   mov ebx, ecx
560
 
561
	   shr ecx, 3
562
	   jz .next
563
 
564
	   and ebx, not 7
565
	   push ebx
566
	   stdcall alloc_pages, ebx
567
	   pop ecx		     ; yes ecx!!!
568
	   and eax, eax
569
	   jz .err
570
 
571
	   mov edi, eax
572
	   mov edx, [lin_addr]
573
@@:
574
	   stdcall map_page,edx,edi,dword PG_SW
575
	   add edx, 0x1000
576
	   add edi, 0x1000
577
	   dec ecx
578
	   jnz @B
579
.next:
580
	   mov ecx, [pages_count]
581
	   and ecx, 7
582
	   jz .end
583
@@:
584
	   push ecx
585
	   call alloc_page
586
	   pop ecx
587
	   test eax, eax
588
	   jz .err
589
 
590
	   stdcall map_page,edx,eax,dword PG_SW
591
	   add edx, 0x1000
592
	   dec ecx
593
	   jnz @B
594
.end:
595
	   mov eax, [lin_addr]
596
	   pop edx
597
	   pop edi
598
	   pop ebx
599
	   ret
600
.err:
601
	   xor eax, eax
602
	   pop edx
603
	   pop edi
604
	   pop ebx
605
	   ret
606
endp
607
 
608
align 4
609
proc kernel_free stdcall, base:dword
610
	   push ebx esi
611
 
612
	   mov ebx, heap_mutex
613
	   call wait_mutex    ;ebx
614
 
615
	   mov eax, [base]
616
	   mov esi, [mem_used.fd]
617
@@:
618
	   cmp esi, mem_used.fd-MEM_LIST_OFFSET
619
	   je .fail
620
 
621
	   cmp [esi+block_base], eax
622
	   je .found
623
	   mov esi, [esi+list_fd]
624
	   jmp @b
625
.found:
626
	   cmp [esi+block_flags], USED_BLOCK
627
	   jne .fail
628
 
629
	   and [heap_mutex], 0
630
 
631
	   push ecx
632
	   mov ecx, [esi+block_size];
633
	   shr ecx, 12
634
	   call release_pages	;eax, ecx
635
	   pop ecx
636
	   stdcall free_kernel_space, [base]
637
	   pop esi ebx
638
	   ret
639
.fail:
640
	   and [heap_mutex], 0
641
	   pop esi ebx
642
	   ret
643
endp
644
 
645
restore block_next
646
restore block_prev
647
restore block_list
648
restore block_base
649
restore block_size
650
restore block_flags
651
 
652
;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
653
 
654
HEAP_TOP  equ 0x5FC00000
655
 
656
align 4
657
proc init_heap
658
 
659
	   mov ebx,[current_slot]
660
	   mov eax, [ebx+APPDATA.heap_top]
661
	   test eax, eax
662
	   jz @F
663
	   sub eax,[ebx+APPDATA.heap_base]
664
	   sub eax, 4096
665
	   ret
666
@@:
667
	   mov esi, [ebx+APPDATA.mem_size]
668
	   add esi, 4095
669
	   and esi, not 4095
670
	   mov [ebx+APPDATA.mem_size], esi
671
	   mov eax, HEAP_TOP
672
	   mov [ebx+APPDATA.heap_base], esi
673
	   mov [ebx+APPDATA.heap_top], eax
674
 
675
	   sub eax, esi
676
	   shr esi, 10
677
	   mov ecx, eax
678
	   sub eax, 4096
679
	   or ecx, FREE_BLOCK
680
	   mov [page_tabs+esi], ecx
681
	   ret
682
endp
683
 
684
align 4
685
proc user_alloc stdcall, alloc_size:dword
686
 
687
	   push ebx
688
	   push esi
689
	   push edi
690
 
691
	   mov ecx, [alloc_size]
692
	   add ecx, (4095+4096)
693
	   and ecx, not 4095
694
 
695
	   mov ebx, [current_slot]
696
	   mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
697
	   mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
698
l_0:
699
	   cmp esi, edi
700
	   jae m_exit
701
 
702
	   mov ebx, esi
703
	   shr ebx, 12
704
	   mov eax, [page_tabs+ebx*4]
705
	   test al, FREE_BLOCK
706
	   jz test_used
707
	   and eax, 0xFFFFF000
708
	   cmp eax, ecx    ;alloc_size
709
	   jb  m_next
710
	   jz  @f
711
 
712
	   lea edx, [esi+ecx]
713
	   sub eax, ecx
714
	   or al, FREE_BLOCK
715
	   shr edx, 12
716
	   mov [page_tabs+edx*4], eax
717
@@:
718
	   or ecx, USED_BLOCK
719
	   mov [page_tabs+ebx*4], ecx
720
	   shr ecx, 12
721
	   inc ebx
722
	   dec ecx
723
	   jz  .no
724
@@:
725
	   mov dword [page_tabs+ebx*4], 2
726
	   inc ebx
727
	   dec ecx
728
	   jnz @B
729
.no:
730
 
731
	   mov	   edx, [current_slot]
732
	   mov	   ebx, [alloc_size]
733
	   add	   ebx, 0xFFF
734
	   and	   ebx, not 0xFFF
735
	   add	   ebx, [edx+APPDATA.mem_size]
736
	   call    update_mem_size
737
 
738
	   lea eax, [esi+4096]
739
 
740
	   pop edi
741
	   pop esi
742
	   pop ebx
743
	   ret
744
test_used:
745
	   test al, USED_BLOCK
746
	   jz m_exit
747
 
748
	   and eax, 0xFFFFF000
749
m_next:
750
	   add esi, eax
751
	   jmp l_0
752
m_exit:
753
	   xor eax, eax
754
	   pop edi
755
	   pop esi
756
	   pop ebx
757
	   ret
758
endp
759
 
760
align 4
761
proc user_free stdcall, base:dword
762
 
763
	   push esi
764
 
765
	   mov esi, [base]
766
	   test esi, esi
767
	   jz .exit
768
 
769
	   push ebx
770
 
771
	   xor ebx, ebx
772
	   shr esi, 12
773
	   mov eax, [page_tabs+(esi-1)*4]
774
	   test al, USED_BLOCK
775
	   jz .cantfree
776
	   test al, DONT_FREE_BLOCK
777
	   jnz .cantfree
778
 
779
	   and eax, not 4095
780
	   mov ecx, eax
781
	   or al, FREE_BLOCK
782
	   mov [page_tabs+(esi-1)*4], eax
783
	   sub ecx, 4096
784
	   mov ebx, ecx
785
	   shr ecx, 12
786
	   jz .released
787
.release:
788
	   xor eax, eax
789
	   xchg eax, [page_tabs+esi*4]
790
	   test al, 1
791
	   jz @F
792
	   test eax, PG_SHARED
793
	   jnz @F
794
	   call free_page
795
	   mov eax, esi
796
	   shl eax, 12
797
	   invlpg [eax]
798
@@:
799
	   inc esi
800
	   dec ecx
801
	   jnz .release
802
.released:
803
	   push edi
804
 
805
	   mov edx, [current_slot]
806
	   mov esi, dword [edx+APPDATA.heap_base]
807
	   mov edi, dword [edx+APPDATA.heap_top]
808
	   sub ebx, [edx+APPDATA.mem_size]
809
	   neg ebx
810
	   call update_mem_size
811
	   call user_normalize
812
	   pop edi
813
	   pop ebx
814
	   pop esi
815
	   ret
816
.exit:
817
	   xor eax, eax
818
	   inc eax
819
	   pop esi
820
	   ret
821
.cantfree:
822
	   xor eax, eax
823
	   pop ebx
824
	   pop esi
825
	   ret
826
endp
827
 
828
user_normalize:
829
; in: esi=heap_base, edi=heap_top
830
; out: eax=0 <=> OK
831
; destroys: ebx,edx,esi,edi
832
	   shr esi, 12
833
	   shr edi, 12
834
@@:
835
	   mov eax, [page_tabs+esi*4]
836
	   test al, USED_BLOCK
837
	   jz .test_free
838
	   shr eax, 12
839
	   add esi, eax
840
	   jmp @B
841
.test_free:
842
	   test al, FREE_BLOCK
843
	   jz .err
844
	   mov edx, eax
845
	   shr edx, 12
846
	   add edx, esi
847
	   cmp edx, edi
848
	   jae .exit
849
 
850
	   mov ebx, [page_tabs+edx*4]
851
	   test bl, USED_BLOCK
852
	   jz .next_free
853
 
854
	   shr ebx, 12
855
	   add edx, ebx
856
	   mov esi, edx
857
	   jmp @B
858
.next_free:
859
	   test bl, FREE_BLOCK
860
	   jz .err
861
	   and dword [page_tabs+edx*4], 0
862
	   add eax, ebx
863
	   and eax, not 4095
864
	   or eax, FREE_BLOCK
865
	   mov [page_tabs+esi*4], eax
866
	   jmp @B
867
.exit:
868
	   xor eax, eax
869
	   inc eax
870
	   ret
871
.err:
872
	   xor eax, eax
873
	   ret
874
 
875
user_realloc:
876
; in: eax = pointer, ebx = new size
877
; out: eax = new pointer or NULL
878
	test	eax, eax
879
	jnz	@f
880
; realloc(NULL,sz) - same as malloc(sz)
881
	push	ebx
882
	call	user_alloc
883
	ret
884
@@:
885
	push	ecx edx
886
	lea	ecx, [eax - 0x1000]
887
	shr	ecx, 12
888
	mov	edx, [page_tabs+ecx*4]
889
	test	dl, USED_BLOCK
890
	jnz	@f
891
; attempt to realloc invalid pointer
892
.ret0:
893
	pop	edx ecx
894
	xor	eax, eax
895
	ret
896
@@:
897
	test	dl, DONT_FREE_BLOCK
898
	jnz	.ret0
899
	add	ebx, 0x1FFF
900
	shr	edx, 12
901
	shr	ebx, 12
902
; edx = allocated size, ebx = new size
903
	add	edx, ecx
904
	add	ebx, ecx
905
	cmp	edx, ebx
906
	jb	.realloc_add
907
; release part of allocated memory
908
.loop:
909
	cmp	edx, ebx
910
	jz	.release_done
911
	dec	edx
912
	xor	eax, eax
913
	xchg	eax, [page_tabs+edx*4]
914
	test	al, 1
915
	jz	.loop
916
	call	free_page
917
	mov	eax, edx
918
	shl	eax, 12
919
	invlpg	[eax]
920
	jmp	.loop
921
.release_done:
922
	sub	ebx, ecx
923
	cmp	ebx, 1
924
	jnz	.nofreeall
925
	mov	eax, [page_tabs+ecx*4]
926
	and	eax, not 0xFFF
927
	mov	edx, [current_slot]
928
	mov	ebx, [APPDATA.mem_size+edx]
929
	sub	ebx, eax
930
	add	ebx, 0x1000
931
	or	al, FREE_BLOCK
932
	mov	[page_tabs+ecx*4], eax
933
	push	esi edi
934
	mov	esi, [APPDATA.heap_base+edx]
935
	mov	edi, [APPDATA.heap_top+edx]
936
	call	update_mem_size
937
	call	user_normalize
938
	pop	edi esi
939
	jmp	.ret0	; all freed
940
.nofreeall:
941
	sub	edx, ecx
942
	shl	ebx, 12
943
	or	ebx, USED_BLOCK
944
	xchg	[page_tabs+ecx*4], ebx
945
	shr	ebx, 12
946
	sub	ebx, edx
947
	push	ebx ecx edx
948
	mov	edx, [current_slot]
949
	shl	ebx, 12
950
	sub	ebx, [APPDATA.mem_size+edx]
951
	neg	ebx
952
	call	update_mem_size
953
	pop	edx ecx ebx
954
	lea	eax, [ecx+1]
955
	shl	eax, 12
956
	push	eax
957
	add	ecx, edx
958
	lea	edx, [ecx+ebx]
959
	shl	ebx, 12
960
	jz	.ret
961
	push	esi
962
	mov	esi, [current_slot]
963
	mov	esi, [APPDATA.heap_top+esi]
964
	shr	esi, 12
965
@@:
966
	cmp	edx, esi
967
	jae	.merge_done
968
	mov	eax, [page_tabs+edx*4]
969
	test	al, USED_BLOCK
970
	jnz	.merge_done
971
	and	dword [page_tabs+edx*4], 0
972
	shr	eax, 12
973
	add	edx, eax
974
	shl	eax, 12
975
	add	ebx, eax
976
	jmp	@b
977
.merge_done:
978
	pop	esi
979
	or	ebx, FREE_BLOCK
980
	mov	[page_tabs+ecx*4], ebx
981
.ret:
982
	pop	eax edx ecx
983
	ret
984
.realloc_add:
985
; get some additional memory
986
	mov	eax, [current_slot]
987
	mov	eax, [APPDATA.heap_top+eax]
988
	shr	eax, 12
989
	cmp	edx, eax
990
	jae	.cant_inplace
991
	mov	eax, [page_tabs+edx*4]
992
	test	al, FREE_BLOCK
993
	jz	.cant_inplace
994
	shr	eax, 12
995
	add	eax, edx
996
	sub	eax, ebx
997
	jb	.cant_inplace
998
	jz	@f
999
	shl	eax, 12
1000
	or	al, FREE_BLOCK
1001
	mov	[page_tabs+ebx*4], eax
1002
@@:
1003
	mov	eax, ebx
1004
	sub	eax, ecx
1005
	shl	eax, 12
1006
	or	al, USED_BLOCK
1007
	mov	[page_tabs+ecx*4], eax
1008
	lea	eax, [ecx+1]
1009
	shl	eax, 12
1010
	push	eax
1011
	push	edi
1012
	lea	edi, [page_tabs+edx*4]
1013
	mov	eax, 2
1014
	sub	ebx, edx
1015
	mov	ecx, ebx
1016
	cld
1017
	rep	stosd
1018
	pop	edi
1019
	mov	edx, [current_slot]
1020
	shl	ebx, 12
1021
	add	ebx, [APPDATA.mem_size+edx]
1022
	call	update_mem_size
1023
	pop	eax edx ecx
1024
	ret
1025
.cant_inplace:
1026
	push	esi edi
1027
	mov	eax, [current_slot]
1028
	mov	esi, [APPDATA.heap_base+eax]
1029
	mov	edi, [APPDATA.heap_top+eax]
1030
	shr	esi, 12
1031
	shr	edi, 12
1032
	sub	ebx, ecx
1033
.find_place:
1034
	cmp	esi, edi
1035
	jae	.place_not_found
1036
	mov	eax, [page_tabs+esi*4]
1037
	test	al, FREE_BLOCK
1038
	jz	.next_place
1039
	shr	eax, 12
1040
	cmp	eax, ebx
1041
	jae	.place_found
1042
	add	esi, eax
1043
	jmp	.find_place
1044
.next_place:
1045
	shr	eax, 12
1046
	add	esi, eax
1047
	jmp	.find_place
1048
.place_not_found:
1049
	pop	edi esi
1050
	jmp	.ret0
1051
.place_found:
1052
	sub	eax, ebx
1053
	jz	@f
1054
	push	esi
1055
	add	esi, ebx
1056
	shl	eax, 12
1057
	or	al, FREE_BLOCK
1058
	mov	[page_tabs+esi*4], eax
1059
	pop	esi
1060
@@:
1061
	mov	eax, ebx
1062
	shl	eax, 12
1063
	or	al, USED_BLOCK
1064
	mov	[page_tabs+esi*4], eax
1065
	inc	esi
1066
	mov	eax, esi
1067
	shl	eax, 12
1068
	push	eax
1069
	mov	eax, [page_tabs+ecx*4]
1070
	and	eax, not 0xFFF
1071
	or	al, FREE_BLOCK
1072
	sub	edx, ecx
1073
	mov	[page_tabs+ecx*4], eax
1074
	inc	ecx
1075
	dec	ebx
1076
	dec	edx
1077
	jz	.no
1078
@@:
1079
	xor	eax, eax
1080
	xchg	eax, [page_tabs+ecx*4]
1081
	mov	[page_tabs+esi*4], eax
1082
	mov	eax, ecx
1083
	shl	eax, 12
1084
	invlpg	[eax]
1085
	inc	esi
1086
	inc	ecx
1087
	dec	ebx
1088
	dec	edx
1089
	jnz	@b
1090
.no:
1091
	push	ebx
1092
	mov	edx, [current_slot]
1093
	shl	ebx, 12
1094
	add	ebx, [APPDATA.mem_size+edx]
1095
	call	update_mem_size
1096
	pop	ebx
1097
@@:
1098
	mov	dword [page_tabs+esi*4], 2
1099
	inc	esi
1100
	dec	ebx
1101
	jnz	@b
1102
	pop	eax edi esi edx ecx
1103
	ret
1104
 
1105
if 0
1106
align 4
1107
proc alloc_dll
1108
	   pushf
1109
	   cli
1110
	   bsf eax, [dll_map]
1111
	   jnz .find
1112
	   popf
1113
	   xor eax, eax
1114
	   ret
1115
.find:
1116
	   btr [dll_map], eax
1117
	   popf
1118
	   shl eax, 5
1119
	   add eax, dll_tab
1120
	   ret
1121
endp
1122
 
1123
align 4
1124
proc alloc_service
1125
	   pushf
1126
	   cli
1127
	   bsf eax, [srv_map]
1128
	   jnz .find
1129
	   popf
1130
	   xor eax, eax
1131
	   ret
1132
.find:
1133
	   btr [srv_map], eax
1134
	   popf
1135
	   shl eax,0x02
1136
	   lea eax,[srv_tab+eax+eax*8]	 ;srv_tab+eax*36
1137
	   ret
1138
endp
1139
 
1140
end if
1141
 
1142
 
1143
;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
1144
 
1145
 
1146
; param
1147
;  eax= shm_map object
1148
 
1149
align 4
1150
destroy_smap:
1151
 
1152
	   pushfd
1153
	   cli
1154
 
1155
	   push esi
1156
	   push edi
1157
 
1158
	   mov edi, eax
1159
	   mov esi, [eax+SMAP.parent]
1160
	   test esi, esi
1161
	   jz .done
1162
 
1163
	   lock dec [esi+SMEM.refcount]
1164
	   jnz .done
1165
 
1166
	   mov ecx, [esi+SMEM.bk]
1167
	   mov edx, [esi+SMEM.fd]
1168
 
1169
	   mov [ecx+SMEM.fd], edx
1170
	   mov [edx+SMEM.bk], ecx
1171
 
1172
	   stdcall kernel_free, [esi+SMEM.base]
1173
	   mov eax, esi
1174
	   call free
1175
.done:
1176
	   mov eax, edi
1177
	   call destroy_kernel_object
1178
 
1179
	   pop edi
1180
	   pop esi
1181
	   popfd
1182
 
1183
	   ret
1184
 
1185
E_NOTFOUND	equ  5
1186
E_ACCESS	equ 10
1187
E_NOMEM 	equ 30
1188
E_PARAM 	equ 33
1189
 
1190
SHM_READ	equ 0
1191
SHM_WRITE	equ 1
1192
 
1193
SHM_ACCESS_MASK equ 3
1194
 
1195
SHM_OPEN	equ (0 shl 2)
1196
SHM_OPEN_ALWAYS equ (1 shl 2)
1197
SHM_CREATE	equ (2 shl 2)
1198
 
1199
SHM_OPEN_MASK	equ (3 shl 2)
1200
 
1201
align 4
1202
proc shmem_open stdcall name:dword, size:dword, access:dword
1203
	   locals
1204
	      action	     dd ?
1205
	      owner_access   dd ?
1206
	      mapped	     dd ?
1207
	   endl
1208
 
1209
	   push ebx
1210
	   push esi
1211
	   push edi
1212
 
1213
	   mov [mapped], 0
1214
	   mov [owner_access], 0
1215
 
1216
	   pushfd		       ;mutex required
1217
	   cli
1218
 
1219
	   mov eax, [access]
1220
	   and eax, SHM_OPEN_MASK
1221
	   mov [action], eax
1222
 
1223
	   mov eax, [name]
1224
	   test eax, eax
1225
	   mov edx, E_PARAM
1226
	   jz .exit
1227
 
1228
	   mov esi, [shmem_list.fd]
1229
align 4
1230
@@:
1231
	   cmp esi, shmem_list
1232
	   je .not_found
1233
 
1234
	   lea edx, [esi+SMEM.name] ; link , base, size
1235
	   stdcall strncmp, edx, eax, 32
1236
	   test eax, eax
1237
	   je .found
1238
 
1239
	   mov esi, [esi+SMEM.fd]
1240
	   jmp @B
1241
 
1242
.not_found:
1243
	   mov eax, [action]
1244
 
1245
	   cmp eax, SHM_OPEN
1246
	   mov edx, E_NOTFOUND
1247
	   je .exit
1248
 
1249
	   cmp eax, SHM_CREATE
1250
	   mov edx, E_PARAM
1251
	   je .create_shm
1252
 
1253
	   cmp eax, SHM_OPEN_ALWAYS
1254
	   jne .exit
1255
 
1256
.create_shm:
1257
 
1258
	   mov ecx, [size]
1259
	   test ecx, ecx
1260
	   jz .exit
1261
 
1262
	   add ecx, 4095
1263
	   and ecx, -4096
1264
	   mov [size], ecx
1265
 
1266
	   mov eax, SMEM.sizeof
1267
	   call malloc
1268
	   test eax, eax
1269
	   mov esi, eax
1270
	   mov edx, E_NOMEM
1271
	   jz .exit
1272
 
1273
	   stdcall kernel_alloc, [size]
1274
	   test eax, eax
1275
	   mov [mapped], eax
1276
	   mov edx, E_NOMEM
1277
	   jz .cleanup
1278
 
1279
	   mov ecx, [size]
1280
	   mov edx, [access]
1281
	   and edx, SHM_ACCESS_MASK
1282
 
1283
	   mov [esi+SMEM.base], eax
1284
	   mov [esi+SMEM.size], ecx
1285
	   mov [esi+SMEM.access], edx
1286
	   mov [esi+SMEM.refcount], 0
1287
	   mov [esi+SMEM.name+28], 0
1288
 
1289
	   lea eax, [esi+SMEM.name]
1290
	   stdcall strncpy, eax, [name], 31
1291
 
1292
	   mov eax, [shmem_list.fd]
1293
	   mov [esi+SMEM.bk], shmem_list
1294
	   mov [esi+SMEM.fd], eax
1295
 
1296
	   mov [eax+SMEM.bk], esi
1297
	   mov [shmem_list.fd], esi
1298
 
1299
	   mov [action], SHM_OPEN
1300
	   mov [owner_access], SHM_WRITE
1301
 
1302
.found:
1303
	   mov eax, [action]
1304
 
1305
	   cmp eax, SHM_CREATE
1306
	   mov edx, E_ACCESS
1307
	   je .exit
1308
 
1309
	   cmp eax, SHM_OPEN
1310
	   mov edx, E_PARAM
1311
	   je .create_map
1312
 
1313
	   cmp eax, SHM_OPEN_ALWAYS
1314
	   jne .exit
1315
 
1316
.create_map:
1317
 
1318
	   mov eax, [access]
1319
	   and eax, SHM_ACCESS_MASK
1320
	   cmp eax, [esi+SMEM.access]
1321
	   mov [access], eax
1322
	   mov edx, E_ACCESS
1323
	   ja .exit
1324
 
1325
	   mov ebx, [CURRENT_TASK]
1326
	   shl ebx, 5
1327
	   mov ebx, [CURRENT_TASK+ebx+4]
1328
	   mov eax, SMAP.sizeof
1329
 
1330
	   call create_kernel_object
1331
	   test eax, eax
1332
	   mov edi, eax
1333
	   mov edx, E_NOMEM
1334
	   jz .exit
1335
 
1336
	   mov [edi+SMAP.magic], 'SMAP'
1337
	   mov [edi+SMAP.destroy], destroy_smap
1338
	   mov [edi+SMAP.base], 0
1339
	   mov [edi+SMAP.parent], 0
1340
 
1341
	   stdcall user_alloc, [esi+SMEM.size]
1342
	   test eax, eax
1343
	   mov [mapped], eax
1344
	   mov edx, E_NOMEM
1345
	   jz .cleanup2
1346
 
1347
	   lock inc [esi+SMEM.refcount]
1348
	   mov [edi+SMAP.base], eax
1349
	   mov [edi+SMAP.parent], esi
1350
 
1351
	   mov ecx, [esi+SMEM.size]
1352
	   mov [size], ecx
1353
 
1354
	   shr ecx, 12
1355
	   shr eax, 10
1356
 
1357
	   mov esi, [esi+SMEM.base]
1358
	   shr esi, 10
1359
	   lea edi, [page_tabs+eax]
1360
	   add esi, page_tabs
1361
 
1362
	   mov edx, [access]
1363
	   or edx, [owner_access]
1364
	   shl edx, 1
1365
	   or edx, PG_USER+PG_SHARED
1366
@@:
1367
	   lodsd
1368
	   and eax, 0xFFFFF000
1369
	   or eax, edx
1370
	   stosd
1371
	   loop @B
1372
 
1373
	   xor edx, edx
1374
 
1375
	   cmp [owner_access], 0
1376
	   jne .exit
1377
 
1378
	   mov edx, [size]
1379
.exit:
1380
	   mov eax, [mapped]
1381
 
1382
	   popfd
1383
	   pop edi
1384
	   pop esi
1385
	   pop ebx
1386
	   ret
1387
 
1388
.cleanup:
1389
	   mov eax, esi
1390
	   call free
1391
	   jmp .exit
1392
 
1393
.cleanup2:
1394
	   mov eax, edi
1395
	   call destroy_smap
1396
	   jmp .exit
1397
endp
1398
 
1399
align 4
1400
proc shmem_close stdcall, name:dword
1401
 
1402
	   mov eax, [name]
1403
	   test eax, eax
1404
	   jz .fail
1405
 
1406
	   push esi
1407
	   push edi
1408
	   pushfd
1409
	   cli
1410
 
1411
	   mov esi, [current_slot]
1412
	   add esi, APP_OBJ_OFFSET
1413
.next:
1414
	   mov eax, [esi+APPOBJ.fd]
1415
	   test eax, eax
1416
	   jz @F
1417
 
1418
	   cmp eax, esi
1419
	   mov esi, eax
1420
	   je @F
1421
 
1422
	   cmp [eax+SMAP.magic], 'SMAP'
1423
	   jne .next
1424
 
1425
	   mov edi, [eax+SMAP.parent]
1426
	   test edi, edi
1427
	   jz .next
1428
 
1429
	   lea eax, [edi+SMEM.name]
1430
	   stdcall strncmp, [name], edi, 32
1431
	   test eax, eax
1432
	   jne .next
1433
 
1434
	   stdcall user_free, [esi+SMAP.base]
1435
 
1436
	   call [esi+APPOBJ.destroy]
1437
@@:
1438
	   popfd
1439
	   pop edi
1440
	   pop esi
1441
.fail:
1442
	   ret
1443
endp