Subversion Repositories Kolibri OS

Rev

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