Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4429 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 4424 $
9
 
10
 
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
20
 
21
FREE_BLOCK      equ  4
22
USED_BLOCK      equ  8
23
DONT_FREE_BLOCK equ  10h
24
 
25
 
26
block_next   equ MEM_BLOCK.next_block
27
block_prev   equ MEM_BLOCK.prev_block
28
list_fd      equ MEM_BLOCK.list.next
29
list_bk      equ MEM_BLOCK.list.prev
30
block_base   equ MEM_BLOCK.base
31
block_size   equ MEM_BLOCK.size
32
block_flags  equ MEM_BLOCK.flags
33
 
34
macro calc_index op
35
{          shr op, 12
36
        dec     op
37
        cmp     op, 63
38
        jna     @f
39
        mov     op, 63
40
@@:
41
}
42
 
43
align 4
44
md:
45
.add_to_used:
46
        mov     eax, [esi+block_base]
47
        mov     ebx, [esi+block_base]
48
        shr     ebx, 6
49
        add     eax, ebx
50
        shr     ebx, 6
51
        add     eax, ebx
52
        shr     eax, 12
53
        and     eax, 63
54
        inc     [mem_hash_cnt+eax*4]
55
 
56
        lea     ecx, [mem_used_list+eax*8]
57
        list_add esi, ecx
58
        mov     [esi+block_flags], USED_BLOCK
59
        mov     eax, [esi+block_size]
60
        sub     [heap_free], eax
61
        ret
62
align 4
63
.find_used:
64
        mov     ecx, eax
65
        mov     ebx, eax
66
        shr     ebx, 6
67
        add     ecx, ebx
68
        shr     ebx, 6
69
        add     ecx, ebx
70
        shr     ecx, 12
71
        and     ecx, 63
72
 
73
        lea     ebx, [mem_used_list+ecx*8]
74
        mov     esi, ebx
75
.next:
76
        mov     esi, [esi+list_fd]
77
        cmp     esi, ebx
78
        je      .fail
79
 
80
        cmp     eax, [esi+block_base]
81
        jne     .next
82
 
83
        ret
84
.fail:
85
        xor     esi, esi
86
        ret
87
 
88
align 4
89
.del_from_used:
90
        call    .find_used
91
        test    esi, esi
92
        jz      .done
93
 
94
        cmp     [esi+block_flags], USED_BLOCK
95
        jne     .fatal
96
 
97
        dec     [mem_hash_cnt+ecx*4]
98
        list_del esi
99
.done:
100
        ret
101
.fatal:                            ;FIXME panic here
102
        xor     esi, esi
103
        ret
104
 
105
;Initial heap state
106
;
107
;+heap_size               terminator        USED_BLOCK
108
;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
109
;HEAP_BASE                heap_descriptors  USED_BLOCK
110
;
111
 
112
align 4
113
proc init_kernel_heap
114
 
115
        mov     ecx, 64
116
        mov     edi, mem_block_list
117
@@:
118
        mov     eax, edi
119
        stosd
120
        stosd
121
        loop    @B
122
 
123
        mov     ecx, 64
124
        mov     edi, mem_used_list
125
@@:
126
        mov     eax, edi
127
        stosd
128
        stosd
129
        loop    @B
130
 
131
        stdcall alloc_pages, dword 32
132
 
133
        or      eax, PG_SW
134
        mov     ebx, HEAP_BASE
135
        mov     ecx, 32
136
        call    commit_pages
137
 
138
        mov     edi, HEAP_BASE                     ;descriptors
139
        mov     ebx, HEAP_BASE+sizeof.MEM_BLOCK      ;free space
140
        mov     ecx, HEAP_BASE+sizeof.MEM_BLOCK*2    ;terminator
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
148
        mov     [edi+block_size], 4096*sizeof.MEM_BLOCK
149
        mov     [edi+block_flags], USED_BLOCK
150
 
151
        mov     [ecx+block_next], eax
152
        mov     [ecx+block_prev], ebx
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
158
 
159
        mov     [ebx+block_next], ecx
160
        mov     [ebx+block_prev], edi
