Subversion Repositories Kolibri OS

Rev

Rev 3371 | Rev 4391 | 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: 3798 $
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]
3246 Serge 57
        list_add esi, ecx
2288 clevermous 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]
3246 Serge 98
        list_del esi
2288 clevermous 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
3371 clevermous 157
        mov     [ecx+list_fd], eax
158
        mov     [ecx+list_bk], eax
159
        mov     [ecx+block_base], eax
160
        mov     [ecx+block_size], eax
161
        mov     [ecx+block_flags], USED_BLOCK
2288 clevermous 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
3246 Serge 179
        list_add ebx, ecx
2288 clevermous 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
 
3246 Serge 396
        list_del edi
2288 clevermous 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
 
3246 Serge 404
        calc_index ecx
2288 clevermous 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
 
3246 Serge 430
        calc_index eax                     ;new index
431
        calc_index ecx                     ;old index
2288 clevermous 432
        cmp     eax, ecx
433
        je      .m_eq
434
 
435
        push    ecx
3246 Serge 436
        list_del edi
2288 clevermous 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
3246 Serge 443
 
2288 clevermous 444
.add_block:
445
        bts     [mem_block_mask], eax
446
        lea     edx, [mem_block_list+eax*8]
3246 Serge 447
        list_add edi, edx
2288 clevermous 448
.m_eq:
449
        mov     ecx, heap_mutex
450
        call    mutex_unlock
451
        xor     eax, eax
452
        not     eax
453
        ret
454
.insert:
455
        mov     [esi+block_flags], FREE_BLOCK
456
        mov     eax, [esi+block_size]
3246 Serge 457
        calc_index eax
2288 clevermous 458
        mov     edi, esi
459
        jmp     .add_block
460
 
461
.fail:
462
        mov     ecx, heap_mutex
463
        call    mutex_unlock
464
        xor     eax, eax
465
        ret
466
endp
467
 
468
align 4
469
proc kernel_alloc stdcall, size:dword
3246 Serge 470
        locals
471
          lin_addr    dd ?
472
          pages_count dd ?
473
        endl
2288 clevermous 474
 
475
        push    ebx
476
        push    edi
477
 
478
        mov     eax, [size]
479
        add     eax, 4095
480
        and     eax, not 4095;
481
        mov     [size], eax
482
        and     eax, eax
483
        jz      .err
484
        mov     ebx, eax
485
        shr     ebx, 12
486
        mov     [pages_count], ebx
487
 
488
        stdcall alloc_kernel_space, eax
489
        test    eax, eax
490
        jz      .err
491
        mov     [lin_addr], eax
492
 
493
        mov     ecx, [pages_count]
494
        mov     edx, eax
495
        mov     ebx, ecx
496
 
497
        shr     ecx, 3
498
        jz      .next
499
 
500
        and     ebx, not 7
501
        push    ebx
502
        stdcall alloc_pages, ebx
503
        pop     ecx                  ; yes ecx!!!
504
        and     eax, eax
505
        jz      .err
506
 
507
        mov     edi, eax
508
        mov     edx, [lin_addr]
509
@@:
510
        stdcall map_page, edx, edi, dword PG_SW
511
        add     edx, 0x1000
512
        add     edi, 0x1000
513
        dec     ecx
514
        jnz     @B
515
.next:
516
        mov     ecx, [pages_count]
517
        and     ecx, 7
518
        jz      .end
519
@@:
520
        push    ecx
521
        call    alloc_page
522
        pop     ecx
523
        test    eax, eax
524
        jz      .err
525
 
526
        stdcall map_page, edx, eax, dword PG_SW
527
        add     edx, 0x1000
528
        dec     ecx
529
        jnz     @B
530
.end:
531
        mov     eax, [lin_addr]
532
        pop     edi
533
        pop     ebx
534
        ret
535
.err:
536
        xor     eax, eax
537
        pop     edi
538
        pop     ebx
539
        ret
540
endp
541
 
542
align 4
543
proc kernel_free stdcall, base:dword
544
 
545
        push    ebx esi
546
 
547
        mov     ecx, heap_mutex
548
        call    mutex_lock
549
 
550
        mov     eax, [base]
551
        call    md.find_used
552
 
553
        mov     ecx, heap_mutex
554
        cmp     [esi+block_flags], USED_BLOCK
555
        jne     .fail
556
 
557
        call    mutex_unlock
558
 
559
        mov     eax, [esi+block_base]
560
        mov     ecx, [esi+block_size]
561
        shr     ecx, 12
