Subversion Repositories Kolibri OS

Rev

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