161
        mov     [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
162
 
163
        mov     ecx, [pg_data.kernel_pages]
164
        shl     ecx, 12
165
        sub     ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
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
175
        list_add ebx, ecx
176
 
177
        mov     ecx, 4096-3-1
178
        mov     eax, HEAP_BASE+sizeof.MEM_BLOCK*4
179
 
180
        mov     [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
181
@@:
182
        mov     [eax-sizeof.MEM_BLOCK], eax
183
        add     eax, sizeof.MEM_BLOCK
184
        loop    @B
185
 
186
        mov     [eax-sizeof.MEM_BLOCK], dword 0
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
 
283
        spin_lock_irqsave heap_mutex
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]
324
        calc_index eax
325
        cmp     eax, [block_ind]
326
        je      .add_used
327
 
328
        list_del edi
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
338
        list_add edi, edx
339
.add_used:
340
 
341
        call    md.add_to_used
342
 
343
        spin_unlock_irqrestore heap_mutex
344
        mov     eax, [esi+block_base]
345
        pop     edi
346
        pop     esi
347
        pop     ebx
348
        ret
349
 
350
.m_eq_size:
351
        list_del edi
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:
361
        spin_unlock_irqrestore heap_mutex
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
 
373
        spin_lock_irqsave heap_mutex
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
 
388
        list_del edi
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
 
396
        calc_index ecx
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
 
422
        calc_index eax                     ;new index
423
        calc_index ecx                     ;old index
424
        cmp     eax, ecx
425
        je      .m_eq
426
 
427
        push    ecx
428
        list_del edi
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
435
 
436
.add_block:
437
        bts     [mem_block_mask], eax
438
        lea     edx, [mem_block_list+eax*8]
439
        list_add edi, edx
440
.m_eq:
441
        spin_unlock_irqrestore heap_mutex
442
        xor     eax, eax
443
        not     eax
444
        ret
445
.insert:
446
        mov     [esi+block_flags], FREE_BLOCK
447
        mov     eax, [esi+block_size]
448
        calc_index eax
449
        mov     edi, esi
450
        jmp     .add_block
451
 
452
.fail:
453
        spin_unlock_irqrestore heap_mutex
454
        xor     eax, eax
455
        ret
456
endp
457
 
458
align 4
459
proc kernel_alloc stdcall, size:dword
460
        locals
461
          lin_addr    dd ?
462
          pages_count dd ?
463
        endl
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
479
        mov     [lin_addr], eax
480
        mov     ebx, [pages_count]
481
        test    eax, eax
482
        jz      .err
483
 
484
        mov     edx, eax
485
 
486
        shr     ebx, 3
487
        jz      .tail
488
 
489
        shl     ebx, 3
490
        stdcall alloc_pages, ebx
491
        test    eax, eax
492
        jz      .err
493
 
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
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
511
        dec     ebx
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
 
530
        spin_lock_irqsave heap_mutex
531
 
532
        mov     eax, [base]
533
        call    md.find_used
534
 
535
        cmp     [esi+block_flags], USED_BLOCK
536
        jne     .fail
537
 
538
        spin_unlock_irqrestore heap_mutex
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:
548
        spin_unlock_irqrestore heap_mutex
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
 
4434 Serge 561
;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
4429 Serge 562
 
563
HEAP_TOP  equ 0x80000000
564
 
565
align 4
566
proc init_heap
567
 
4432 Serge 568
        mov     ebx, [current_process]
4430 Serge 569
        mov     eax, [ebx+PROC.heap_top]
4429 Serge 570
        test    eax, eax
571
        jz      @F
4430 Serge 572
        sub     eax, [ebx+PROC.heap_base]
573
        sub     eax, PAGE_SIZE
4429 Serge 574
        ret
575
@@:
4434 Serge 576
        lea     ecx, [ebx+PROC.heap_lock]
577
        call    mutex_init
578
 
4430 Serge 579
        mov     esi, [ebx+PROC.mem_used]
4429 Serge 580
        add     esi, 4095
581
        and     esi, not 4095
4430 Serge 582
        mov     [ebx+PROC.mem_used], esi
4429 Serge 583
        mov     eax, HEAP_TOP
4430 Serge 584
        mov     [ebx+PROC.heap_base], esi
585
        mov     [ebx+PROC.heap_top], eax
4429 Serge 586
 
587
        sub     eax, esi
588
        shr     esi, 10
589
        mov     ecx, eax
4430 Serge 590
        sub     eax, PAGE_SIZE
4429 Serge 591
        or      ecx, FREE_BLOCK
592
        mov     [page_tabs+esi], ecx
593
        ret
594
endp
595
 
596
align 4
597
proc user_alloc stdcall, alloc_size:dword
598
 
599
        push    ebx
600
        push    esi
601
        push    edi
602
 
4434 Serge 603
        mov     ebx, [current_process]
604
        lea     ecx, [ebx+PROC.heap_lock]
605
        call    mutex_lock
606
 
4429 Serge 607
        mov     ecx, [alloc_size]
4430 Serge 608
        add     ecx, (4095+PAGE_SIZE)
4429 Serge 609
        and     ecx, not 4095
610
 
4430 Serge 611
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
612
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
613
.scan:
4429 Serge 614
        cmp     esi, edi
4430 Serge 615
        jae     .m_exit
4429 Serge 616
 
617
        mov     ebx, esi
618
        shr     ebx, 12
619
        mov     eax, [page_tabs+ebx*4]
620
        test    al, FREE_BLOCK
4430 Serge 621
        jz      .test_used
4429 Serge 622
        and     eax, 0xFFFFF000
623
        cmp     eax, ecx   ;alloc_size
4430 Serge 624
        jb      .m_next
4429 Serge 625
        jz      @f
626
 
627
        lea     edx, [esi+ecx]
628
        sub     eax, ecx
629
        or      al, FREE_BLOCK
630
        shr     edx, 12
631
        mov     [page_tabs+edx*4], eax
632
@@:
633
        or      ecx, USED_BLOCK
634
        mov     [page_tabs+ebx*4], ecx
635
        shr     ecx, 12
636
        inc     ebx
637
        dec     ecx
638
        jz      .no
639
@@:
640
        mov     dword [page_tabs+ebx*4], 2
641
        inc     ebx
642
        dec     ecx
643
        jnz     @B
644
.no:
645
 
4432 Serge 646
        mov     edx, [current_process]
4429 Serge 647
        mov     ebx, [alloc_size]
648
        add     ebx, 0xFFF
649
        and     ebx, not 0xFFF
4430 Serge 650
        add     [edx+PROC.mem_used], ebx
4429 Serge 651
 
4434 Serge 652
        lea     ecx, [edx+PROC.heap_lock]
653
        call    mutex_unlock
654
 
4429 Serge 655
        lea     eax, [esi+4096]
656
 
657
        pop     edi
658
        pop     esi
659
        pop     ebx
660
        ret
4430 Serge 661
.test_used:
4429 Serge 662
        test    al, USED_BLOCK
4430 Serge 663
        jz      .m_exit
4429 Serge 664
 
665
        and     eax, 0xFFFFF000
4430 Serge 666
.m_next:
4429 Serge 667
        add     esi, eax
4430 Serge 668
        jmp     .scan
669
.m_exit:
4434 Serge 670
        mov     ecx, [current_process]
671
        lea     ecx, [ecx+PROC.heap_lock]
672
        call    mutex_unlock
673
 
4429 Serge 674
        xor     eax, eax
675
        pop     edi
676
        pop     esi
677
        pop     ebx
678
        ret
679
endp
680
 
681
align 4
682
proc user_alloc_at stdcall, address:dword, alloc_size:dword
683
 
684
        push    ebx
685
        push    esi
686
        push    edi
687
 
4432 Serge 688
        mov     ebx, [current_process]
4434 Serge 689
        lea     ecx, [ebx+PROC.heap_lock]
690
        call    mutex_lock
4430 Serge 691
 
4429 Serge 692
        mov     edx, [address]
693
        and     edx, not 0xFFF
694
        mov     [address], edx
695
        sub     edx, 0x1000
696
        jb      .error
4430 Serge 697
        mov     esi, [ebx+PROC.heap_base]
698
        mov     edi, [ebx+PROC.heap_top]
4429 Serge 699
        cmp     edx, esi
700
        jb      .error
701
.scan:
702
        cmp     esi, edi
703
        jae     .error
704
        mov     ebx, esi
705
        shr     ebx, 12
706
        mov     eax, [page_tabs+ebx*4]
707
        mov     ecx, eax
708
        and     ecx, 0xFFFFF000
709
        add     ecx, esi
710
        cmp     edx, ecx
711
        jb      .found
712
        mov     esi, ecx
713
        jmp     .scan
714
.error:
4434 Serge 715
        mov     ecx, [current_process]
716
        lea     ecx, [ecx+PROC.heap_lock]
717
        call    mutex_unlock
718
 
4429 Serge 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
762
 
763
.second_nofill:
764
        sub     ecx, edx
765
        jz      .nothird
766
        or      cl, FREE_BLOCK
767
        mov     [page_tabs+ebx*4], ecx
768
 
769
.nothird:
4432 Serge 770
        mov     edx, [current_process]
4429 Serge 771
        mov     ebx, [alloc_size]
772
        add     ebx, 0xFFF
773
        and     ebx, not 0xFFF
4430 Serge 774
        add     [edx+PROC.mem_used], ebx
4429 Serge 775
 
4434 Serge 776
        lea     ecx, [edx+PROC.heap_lock]
777
        call    mutex_unlock
778
 
4429 Serge 779
        mov     eax, [address]
780
 
781
        pop     edi
782
        pop     esi
783
        pop     ebx
784
        ret
785
endp
786
 
787
align 4
788
proc user_free stdcall, base:dword
789
 
790
        push    esi
791
 
792
        mov     esi, [base]
793
        test    esi, esi
4434 Serge 794
        jz      .fail
4429 Serge 795
 
796
        push    ebx
797
 
4434 Serge 798
        mov     ebx, [current_process]
799
        lea     ecx, [ebx+PROC.heap_lock]
800
        call    mutex_lock
801
 
4429 Serge 802
        xor     ebx, ebx
803
        shr     esi, 12
804
        mov     eax, [page_tabs+(esi-1)*4]
805
        test    al, USED_BLOCK
806
        jz      .cantfree
807
        test    al, DONT_FREE_BLOCK
808
        jnz     .cantfree
809
 
810
        and     eax, not 4095
811
        mov     ecx, eax
812
        or      al, FREE_BLOCK
813
        mov     [page_tabs+(esi-1)*4], eax
814
        sub     ecx, 4096
815
        mov     ebx, ecx
816
        shr     ecx, 12
817
        jz      .released
818
.release:
819
        xor     eax, eax
820
        xchg    eax, [page_tabs+esi*4]
821
        test    al, 1
822
        jz      @F
823
        test    eax, PG_SHARED
824
        jnz     @F
825
        call    free_page
826
        mov     eax, esi
827
        shl     eax, 12
828
        invlpg  [eax]
829
@@:
830
        inc     esi
831
        dec     ecx
832
        jnz     .release
833
 
834
.released:
835
        push    edi
836
 
4432 Serge 837
        mov     edx, [current_process]
4434 Serge 838
        lea     ecx, [edx+PROC.heap_lock]
4430 Serge 839
        mov     esi, dword [edx+PROC.heap_base]
840
        mov     edi, dword [edx+PROC.heap_top]
841
        sub     ebx, [edx+PROC.mem_used]
4429 Serge 842
        neg     ebx
4430 Serge 843
        mov     [edx+PROC.mem_used], ebx
4429 Serge 844
        call    user_normalize
845
        pop     edi
846
.exit:
4434 Serge 847
        call    mutex_unlock
848
 
4429 Serge 849
        xor     eax, eax
5119 serge 850
        inc     eax
4434 Serge 851
        pop     ebx
4429 Serge 852
        pop     esi
853
        ret
4434 Serge 854
 
4429 Serge 855
.cantfree:
4434 Serge 856
        mov     ecx, [current_process]
857
        lea     ecx, [ecx+PROC.heap_lock]
858
        jmp     .exit
859
.fail:
4429 Serge 860
        xor     eax, eax
861
        pop     esi
862
        ret
863
endp
864
 
865
 
866
align 4
867
proc user_unmap stdcall, base:dword, offset:dword, size:dword
868
 
869
        push    ebx
870
 
871
        mov     ebx, [base]             ; must be valid pointer
872
        test    ebx, ebx
873
        jz      .error
874
 
875
        mov     edx, [offset]           ; check offset
876
        add     edx, ebx                ; must be below 2Gb app limit
877
        js      .error
878
 
879
        shr     ebx, 12                 ; chek block attributes
880
        lea     ebx, [page_tabs+ebx*4]
881
        mov     eax, [ebx-4]            ; block attributes
882
        test    al, USED_BLOCK
883
        jz      .error
884
        test    al, DONT_FREE_BLOCK
885
        jnz     .error
886
 
887
        shr     edx, 12
888
        lea     edx, [page_tabs+edx*4]  ; unmap offset
889
 
890
        mov     ecx, [size]
891
        add     ecx, 4095
892
        shr     ecx, 12                 ; unmap size in pages
893
 
894
        shr     eax, 12                 ; block size + 1 page
895
        lea     ebx, [ebx+eax*4-4]      ; block end ptr
896
        lea     eax, [edx+ecx*4]        ; unmap end ptr
897
 
898
        cmp     eax, ebx                ; check for overflow
899
        ja      .error
900
 
901
        mov     ebx, [offset]
902
        and     ebx, not 4095           ; is it required ?
903
        add     ebx, [base]
904
 
905
.unmap:
906
        mov     eax, [edx]              ; get page addres
907
        test    al, 1                   ; page mapped ?
908
        jz      @F
909
        test    eax, PG_SHARED          ; page shared ?
910
        jnz     @F
911
        mov     [edx], dword 2
912
                                        ; mark page as reserved
913
        invlpg  [ebx]                   ; when we start using
914
        call    free_page               ; empty c-o-w page instead this ?
915
@@:
916
        add     ebx, 4096
917
        add     edx, 4
918
        dec     ecx
919
        jnz     .unmap
920
 
921
        pop     ebx
922
        or      al, 1                   ; return non zero on success
923
        ret
924
.error:
925
        pop     ebx
926
        xor     eax, eax                ; something wrong
927
        ret
928
endp
929
 
930
align 4
931
user_normalize:
932
; in: esi=heap_base, edi=heap_top
933
; out: eax=0 <=> OK
934
; destroys: ebx,edx,esi,edi
935
        shr     esi, 12
936
        shr     edi, 12
937
@@:
938
        mov     eax, [page_tabs+esi*4]
939
        test    al, USED_BLOCK
940
        jz      .test_free
941
        shr     eax, 12
942
        add     esi, eax
943
        jmp     @B
944
.test_free:
945
        test    al, FREE_BLOCK
946
        jz      .err
947
        mov     edx, eax
948
        shr     edx, 12
949
        add     edx, esi
950
        cmp     edx, edi
951
        jae     .exit
952
 
953
        mov     ebx, [page_tabs+edx*4]
954
        test    bl, USED_BLOCK
955
        jz      .next_free
956
 
957
        shr     ebx, 12
958
        add     edx, ebx
959
        mov     esi, edx
960
        jmp     @B
961
.next_free:
962
        test    bl, FREE_BLOCK
963
        jz      .err
964
        and     dword [page_tabs+edx*4], 0
965
        add     eax, ebx
966
        and     eax, not 4095
967
        or      eax, FREE_BLOCK
968
        mov     [page_tabs+esi*4], eax
969
        jmp     @B
970
.exit:
971
        xor     eax, eax
972
        inc     eax
973
        ret
974
.err:
975
        xor     eax, eax
976
        ret
977
 
978
user_realloc:
979
; in: eax = pointer, ebx = new size
980
; out: eax = new pointer or NULL
981
        test    eax, eax
982
        jnz     @f
983
; realloc(NULL,sz) - same as malloc(sz)
984
        push    ebx
985
        call    user_alloc
986
        ret
987
@@:
988
        push    ecx edx
4434 Serge 989
 
990
        push    eax
991
        mov     ecx, [current_process]
992
        lea     ecx, [ecx+PROC.heap_lock]
993
        call    mutex_lock
994
        pop     eax
995
 
4429 Serge 996
        lea     ecx, [eax - 0x1000]
997
        shr     ecx, 12
998
        mov     edx, [page_tabs+ecx*4]
999
        test    dl, USED_BLOCK
1000
        jnz     @f
1001
; attempt to realloc invalid pointer
1002
.ret0:
4434 Serge 1003
        mov     ecx, [current_process]
1004
        lea     ecx, [ecx+PROC.heap_lock]
1005
        call    mutex_unlock
1006
 
4429 Serge 1007
        pop     edx ecx
1008
        xor     eax, eax
1009
        ret
1010
@@:
1011
        test    dl, DONT_FREE_BLOCK
1012
        jnz     .ret0
1013
        add     ebx, 0x1FFF
1014
        shr     edx, 12
1015
        shr     ebx, 12
1016
; edx = allocated size, ebx = new size
1017
        add     edx, ecx
1018
        add     ebx, ecx
1019
        cmp     edx, ebx
1020
        jb      .realloc_add
1021
; release part of allocated memory
1022
.loop:
1023
        cmp     edx, ebx
1024
        jz      .release_done
1025
        dec     edx
1026
        xor     eax, eax
1027
        xchg    eax, [page_tabs+edx*4]
1028
        test    al, 1
1029
        jz      .loop
1030
        call    free_page
1031
        mov     eax, edx
1032
        shl     eax, 12
1033
        invlpg  [eax]
1034
        jmp     .loop
1035
.release_done:
1036
        sub     ebx, ecx
1037
        cmp     ebx, 1
1038
        jnz     .nofreeall
1039
        mov     eax, [page_tabs+ecx*4]
1040
        and     eax, not 0xFFF
4432 Serge 1041
        mov     edx, [current_process]
4430 Serge 1042
        mov     ebx, [edx+PROC.mem_used]
4429 Serge 1043
        sub     ebx, eax
1044
        add     ebx, 0x1000
1045
        or      al, FREE_BLOCK
1046
        mov     [page_tabs+ecx*4], eax
1047
        push    esi edi
4430 Serge 1048
        mov     esi, [edx+PROC.heap_base]
1049
        mov     edi, [edx+PROC.heap_top]
1050
        mov     [edx+PROC.mem_used], ebx
4429 Serge 1051
        call    user_normalize
1052
        pop     edi esi
1053
        jmp     .ret0   ; all freed
1054
.nofreeall:
1055
        sub     edx, ecx
1056
        shl     ebx, 12
1057
        or      ebx, USED_BLOCK
1058
        xchg    [page_tabs+ecx*4], ebx
1059
        shr     ebx, 12
1060
        sub     ebx, edx
1061
        push    ebx ecx edx
4432 Serge 1062
        mov     edx, [current_process]
4429 Serge 1063
        shl     ebx, 12
4430 Serge 1064
        sub     ebx, [edx+PROC.mem_used]
4429 Serge 1065
        neg     ebx
4430 Serge 1066
        mov     [edx+PROC.mem_used], ebx
4429 Serge 1067
        pop     edx ecx ebx
1068
        lea     eax, [ecx+1]
1069
        shl     eax, 12
1070
        push    eax
1071
        add     ecx, edx
1072
        lea     edx, [ecx+ebx]
1073
        shl     ebx, 12
1074
        jz      .ret
1075
        push    esi
4432 Serge 1076
        mov     esi, [current_process]
4430 Serge 1077
        mov     esi, [esi+PROC.heap_top]
4429 Serge 1078
        shr     esi, 12
1079
@@:
1080
        cmp     edx, esi
1081
        jae     .merge_done
1082
        mov     eax, [page_tabs+edx*4]
1083
        test    al, USED_BLOCK
1084
        jnz     .merge_done
1085
        and     dword [page_tabs+edx*4], 0
1086
        shr     eax, 12
1087
        add     edx, eax
1088
        shl     eax, 12
1089
        add     ebx, eax
1090
        jmp     @b
1091
.merge_done:
1092
        pop     esi
1093
        or      ebx, FREE_BLOCK
1094
        mov     [page_tabs+ecx*4], ebx
1095
.ret:
4434 Serge 1096
        mov     ecx, [current_process]
1097
        lea     ecx, [ecx+PROC.heap_lock]
1098
        call    mutex_unlock
4429 Serge 1099
        pop     eax edx ecx
1100
        ret
4434 Serge 1101
 
4429 Serge 1102
.realloc_add:
1103
; get some additional memory
4432 Serge 1104
        mov     eax, [current_process]
4430 Serge 1105
        mov     eax, [eax+PROC.heap_top]
4429 Serge 1106
        shr     eax, 12
1107
        cmp     edx, eax
1108
        jae     .cant_inplace
1109
        mov     eax, [page_tabs+edx*4]
1110
        test    al, FREE_BLOCK
1111
        jz      .cant_inplace
1112
        shr     eax, 12
1113
        add     eax, edx
1114
        sub     eax, ebx
1115
        jb      .cant_inplace
1116
        jz      @f
1117
        shl     eax, 12
1118
        or      al, FREE_BLOCK
1119
        mov     [page_tabs+ebx*4], eax
1120
@@:
1121
        mov     eax, ebx
1122
        sub     eax, ecx
1123
        shl     eax, 12
1124
        or      al, USED_BLOCK
1125
        mov     [page_tabs+ecx*4], eax
1126
        lea     eax, [ecx+1]
1127
        shl     eax, 12
1128
        push    eax
1129
        push    edi
1130
        lea     edi, [page_tabs+edx*4]
1131
        mov     eax, 2
1132
        sub     ebx, edx
1133
        mov     ecx, ebx
1134
        cld
1135
        rep stosd
1136
        pop     edi
4432 Serge 1137
        mov     edx, [current_process]
4429 Serge 1138
        shl     ebx, 12
4430 Serge 1139
        add     [edx+PROC.mem_used], ebx
4434 Serge 1140
 
1141
        mov     ecx, [current_process]
1142
        lea     ecx, [ecx+PROC.heap_lock]
1143
        call    mutex_unlock
4429 Serge 1144
        pop     eax edx ecx
1145
        ret
4434 Serge 1146
 
4429 Serge 1147
.cant_inplace:
1148
        push    esi edi
4432 Serge 1149
        mov     eax, [current_process]
4430 Serge 1150
        mov     esi, [eax+PROC.heap_base]
1151
        mov     edi, [eax+PROC.heap_top]
4429 Serge 1152
        shr     esi, 12
1153
        shr     edi, 12
1154
        sub     ebx, ecx
1155
.find_place:
1156
        cmp     esi, edi
1157
        jae     .place_not_found
1158
        mov     eax, [page_tabs+esi*4]
1159
        test    al, FREE_BLOCK
1160
        jz      .next_place
1161
        shr     eax, 12
1162
        cmp     eax, ebx
1163
        jae     .place_found
1164
        add     esi, eax
1165
        jmp     .find_place
1166
.next_place:
1167
        shr     eax, 12
1168
        add     esi, eax
1169
        jmp     .find_place
1170
.place_not_found:
1171
        pop     edi esi
1172
        jmp     .ret0
1173
.place_found:
1174
        sub     eax, ebx
1175
        jz      @f
1176
        push    esi
1177
        add     esi, ebx
1178
        shl     eax, 12
1179
        or      al, FREE_BLOCK
1180
        mov     [page_tabs+esi*4], eax
1181
        pop     esi
1182
@@:
1183
        mov     eax, ebx
1184
        shl     eax, 12
1185
        or      al, USED_BLOCK
1186
        mov     [page_tabs+esi*4], eax
1187
        inc     esi
1188
        mov     eax, esi
1189
        shl     eax, 12
1190
        push    eax
1191
        mov     eax, [page_tabs+ecx*4]
1192
        and     eax, not 0xFFF
1193
        or      al, FREE_BLOCK
1194
        sub     edx, ecx
1195
        mov     [page_tabs+ecx*4], eax
1196
        inc     ecx
1197
        dec     ebx
1198
        dec     edx
1199
        jz      .no
1200
@@:
1201
        xor     eax, eax
1202
        xchg    eax, [page_tabs+ecx*4]
1203
        mov     [page_tabs+esi*4], eax
1204
        mov     eax, ecx
1205
        shl     eax, 12
1206
        invlpg  [eax]
1207
        inc     esi
1208
        inc     ecx
1209
        dec     ebx
1210
        dec     edx
1211
        jnz     @b
1212
.no:
1213
        push    ebx
4432 Serge 1214
        mov     edx, [current_process]
4429 Serge 1215
        shl     ebx, 12
4430 Serge 1216
        add     [edx+PROC.mem_used], ebx
4429 Serge 1217
        pop     ebx
1218
@@:
1219
        mov     dword [page_tabs+esi*4], 2
1220
        inc     esi
1221
        dec     ebx
1222
        jnz     @b
4434 Serge 1223
 
1224
        mov     ecx, [current_process]
1225
        lea     ecx, [ecx+PROC.heap_lock]
1226
        call    mutex_unlock
4429 Serge 1227
        pop     eax edi esi edx ecx
1228
        ret
1229
 
1230
 
1231
 
4430 Serge 1232
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
4429 Serge 1233
 
1234
 
1235
; param
1236
;  eax= shm_map object
1237
 
1238
align 4
1239
destroy_smap:
1240
 
1241
        pushfd
1242
        cli
1243
 
1244
        push    esi
1245
        push    edi
1246
 
1247
        mov     edi, eax
1248
        mov     esi, [eax+SMAP.parent]
1249
        test    esi, esi
1250
        jz      .done
1251
 
1252
        lock dec [esi+SMEM.refcount]
1253
        jnz     .done
1254
 
1255
        mov     ecx, [esi+SMEM.bk]
1256
        mov     edx, [esi+SMEM.fd]
1257
 
1258
        mov     [ecx+SMEM.fd], edx
1259
        mov     [edx+SMEM.bk], ecx
1260
 
1261
        stdcall kernel_free, [esi+SMEM.base]
1262
        mov     eax, esi
1263
        call    free
1264
.done:
1265
        mov     eax, edi
1266
        call    destroy_kernel_object
1267
 
1268
        pop     edi
1269
        pop     esi
1270
        popfd
1271
 
1272
        ret
1273
 
1274
E_NOTFOUND      equ  5
1275
E_ACCESS        equ 10
1276
E_NOMEM         equ 30
1277
E_PARAM         equ 33
1278
 
1279
SHM_READ        equ 0
1280
SHM_WRITE       equ 1
1281
 
1282
SHM_ACCESS_MASK equ 3
1283
 
1284
SHM_OPEN        equ (0 shl 2)
1285
SHM_OPEN_ALWAYS equ (1 shl 2)
1286
SHM_CREATE      equ (2 shl 2)
1287
 
1288
SHM_OPEN_MASK   equ (3 shl 2)
1289
 
1290
align 4
1291
proc shmem_open stdcall name:dword, size:dword, access:dword
1292
        locals
1293
           action         dd ?
1294
           owner_access   dd ?
1295
           mapped         dd ?
1296
        endl
1297
 
1298
        push    ebx
1299
        push    esi
1300
        push    edi
1301
 
1302
        mov     [mapped], 0
1303
        mov     [owner_access], 0
1304
 
1305
        pushfd                         ;mutex required
1306
        cli
1307
 
1308
        mov     eax, [access]
1309
        and     eax, SHM_OPEN_MASK
1310
        mov     [action], eax
1311
 
1312
        mov     ebx, [name]
1313
        test    ebx, ebx
1314
        mov     edx, E_PARAM
1315
        jz      .fail
1316
 
1317
        mov     esi, [shmem_list.fd]
1318
align 4
1319
@@:
1320
        cmp     esi, shmem_list
1321
        je      .not_found
1322
 
1323
        lea     edx, [esi+SMEM.name]; link , base, size
1324
        stdcall strncmp, edx, ebx, 32
1325
        test    eax, eax
1326
        je      .found
1327
 
1328
        mov     esi, [esi+SMEM.fd]
1329
        jmp     @B
1330
 
1331
.not_found:
1332
        mov     eax, [action]
1333
 
1334
        cmp     eax, SHM_OPEN
1335
        mov     edx, E_NOTFOUND
1336
        je      .fail
1337
 
1338
        cmp     eax, SHM_CREATE
1339
        mov     edx, E_PARAM
1340
        je      .create_shm
1341
 
1342
        cmp     eax, SHM_OPEN_ALWAYS
1343
        jne     .fail
1344
 
1345
.create_shm:
1346
 
1347
        mov     ecx, [size]
1348
        test    ecx, ecx
1349
        jz      .fail
1350
 
1351
        add     ecx, 4095
1352
        and     ecx, -4096
1353
        mov     [size], ecx
1354
 
1355
        mov     eax, sizeof.SMEM
1356
        call    malloc
1357
        test    eax, eax
1358
        mov     esi, eax
1359
        mov     edx, E_NOMEM
1360
        jz      .fail
1361
 
1362
        stdcall kernel_alloc, [size]
1363
        test    eax, eax
1364
        mov     [mapped], eax
1365
        mov     edx, E_NOMEM
1366
        jz      .cleanup
1367
 
1368
        mov     ecx, [size]
1369
        mov     edx, [access]
1370
        and     edx, SHM_ACCESS_MASK
1371
 
1372
        mov     [esi+SMEM.base], eax
1373
        mov     [esi+SMEM.size], ecx
1374
        mov     [esi+SMEM.access], edx
1375
        mov     [esi+SMEM.refcount], 0
1376
        mov     [esi+SMEM.name+28], 0
1377
 
1378
        lea     eax, [esi+SMEM.name]
1379
        stdcall strncpy, eax, [name], 31
1380
 
1381
        mov     eax, [shmem_list.fd]
1382
        mov     [esi+SMEM.bk], shmem_list
1383
        mov     [esi+SMEM.fd], eax
1384
 
1385
        mov     [eax+SMEM.bk], esi
1386
        mov     [shmem_list.fd], esi
1387
 
1388
        mov     [action], SHM_OPEN
1389
        mov     [owner_access], SHM_WRITE
1390
 
1391
.found:
1392
        mov     eax, [action]
1393
 
1394
        cmp     eax, SHM_CREATE
1395
        mov     edx, E_ACCESS
1396
        je      .exit
1397
 
1398
        cmp     eax, SHM_OPEN
1399
        mov     edx, E_PARAM
1400
        je      .create_map
1401
 
1402
        cmp     eax, SHM_OPEN_ALWAYS
1403
        jne     .fail
1404
 
1405
.create_map:
1406
 
1407
        mov     eax, [access]
1408
        and     eax, SHM_ACCESS_MASK
1409
        cmp     eax, [esi+SMEM.access]
1410
        mov     [access], eax
1411
        mov     edx, E_ACCESS
1412
        ja      .fail
1413
 
1414
        mov     ebx, [CURRENT_TASK]
1415
        shl     ebx, 5
1416
        mov     ebx, [CURRENT_TASK+ebx+4]
1417
        mov     eax, sizeof.SMAP
1418
 
1419
        call    create_kernel_object
1420
        test    eax, eax
1421
        mov     edi, eax
1422
        mov     edx, E_NOMEM
1423
        jz      .fail
1424
 
1425
        inc     [esi+SMEM.refcount]
1426
 
1427
        mov     [edi+SMAP.magic], 'SMAP'
1428
        mov     [edi+SMAP.destroy], destroy_smap
1429
        mov     [edi+SMAP.parent], esi
1430
        mov     [edi+SMAP.base], 0
1431
 
1432
        stdcall user_alloc, [esi+SMEM.size]
1433
        test    eax, eax
1434
        mov     [mapped], eax
1435
        mov     edx, E_NOMEM
1436
        jz      .cleanup2
1437
 
1438
        mov     [edi+SMAP.base], eax
1439
 
1440
        mov     ecx, [esi+SMEM.size]
1441
        mov     [size], ecx
1442
 
1443
        shr     ecx, 12
1444
        shr     eax, 10
1445
 
1446
        mov     esi, [esi+SMEM.base]
1447
        shr     esi, 10
1448
        lea     edi, [page_tabs+eax]
1449
        add     esi, page_tabs
1450
 
1451
        mov     edx, [access]
1452
        or      edx, [owner_access]
1453
        shl     edx, 1
1454
        or      edx, PG_USER+PG_SHARED
1455
@@:
1456
        lodsd
1457
        and     eax, 0xFFFFF000
1458
        or      eax, edx
1459
        stosd
1460
        loop    @B
1461
 
1462
        xor     edx, edx
1463
 
1464
        cmp     [owner_access], 0
1465
        jne     .fail
1466
.exit:
1467
        mov     edx, [size]
1468
.fail:
1469
        mov     eax, [mapped]
1470
 
1471
        popfd
1472
        pop     edi
1473
        pop     esi
1474
        pop     ebx
1475
        ret
1476
.cleanup:
1477
        mov     [size], edx
1478
        mov     eax, esi
1479
        call    free
1480
        jmp     .exit
1481
 
1482
.cleanup2:
1483
        mov     [size], edx
1484
        mov     eax, edi
1485
        call    destroy_smap
1486
        jmp     .exit
1487
endp
1488
 
1489
align 4
1490
proc shmem_close stdcall, name:dword
1491
 
1492
        mov     eax, [name]
1493
        test    eax, eax
1494
        jz      .fail
1495
 
1496
        push    esi
1497
        push    edi
1498
        pushfd
1499
        cli
1500
 
1501
        mov     esi, [current_slot]
1502
        add     esi, APP_OBJ_OFFSET
1503
.next:
1504
        mov     eax, [esi+APPOBJ.fd]
1505
        test    eax, eax
1506
        jz      @F
1507
 
1508
        cmp     eax, esi
1509
        mov     esi, eax
1510
        je      @F
1511
 
1512
        cmp     [eax+SMAP.magic], 'SMAP'
1513
        jne     .next
1514
 
1515
        mov     edi, [eax+SMAP.parent]
1516
        test    edi, edi
1517
        jz      .next
1518
 
1519
        lea     edi, [edi+SMEM.name]
1520
        stdcall strncmp, [name], edi, 32
1521
        test    eax, eax
1522
        jne     .next
1523
 
1524
        stdcall user_free, [esi+SMAP.base]
1525
 
1526
        mov     eax, esi
1527
        call    [esi+APPOBJ.destroy]
1528
@@:
1529
        popfd
1530
        pop     edi
1531
        pop     esi
1532
.fail:
1533
        ret
1534
endp