562
        call    release_pages   ;eax, ecx
563
        stdcall free_kernel_space, [base]
564
        pop     esi ebx
565
        ret
566
.fail:
567
        call    mutex_unlock
568
        xor     eax, eax
569
        pop     esi ebx
570
        ret
571
endp
572
 
573
restore block_next
574
restore block_prev
575
restore block_list
576
restore block_base
577
restore block_size
578
restore block_flags
579
 
580
;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
581
 
2412 Serge 582
HEAP_TOP  equ 0x80000000
2288 clevermous 583
 
584
align 4
585
proc init_heap
586
 
587
        mov     ebx, [current_slot]
588
        mov     eax, [ebx+APPDATA.heap_top]
589
        test    eax, eax
590
        jz      @F
591
        sub     eax, [ebx+APPDATA.heap_base]
592
        sub     eax, 4096
593
        ret
594
@@:
595
        mov     esi, [ebx+APPDATA.mem_size]
596
        add     esi, 4095
597
        and     esi, not 4095
598
        mov     [ebx+APPDATA.mem_size], esi
599
        mov     eax, HEAP_TOP
600
        mov     [ebx+APPDATA.heap_base], esi
601
        mov     [ebx+APPDATA.heap_top], eax
602
 
603
        sub     eax, esi
604
        shr     esi, 10
605
        mov     ecx, eax
606
        sub     eax, 4096
607
        or      ecx, FREE_BLOCK
608
        mov     [page_tabs+esi], ecx
609
        ret
610
endp
611
 
612
align 4
613
proc user_alloc stdcall, alloc_size:dword
614
 
615
        push    ebx
616
        push    esi
617
        push    edi
618
 
619
        mov     ecx, [alloc_size]
620
        add     ecx, (4095+4096)
621
        and     ecx, not 4095
622
 
623
        mov     ebx, [current_slot]
624
        mov     esi, dword [ebx+APPDATA.heap_base] ; heap_base
625
        mov     edi, dword [ebx+APPDATA.heap_top]  ; heap_top
626
l_0:
627
        cmp     esi, edi
628
        jae     m_exit
629
 
630
        mov     ebx, esi
631
        shr     ebx, 12
632
        mov     eax, [page_tabs+ebx*4]
633
        test    al, FREE_BLOCK
634
        jz      test_used
635
        and     eax, 0xFFFFF000
636
        cmp     eax, ecx   ;alloc_size
637
        jb      m_next
638
        jz      @f
639
 
640
        lea     edx, [esi+ecx]
641
        sub     eax, ecx
642
        or      al, FREE_BLOCK
643
        shr     edx, 12
644
        mov     [page_tabs+edx*4], eax
645
@@:
646
        or      ecx, USED_BLOCK
647
        mov     [page_tabs+ebx*4], ecx
648
        shr     ecx, 12
649
        inc     ebx
650
        dec     ecx
651
        jz      .no
652
@@:
653
        mov     dword [page_tabs+ebx*4], 2
654
        inc     ebx
655
        dec     ecx
656
        jnz     @B
657
.no:
658
 
659
        mov     edx, [current_slot]
660
        mov     ebx, [alloc_size]
661
        add     ebx, 0xFFF
662
        and     ebx, not 0xFFF
663
        add     ebx, [edx+APPDATA.mem_size]
664
        call    update_mem_size
665
 
666
        lea     eax, [esi+4096]
667
 
668
        pop     edi
669
        pop     esi
670
        pop     ebx
671
        ret
672
test_used:
673
        test    al, USED_BLOCK
674
        jz      m_exit
675
 
676
        and     eax, 0xFFFFF000
677
m_next:
678
        add     esi, eax
679
        jmp     l_0
680
m_exit:
681
        xor     eax, eax
682
        pop     edi
683
        pop     esi
684
        pop     ebx
685
        ret
686
endp
687
 
688
align 4
689
proc user_alloc_at stdcall, address:dword, alloc_size:dword
690
 
691
        push    ebx
692
        push    esi
693
        push    edi
694
 
695
        mov     ebx, [current_slot]
696
        mov     edx, [address]
697
        and     edx, not 0xFFF
698
        mov     [address], edx
699
        sub     edx, 0x1000
700
        jb      .error
701
        mov     esi, [ebx+APPDATA.heap_base]
702
        mov     edi, [ebx+APPDATA.heap_top]
703
        cmp     edx, esi
704
        jb      .error
705
.scan:
706
        cmp     esi, edi
707
        jae     .error
708
        mov     ebx, esi
709
        shr     ebx, 12
