Subversion Repositories Kolibri OS

Rev

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

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