Subversion Repositories Kolibri OS

Rev

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