710
        mov     eax, [page_tabs+ebx*4]
711
        mov     ecx, eax
712
        and     ecx, 0xFFFFF000
713
        add     ecx, esi
714
        cmp     edx, ecx
715
        jb      .found
716
        mov     esi, ecx
717
        jmp     .scan
718
.error:
719
        xor     eax, eax
720
        pop     edi
721
        pop     esi
722
        pop     ebx
723
        ret
724
.found:
725
        test    al, FREE_BLOCK
726
        jz      .error
727
        mov     eax, ecx
728
        sub     eax, edx
729
        sub     eax, 0x1000
730
        cmp     eax, [alloc_size]
731
        jb      .error
732
 
733
; Here we have 1 big free block which includes requested area.
734
; In general, 3 other blocks must be created instead:
735
; free at [esi, edx);
736
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
737
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
738
; First or third block (or both) may be absent.
739
        mov     eax, edx
740
        sub     eax, esi
741
        jz      .nofirst
742
        or      al, FREE_BLOCK
743
        mov     [page_tabs+ebx*4], eax
744
.nofirst:
745
        mov     eax, [alloc_size]
746
        add     eax, 0x1FFF
747
        and     eax, not 0xFFF
748
        mov     ebx, edx
749
        add     edx, eax
750
        shr     ebx, 12
751
        or      al, USED_BLOCK
752
        mov     [page_tabs+ebx*4], eax
753
        shr     eax, 12
754
        dec     eax
755
        jz      .second_nofill
756
        inc     ebx
757
.fill:
758
        mov     dword [page_tabs+ebx*4], 2
759
        inc     ebx
760
        dec     eax
761
        jnz     .fill
3246 Serge 762
 
2288 clevermous 763
.second_nofill:
764
        sub     ecx, edx
765
        jz      .nothird
766
        or      cl, FREE_BLOCK
767
        mov     [page_tabs+ebx*4], ecx
3246 Serge 768
 
2288 clevermous 769
.nothird:
770
 
771
        mov     edx, [current_slot]
772
        mov     ebx, [alloc_size]
773
        add     ebx, 0xFFF
774
        and     ebx, not 0xFFF
775
        add     ebx, [edx+APPDATA.mem_size]
776
        call    update_mem_size
777
 
778
        mov     eax, [address]
779
 
780
        pop     edi
781
        pop     esi
782
        pop     ebx
783
        ret
784
endp
785
 
786
align 4
787
proc user_free stdcall, base:dword
788
 
789
        push    esi
790
 
791
        mov     esi, [base]
792
        test    esi, esi
793
        jz      .exit
794
 
795
        push    ebx
796
 
797
        xor     ebx, ebx
798
        shr     esi, 12
799
        mov     eax, [page_tabs+(esi-1)*4]
800
        test    al, USED_BLOCK
801
        jz      .cantfree
802
        test    al, DONT_FREE_BLOCK
803
        jnz     .cantfree
804
 
805
        and     eax, not 4095
806
        mov     ecx, eax
807
        or      al, FREE_BLOCK
808
        mov     [page_tabs+(esi-1)*4], eax
809
        sub     ecx, 4096
810
        mov     ebx, ecx
811
        shr     ecx, 12
812
        jz      .released
813
.release:
814
        xor     eax, eax
815
        xchg    eax, [page_tabs+esi*4]
816
        test    al, 1
817
        jz      @F
818
        test    eax, PG_SHARED
819
        jnz     @F
820
        call    free_page
821
        mov     eax, esi
822
        shl     eax, 12
823
        invlpg  [eax]
824
@@:
825
        inc     esi
826
        dec     ecx
827
        jnz     .release
3246 Serge 828
 
2288 clevermous 829
.released:
830
        push    edi
831
 
832
        mov     edx, [current_slot]
833
        mov     esi, dword [edx+APPDATA.heap_base]
834
        mov     edi, dword [edx+APPDATA.heap_top]
835
        sub     ebx, [edx+APPDATA.mem_size]
836
        neg     ebx
837
        call    update_mem_size
838
        call    user_normalize
839
        pop     edi
840
        pop     ebx
841
        pop     esi
842
        ret
843
.exit:
844
        xor     eax, eax
845
        inc     eax
846
        pop     esi
847
        ret
848
.cantfree:
849
        xor     eax, eax
850
        pop     ebx
851
        pop     esi
852
        ret
853
endp
854
 
2400 Serge 855
 
856
align 4
857
proc user_unmap stdcall, base:dword, offset:dword, size:dword
858
 
