Subversion Repositories Kolibri OS

Rev

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

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