859
        push    ebx
860
 
861
        mov     ebx, [base]             ; must be valid pointer
862
        test    ebx, ebx
863
        jz      .error
864
 
865
        mov     edx, [offset]           ; check offset
866
        add     edx, ebx                ; must be below 2Gb app limit
867
        js      .error
868
 
869
        shr     ebx, 12                 ; chek block attributes
870
        lea     ebx, [page_tabs+ebx*4]
871
        mov     eax, [ebx-4]            ; block attributes
872
        test    al, USED_BLOCK
873
        jz      .error
874
        test    al, DONT_FREE_BLOCK
875
        jnz     .error
876
 
877
        shr     edx, 12
878
        lea     edx, [page_tabs+edx*4]  ; unmap offset
879
 
880
        mov     ecx, [size]
881
        add     ecx, 4095
882
        shr     ecx, 12                 ; unmap size in pages
883
 
884
        shr     eax, 12                 ; block size + 1 page
885
        lea     ebx, [ebx+eax*4-4]      ; block end ptr
886
        lea     eax, [edx+ecx*4]        ; unmap end ptr
887
 
888
        cmp     eax, ebx                ; check for overflow
889
        ja      .error
890
 
891
        mov     ebx, [offset]
892
        and     ebx, not 4095           ; is it required ?
3798 Serge 893
        add     ebx, [base]
2400 Serge 894
 
895
.unmap:
896
        mov     eax, [edx]              ; get page addres
897
        test    al, 1                   ; page mapped ?
898
        jz      @F
899
        test    eax, PG_SHARED          ; page shared ?
900
        jnz     @F
3798 Serge 901
        mov     [edx], dword 2
2400 Serge 902
                                        ; mark page as reserved
903
        invlpg  [ebx]                   ; when we start using
904
        call    free_page               ; empty c-o-w page instead this ?
905
@@:
906
        add     ebx, 4096
907
        add     edx, 4
908
        dec     ecx
909
        jnz     .unmap
910
 
911
        pop     ebx
912
        or      al, 1                   ; return non zero on success
913
        ret
914
.error:
915
        pop     ebx
916
        xor     eax, eax                ; something wrong
917
        ret
918
endp
919
 
920
align 4
2288 clevermous 921
user_normalize:
922
; in: esi=heap_base, edi=heap_top
923
; out: eax=0 <=> OK
924
; destroys: ebx,edx,esi,edi
925
        shr     esi, 12
926
        shr     edi, 12
927
@@:
928
        mov     eax, [page_tabs+esi*4]
929
        test    al, USED_BLOCK
930
        jz      .test_free
931
        shr     eax, 12
932
        add     esi, eax
933
        jmp     @B
934
.test_free:
935
        test    al, FREE_BLOCK
936
        jz      .err
937
        mov     edx, eax
938
        shr     edx, 12
939
        add     edx, esi
940
        cmp     edx, edi
941
        jae     .exit
942
 
943
        mov     ebx, [page_tabs+edx*4]
944
        test    bl, USED_BLOCK
945
        jz      .next_free
946
 
947
        shr     ebx, 12
948
        add     edx, ebx
949
        mov     esi, edx
950
        jmp     @B
951
.next_free:
952
        test    bl, FREE_BLOCK
953
        jz      .err
954
        and     dword [page_tabs+edx*4], 0
955
        add     eax, ebx
956
        and     eax, not 4095
957
        or      eax, FREE_BLOCK
958
        mov     [page_tabs+esi*4], eax
959
        jmp     @B
960
.exit:
961
        xor     eax, eax
962
        inc     eax
963
        ret
964
.err:
965
        xor     eax, eax
966
        ret
967
 
968
user_realloc:
969
; in: eax = pointer, ebx = new size
970
; out: eax = new pointer or NULL
971
        test    eax, eax
972
        jnz     @f
973
; realloc(NULL,sz) - same as malloc(sz)
974
        push    ebx
975
        call    user_alloc
976
        ret
977
@@:
978
        push    ecx edx
979
        lea     ecx, [eax - 0x1000]
980
        shr     ecx, 12
981
        mov     edx, [page_tabs+ecx*4]
982
        test    dl, USED_BLOCK
983
        jnz     @f
984
; attempt to realloc invalid pointer
985
.ret0:
986
        pop     edx ecx
987
        xor     eax, eax
988
        ret
989
@@:
990
        test    dl, DONT_FREE_BLOCK
991
        jnz     .ret0
992
        add     ebx, 0x1FFF
993
        shr     edx, 12
994
        shr     ebx, 12
995
; edx = allocated size, ebx = new size
996
        add     edx, ecx
997
        add     ebx, ecx
998
        cmp     edx, ebx
999
        jb      .realloc_add
1000
; release part of allocated memory
1001
.loop:
1002
        cmp     edx, ebx
1003
        jz      .release_done
1004
        dec     edx
1005
        xor     eax, eax
1006
        xchg    eax, [page_tabs+edx*4]
1007
        test    al, 1
1008
        jz      .loop
1009
        call    free_page
1010
        mov     eax, edx
1011
        shl     eax, 12
1012
        invlpg  [eax]
1013
        jmp     .loop
1014
.release_done:
1015
        sub     ebx, ecx
1016
        cmp     ebx, 1
1017
        jnz     .nofreeall
1018
        mov     eax, [page_tabs+ecx*4]
1019
        and     eax, not 0xFFF
1020
        mov     edx, [current_slot]
1021
        mov     ebx, [APPDATA.mem_size+edx]
1022
        sub     ebx, eax
1023
        add     ebx, 0x1000
1024
        or      al, FREE_BLOCK
1025
        mov     [page_tabs+ecx*4], eax
1026
        push    esi edi
1027
        mov     esi, [APPDATA.heap_base+edx]
1028
        mov     edi, [APPDATA.heap_top+edx]
1029
        call    update_mem_size
1030
        call    user_normalize
1031
        pop     edi esi
1032
        jmp     .ret0   ; all freed
1033
.nofreeall:
1034
        sub     edx, ecx
1035
        shl     ebx, 12
1036
        or      ebx, USED_BLOCK
1037
        xchg    [page_tabs+ecx*4], ebx
1038
        shr     ebx, 12
1039
        sub     ebx, edx
1040
        push    ebx ecx edx
1041
        mov     edx, [current_slot]
1042
        shl     ebx, 12
1043
        sub     ebx, [APPDATA.mem_size+edx]
1044
        neg     ebx
1045
        call    update_mem_size
1046
        pop     edx ecx ebx
1047
        lea     eax, [ecx+1]
1048
        shl     eax, 12
1049
        push    eax
1050
        add     ecx, edx
1051
        lea     edx, [ecx+ebx]
1052
        shl     ebx, 12
1053
        jz      .ret
1054
        push    esi
1055
        mov     esi, [current_slot]
1056
        mov     esi, [APPDATA.heap_top+esi]
1057
        shr     esi, 12
1058
@@:
1059
        cmp     edx, esi
1060
        jae     .merge_done
1061
        mov     eax, [page_tabs+edx*4]
1062
        test    al, USED_BLOCK
1063
        jnz     .merge_done
1064
        and     dword [page_tabs+edx*4], 0
1065
        shr     eax, 12
1066
        add     edx, eax
1067
        shl     eax, 12
1068
        add     ebx, eax
1069
        jmp     @b
1070
.merge_done:
1071
        pop     esi
1072
        or      ebx, FREE_BLOCK
1073
        mov     [page_tabs+ecx*4], ebx
1074
.ret:
1075
        pop     eax edx ecx
1076
        ret
1077
.realloc_add:
1078
; get some additional memory
1079
        mov     eax, [current_slot]
1080
        mov     eax, [APPDATA.heap_top+eax]
1081
        shr     eax, 12
1082
        cmp     edx, eax
1083
        jae     .cant_inplace
1084
        mov     eax, [page_tabs+edx*4]
1085
        test    al, FREE_BLOCK
1086
        jz      .cant_inplace
1087
        shr     eax, 12
1088
        add     eax, edx
1089
        sub     eax, ebx
1090
        jb      .cant_inplace
1091
        jz      @f
1092
        shl     eax, 12
1093
        or      al, FREE_BLOCK
1094
        mov     [page_tabs+ebx*4], eax
1095
@@:
1096
        mov     eax, ebx
1097
        sub     eax, ecx
1098
        shl     eax, 12
1099
        or      al, USED_BLOCK
1100
        mov     [page_tabs+ecx*4], eax
1101
        lea     eax, [ecx+1]
1102
        shl     eax, 12
1103
        push    eax
1104
        push    edi
1105
        lea     edi, [page_tabs+edx*4]
1106
        mov     eax, 2
1107
        sub     ebx, edx
1108
        mov     ecx, ebx
1109
        cld
1110
        rep stosd
1111
        pop     edi
1112
        mov     edx, [current_slot]
1113
        shl     ebx, 12
1114
        add     ebx, [APPDATA.mem_size+edx]
1115
        call    update_mem_size
1116
        pop     eax edx ecx
1117
        ret
1118
.cant_inplace:
1119
        push    esi edi
1120
        mov     eax, [current_slot]
1121
        mov     esi, [APPDATA.heap_base+eax]
1122
        mov     edi, [APPDATA.heap_top+eax]
1123
        shr     esi, 12
1124
        shr     edi, 12
1125
        sub     ebx, ecx
1126
.find_place:
1127
        cmp     esi, edi
1128
        jae     .place_not_found
1129
        mov     eax, [page_tabs+esi*4]
1130
        test    al, FREE_BLOCK
1131
        jz      .next_place
1132
        shr     eax, 12
1133
        cmp     eax, ebx
1134
        jae     .place_found
1135
        add     esi, eax
1136
        jmp     .find_place
1137
.next_place:
1138
        shr     eax, 12
1139
        add     esi, eax
1140
        jmp     .find_place
1141
.place_not_found:
1142
        pop     edi esi
1143
        jmp     .ret0
1144
.place_found:
1145
        sub     eax, ebx
1146
        jz      @f
1147
        push    esi
1148
        add     esi, ebx
1149
        shl     eax, 12
1150
        or      al, FREE_BLOCK
1151
        mov     [page_tabs+esi*4], eax
1152
        pop     esi
1153
@@:
1154
        mov     eax, ebx
1155
        shl     eax, 12
1156
        or      al, USED_BLOCK
1157
        mov     [page_tabs+esi*4], eax
1158
        inc     esi
1159
        mov     eax, esi
1160
        shl     eax, 12
1161
        push    eax
1162
        mov     eax, [page_tabs+ecx*4]
1163
        and     eax, not 0xFFF
1164
        or      al, FREE_BLOCK
1165
        sub     edx, ecx
1166
        mov     [page_tabs+ecx*4], eax
1167
        inc     ecx
1168
        dec     ebx
1169
        dec     edx
1170
        jz      .no
1171
@@:
1172
        xor     eax, eax
1173
        xchg    eax, [page_tabs+ecx*4]
1174
        mov     [page_tabs+esi*4], eax
1175
        mov     eax, ecx
1176
        shl     eax, 12
1177
        invlpg  [eax]
1178
        inc     esi
1179
        inc     ecx
1180
        dec     ebx
1181
        dec     edx
1182
        jnz     @b
1183
.no:
1184
        push    ebx
1185
        mov     edx, [current_slot]
1186
        shl     ebx, 12
1187
        add     ebx, [APPDATA.mem_size+edx]
1188
        call    update_mem_size
1189
        pop     ebx
1190
@@:
1191
        mov     dword [page_tabs+esi*4], 2
1192
        inc     esi
1193
        dec     ebx
1194
        jnz     @b
1195
        pop     eax edi esi edx ecx
1196
        ret
1197
 
1198
if 0
1199
align 4
1200
proc alloc_dll
1201
        pushf
1202
        cli
1203
        bsf     eax, [dll_map]
1204
        jnz     .find
1205
        popf
1206
        xor     eax, eax
1207
        ret
1208
.find:
1209
        btr     [dll_map], eax
1210
        popf
1211
        shl     eax, 5
1212
        add     eax, dll_tab
1213
        ret
1214
endp
1215
 
1216
align 4
1217
proc alloc_service
1218
        pushf
1219
        cli
1220
        bsf     eax, [srv_map]
1221
        jnz     .find
1222
        popf
1223
        xor     eax, eax
1224
        ret
1225
.find:
1226
        btr     [srv_map], eax
1227
        popf
1228
        shl     eax, 0x02
1229
        lea     eax, [srv_tab+eax+eax*8] ;srv_tab+eax*36
1230
        ret
1231
endp
1232
 
1233
end if
1234
 
1235
 
1236
;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
1237
 
1238
 
1239
; param
1240
;  eax= shm_map object
1241
 
1242
align 4
1243
destroy_smap:
1244
 
1245
        pushfd
1246
        cli
1247
 
1248
        push    esi
1249
        push    edi
1250
 
1251
        mov     edi, eax
1252
        mov     esi, [eax+SMAP.parent]
1253
        test    esi, esi
1254
        jz      .done
1255
 
1256
        lock dec [esi+SMEM.refcount]
1257
        jnz     .done
1258
 
1259
        mov     ecx, [esi+SMEM.bk]
1260
        mov     edx, [esi+SMEM.fd]
1261
 
1262
        mov     [ecx+SMEM.fd], edx
1263
        mov     [edx+SMEM.bk], ecx
1264
 
1265
        stdcall kernel_free, [esi+SMEM.base]
1266
        mov     eax, esi
1267
        call    free
1268
.done:
1269
        mov     eax, edi
1270
        call    destroy_kernel_object
1271
 
1272
        pop     edi
1273
        pop     esi
1274
        popfd
1275
 
1276
        ret
1277
 
1278
E_NOTFOUND      equ  5
1279
E_ACCESS        equ 10
1280
E_NOMEM         equ 30
1281
E_PARAM         equ 33
1282
 
1283
SHM_READ        equ 0
1284
SHM_WRITE       equ 1
1285
 
1286
SHM_ACCESS_MASK equ 3
1287
 
1288
SHM_OPEN        equ (0 shl 2)
1289
SHM_OPEN_ALWAYS equ (1 shl 2)
1290
SHM_CREATE      equ (2 shl 2)
1291
 
1292
SHM_OPEN_MASK   equ (3 shl 2)
1293
 
1294
align 4
1295
proc shmem_open stdcall name:dword, size:dword, access:dword
3246 Serge 1296
        locals
1297
           action         dd ?
1298
           owner_access   dd ?
1299
           mapped         dd ?
1300
        endl
2288 clevermous 1301
 
1302
        push    ebx
1303
        push    esi
1304
        push    edi
1305
 
1306
        mov     [mapped], 0
1307
        mov     [owner_access], 0
1308
 
1309
        pushfd                         ;mutex required
1310
        cli
1311
 
1312
        mov     eax, [access]
1313
        and     eax, SHM_OPEN_MASK
1314
        mov     [action], eax
1315
 
1316
        mov     ebx, [name]
1317
        test    ebx, ebx
1318
        mov     edx, E_PARAM
1319
        jz      .fail
1320
 
1321
        mov     esi, [shmem_list.fd]
1322
align 4
1323
@@:
1324
        cmp     esi, shmem_list
1325
        je      .not_found
1326
 
1327
        lea     edx, [esi+SMEM.name]; link , base, size
1328
        stdcall strncmp, edx, ebx, 32
1329
        test    eax, eax
1330
        je      .found
1331
 
1332
        mov     esi, [esi+SMEM.fd]
1333
        jmp     @B
1334
 
1335
.not_found:
1336
        mov     eax, [action]
1337
 
1338
        cmp     eax, SHM_OPEN
1339
        mov     edx, E_NOTFOUND
1340
        je      .fail
1341
 
1342
        cmp     eax, SHM_CREATE
1343
        mov     edx, E_PARAM
1344
        je      .create_shm
1345
 
1346
        cmp     eax, SHM_OPEN_ALWAYS
1347
        jne     .fail
1348
 
1349
.create_shm:
1350
 
1351
        mov     ecx, [size]
1352
        test    ecx, ecx
1353
        jz      .fail
1354
 
1355
        add     ecx, 4095
1356
        and     ecx, -4096
1357
        mov     [size], ecx
1358
 
2384 hidnplayr 1359
        mov     eax, sizeof.SMEM
2288 clevermous 1360
        call    malloc
1361
        test    eax, eax
1362
        mov     esi, eax
1363
        mov     edx, E_NOMEM
1364
        jz      .fail
1365
 
1366
        stdcall kernel_alloc, [size]
1367
        test    eax, eax
1368
        mov     [mapped], eax
1369
        mov     edx, E_NOMEM
1370
        jz      .cleanup
1371
 
1372
        mov     ecx, [size]
1373
        mov     edx, [access]
1374
        and     edx, SHM_ACCESS_MASK
1375
 
1376
        mov     [esi+SMEM.base], eax
1377
        mov     [esi+SMEM.size], ecx
1378
        mov     [esi+SMEM.access], edx
1379
        mov     [esi+SMEM.refcount], 0
1380
        mov     [esi+SMEM.name+28], 0
1381
 
1382
        lea     eax, [esi+SMEM.name]
1383
        stdcall strncpy, eax, [name], 31
1384
 
1385
        mov     eax, [shmem_list.fd]
1386
        mov     [esi+SMEM.bk], shmem_list
1387
        mov     [esi+SMEM.fd], eax
1388
 
1389
        mov     [eax+SMEM.bk], esi
1390
        mov     [shmem_list.fd], esi
1391
 
1392
        mov     [action], SHM_OPEN
1393
        mov     [owner_access], SHM_WRITE
1394
 
1395
.found:
1396
        mov     eax, [action]
1397
 
1398
        cmp     eax, SHM_CREATE
1399
        mov     edx, E_ACCESS
1400
        je      .exit
1401
 
1402
        cmp     eax, SHM_OPEN
1403
        mov     edx, E_PARAM
1404
        je      .create_map
1405
 
1406
        cmp     eax, SHM_OPEN_ALWAYS
1407
        jne     .fail
1408
 
1409
.create_map:
1410
 
1411
        mov     eax, [access]
1412
        and     eax, SHM_ACCESS_MASK
1413
        cmp     eax, [esi+SMEM.access]
1414
        mov     [access], eax
1415
        mov     edx, E_ACCESS
1416
        ja      .fail
1417
 
1418
        mov     ebx, [CURRENT_TASK]
1419
        shl     ebx, 5
1420
        mov     ebx, [CURRENT_TASK+ebx+4]
2384 hidnplayr 1421
        mov     eax, sizeof.SMAP
2288 clevermous 1422
 
1423
        call    create_kernel_object
1424
        test    eax, eax
1425
        mov     edi, eax
1426
        mov     edx, E_NOMEM
1427
        jz      .fail
1428
 
1429
        inc     [esi+SMEM.refcount]
1430
 
1431
        mov     [edi+SMAP.magic], 'SMAP'
1432
        mov     [edi+SMAP.destroy], destroy_smap
1433
        mov     [edi+SMAP.parent], esi
1434
        mov     [edi+SMAP.base], 0
1435
 
1436
        stdcall user_alloc, [esi+SMEM.size]
1437
        test    eax, eax
1438
        mov     [mapped], eax
1439
        mov     edx, E_NOMEM
1440
        jz      .cleanup2
1441
 
1442
        mov     [edi+SMAP.base], eax
1443
 
1444
        mov     ecx, [esi+SMEM.size]
1445
        mov     [size], ecx
1446
 
1447
        shr     ecx, 12
1448
        shr     eax, 10
1449
 
1450
        mov     esi, [esi+SMEM.base]
1451
        shr     esi, 10
1452
        lea     edi, [page_tabs+eax]
1453
        add     esi, page_tabs
1454
 
1455
        mov     edx, [access]
1456
        or      edx, [owner_access]
1457
        shl     edx, 1
1458
        or      edx, PG_USER+PG_SHARED
1459
@@:
1460
        lodsd
1461
        and     eax, 0xFFFFF000
1462
        or      eax, edx
1463
        stosd
1464
        loop    @B
1465
 
1466
        xor     edx, edx
1467
 
1468
        cmp     [owner_access], 0
1469
        jne     .fail
1470
.exit:
1471
        mov     edx, [size]
1472
.fail:
1473
        mov     eax, [mapped]
1474
 
1475
        popfd
1476
        pop     edi
1477
        pop     esi
1478
        pop     ebx
1479
        ret
1480
.cleanup:
1481
        mov     [size], edx
1482
        mov     eax, esi
1483
        call    free
1484
        jmp     .exit
1485
 
1486
.cleanup2:
1487
        mov     [size], edx
1488
        mov     eax, edi
1489
        call    destroy_smap
1490
        jmp     .exit
1491
endp
1492
 
1493
align 4
1494
proc shmem_close stdcall, name:dword
1495
 
1496
        mov     eax, [name]
1497
        test    eax, eax
1498
        jz      .fail
1499
 
1500
        push    esi
1501
        push    edi
1502
        pushfd
1503
        cli
1504
 
1505
        mov     esi, [current_slot]
1506
        add     esi, APP_OBJ_OFFSET
1507
.next:
1508
        mov     eax, [esi+APPOBJ.fd]
1509
        test    eax, eax
1510
        jz      @F
1511
 
1512
        cmp     eax, esi
1513
        mov     esi, eax
1514
        je      @F
1515
 
1516
        cmp     [eax+SMAP.magic], 'SMAP'
1517
        jne     .next
1518
 
1519
        mov     edi, [eax+SMAP.parent]
1520
        test    edi, edi
1521
        jz      .next
1522
 
1523
        lea     edi, [edi+SMEM.name]
1524
        stdcall strncmp, [name], edi, 32
1525
        test    eax, eax
1526
        jne     .next
1527
 
1528
        stdcall user_free, [esi+SMAP.base]
1529
 
1530
        mov     eax, esi
1531
        call    [esi+APPOBJ.destroy]
1532
@@:
1533
        popfd
1534
        pop     edi
1535
        pop     esi
1536
.fail:
1537
        ret
1538
endp