Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
164 serge 7
 
593 mikedld 8
$Revision: 5596 $
9
 
10
 
2434 Serge 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
164 serge 20
 
21
FREE_BLOCK      equ  4
22
USED_BLOCK      equ  8
546 diamond 23
DONT_FREE_BLOCK equ  10h
164 serge 24
 
25
 
26
block_next   equ MEM_BLOCK.next_block
27
block_prev   equ MEM_BLOCK.prev_block
2138 serge 28
list_fd      equ MEM_BLOCK.list.next
29
list_bk      equ MEM_BLOCK.list.prev
164 serge 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
3908 Serge 36
        dec     op
37
        cmp     op, 63
38
        jna     @f
39
        mov     op, 63
164 serge 40
@@:
41
}
42
 
2156 serge 43
align 4
44
md:
45
.add_to_used:
3908 Serge 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]
164 serge 55
 
3908 Serge 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
2156 serge 62
align 4
63
.find_used:
3908 Serge 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
2156 serge 72
 
3908 Serge 73
        lea     ebx, [mem_used_list+ecx*8]
74
        mov     esi, ebx
2156 serge 75
.next:
3908 Serge 76
        mov     esi, [esi+list_fd]
77
        cmp     esi, ebx
78
        je      .fail
2156 serge 79
 
3908 Serge 80
        cmp     eax, [esi+block_base]
81
        jne     .next
2156 serge 82
 
3908 Serge 83
        ret
2156 serge 84
.fail:
3908 Serge 85
        xor     esi, esi
86
        ret
2156 serge 87
 
88
align 4
89
.del_from_used:
3908 Serge 90
        call    .find_used
91
        test    esi, esi
92
        jz      .done
2156 serge 93
 
3908 Serge 94
        cmp     [esi+block_flags], USED_BLOCK
95
        jne     .fatal
2156 serge 96
 
3908 Serge 97
        dec     [mem_hash_cnt+ecx*4]
98
        list_del esi
2156 serge 99
.done:
3908 Serge 100
        ret
2156 serge 101
.fatal:                            ;FIXME panic here
3908 Serge 102
        xor     esi, esi
103
        ret
2156 serge 104
 
2138 serge 105
;Initial heap state
106
;
2143 serge 107
;+heap_size               terminator        USED_BLOCK
2151 serge 108
;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
2143 serge 109
;HEAP_BASE                heap_descriptors  USED_BLOCK
2138 serge 110
;
111
 
164 serge 112
align 4
113
proc init_kernel_heap
114
 
3908 Serge 115
        mov     ecx, 64
116
        mov     edi, mem_block_list
2138 serge 117
@@:
3908 Serge 118
        mov     eax, edi
119
        stosd
120
        stosd
121
        loop    @B
164 serge 122
 
3908 Serge 123
        mov     ecx, 64
124
        mov     edi, mem_used_list
2156 serge 125
@@:
3908 Serge 126
        mov     eax, edi
127
        stosd
128
        stosd
129
        loop    @B
357 serge 130
 
3908 Serge 131
        stdcall alloc_pages, dword 32
5201 serge 132
 
5565 serge 133
        or      eax, PG_SWR
5201 serge 134
        mov     ebx, HEAP_BASE
3908 Serge 135
        mov     ecx, 32
5201 serge 136
        call    commit_pages
164 serge 137
 
3908 Serge 138
        mov     edi, HEAP_BASE                     ;descriptors
2434 Serge 139
        mov     ebx, HEAP_BASE+sizeof.MEM_BLOCK      ;free space
140
        mov     ecx, HEAP_BASE+sizeof.MEM_BLOCK*2    ;terminator
164 serge 141
 
3908 Serge 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
2434 Serge 148
        mov     [edi+block_size], 4096*sizeof.MEM_BLOCK
3908 Serge 149
        mov     [edi+block_flags], USED_BLOCK
164 serge 150
 
3908 Serge 151
        mov     [ecx+block_next], eax
152
        mov     [ecx+block_prev], ebx
3500 Serge 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
164 serge 158
 
3908 Serge 159
        mov     [ebx+block_next], ecx
160
        mov     [ebx+block_prev], edi
2434 Serge 161
        mov     [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
164 serge 162
 
3908 Serge 163
        mov     ecx, [pg_data.kernel_pages]
164
        shl     ecx, 12
2434 Serge 165
        sub     ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
3908 Serge 166
        mov     [heap_size], ecx
167
        mov     [heap_free], ecx
168
        mov     [ebx+block_size], ecx
169
        mov     [ebx+block_flags], FREE_BLOCK
2138 serge 170
 
3908 Serge 171
        mov     [mem_block_mask], eax
2434 Serge 172
        mov     [mem_block_mask+4], 0x80000000
2138 serge 173
 
3908 Serge 174
        mov     ecx, mem_block_list+63*8
175
        list_add ebx, ecx
2138 serge 176
 
3908 Serge 177
        mov     ecx, 4096-3-1
2434 Serge 178
        mov     eax, HEAP_BASE+sizeof.MEM_BLOCK*4
2151 serge 179
 
2434 Serge 180
        mov     [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
2151 serge 181
@@:
2434 Serge 182
        mov     [eax-sizeof.MEM_BLOCK], eax
183
        add     eax, sizeof.MEM_BLOCK
3908 Serge 184
        loop    @B
2151 serge 185
 
2434 Serge 186
        mov     [eax-sizeof.MEM_BLOCK], dword 0
2151 serge 187
 
3908 Serge 188
        mov     ecx, heap_mutex
189
        call    mutex_init
190
        mov     [heap_blocks], 4094
191
        mov     [free_blocks], 4093
192
        ret
164 serge 193
endp
194
 
369 serge 195
; param
196
;  eax= required size
197
;
198
; retval
199
;  edi= memory block descriptor
200
;  ebx= descriptor index
201
 
164 serge 202
align 4
819 serge 203
get_small_block:
3908 Serge 204
        mov     ecx, eax
205
        shr     ecx, 12
206
        dec     ecx
207
        cmp     ecx, 63
208
        jle     .get_index
209
        mov     ecx, 63
369 serge 210
.get_index:
3908 Serge 211
        lea     esi, [mem_block_mask]
212
        xor     ebx, ebx
213
        or      edx, -1
164 serge 214
 
3908 Serge 215
        cmp     ecx, 32
216
        jb      .bit_test
164 serge 217
 
3908 Serge 218
        sub     ecx, 32
219
        add     ebx, 32
220
        add     esi, 4
164 serge 221
.bit_test:
3908 Serge 222
        shl     edx, cl
223
        and     edx, [esi]
369 serge 224
.find:
3908 Serge 225
        bsf     edi, edx
226
        jz      .high_mask
227
        add     ebx, edi
228
        lea     ecx, [mem_block_list+ebx*8]
229
        mov     edi, ecx
2138 serge 230
.next:
3908 Serge 231
        mov     edi, [edi+list_fd]
232
        cmp     edi, ecx
233
        je      .err
234
        cmp     eax, [edi+block_size]
235
        ja      .next
236
        ret
2138 serge 237
.err:
3908 Serge 238
        xor     edi, edi
239
        ret
164 serge 240
 
241
.high_mask:
3908 Serge 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
164 serge 248
 
249
 
819 serge 250
align 4
251
free_mem_block:
3908 Serge 252
        mov     ebx, [next_memblock]
253
        mov     [eax], ebx
254
        mov     [next_memblock], eax
255
        xor     ebx, ebx
357 serge 256
 
3908 Serge 257
        mov     dword [eax+4], ebx
258
        mov     dword [eax+8], ebx
259
        mov     dword [eax+12], ebx
260
        mov     dword [eax+16], ebx
2151 serge 261
;           mov dword [eax+20], 0     ;don't clear block size
3908 Serge 262
        mov     dword [eax+24], ebx
263
        mov     dword [eax+28], ebx
264
        inc     [free_blocks]
265
        ret
164 serge 266
 
267
align 4
268
proc alloc_kernel_space stdcall, size:dword
269
           local block_ind:DWORD
270
 
3908 Serge 271
        push    ebx
272
        push    esi
273
        push    edi
660 serge 274
 
3908 Serge 275
        mov     eax, [size]
276
        add     eax, 4095
277
        and     eax, not 4095
278
        mov     [size], eax
279 serge 279
 
3908 Serge 280
        cmp     eax, [heap_free]
281
        ja      .error
164 serge 282
 
4423 Serge 283
        spin_lock_irqsave heap_mutex
2138 serge 284
 
3908 Serge 285
        mov     eax, [size]
2138 serge 286
 
3908 Serge 287
        call    get_small_block ; eax
288
        test    edi, edi
289
        jz      .error_unlock
164 serge 290
 
3908 Serge 291
        cmp     [edi+block_flags], FREE_BLOCK
292
        jne     .error_unlock
164 serge 293
 
3908 Serge 294
        mov     [block_ind], ebx  ;index of allocated block
164 serge 295
 
3908 Serge 296
        mov     eax, [edi+block_size]
297
        cmp     eax, [size]
298
        je      .m_eq_size
164 serge 299
 
3908 Serge 300
        mov     esi, [next_memblock]    ;new memory block
301
        test    esi, esi
302
        jz      .error_unlock
164 serge 303
 
3908 Serge 304
        dec     [free_blocks]
305
        mov     eax, [esi]
306
        mov     [next_memblock], eax
164 serge 307
 
3908 Serge 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
2138 serge 315
 
3908 Serge 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
164 serge 322
 
3908 Serge 323
        mov     eax, [edi+block_size]
5596 serge 324
        calc_index eax
3908 Serge 325
        cmp     eax, [block_ind]
326
        je      .add_used
164 serge 327
 
5596 serge 328
        list_del edi
164 serge 329
 
3908 Serge 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
164 serge 335
@@:
3908 Serge 336
        bts     [mem_block_mask], eax
337
        lea     edx, [mem_block_list+eax*8]  ;edx= list head
5596 serge 338
        list_add edi, edx
2156 serge 339
.add_used:
357 serge 340
 
3908 Serge 341
        call    md.add_to_used
2138 serge 342
 
4423 Serge 343
        spin_unlock_irqrestore heap_mutex
3908 Serge 344
        mov     eax, [esi+block_base]
345
        pop     edi
346
        pop     esi
347
        pop     ebx
348
        ret
2156 serge 349
 
164 serge 350
.m_eq_size:
5596 serge 351
        list_del edi
3908 Serge 352
        lea     edx, [mem_block_list+ebx*8]
353
        cmp     edx, [edx]
354
        jnz     @f
355
        btr     [mem_block_mask], ebx
164 serge 356
@@:
3908 Serge 357
        mov     esi, edi
358
        jmp     .add_used
357 serge 359
 
2138 serge 360
.error_unlock:
4423 Serge 361
        spin_unlock_irqrestore heap_mutex
2138 serge 362
.error:
3908 Serge 363
        xor     eax, eax
364
        pop     edi
365
        pop     esi
366
        pop     ebx
367
        ret
164 serge 368
endp
369
 
370
align 4
321 diamond 371
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
279 serge 372
 
4423 Serge 373
        spin_lock_irqsave heap_mutex
2130 serge 374
 
3908 Serge 375
        mov     eax, [base]
164 serge 376
 
3908 Serge 377
        call    md.del_from_used
378
        test    esi, esi
379
        jz      .fail
164 serge 380
 
3908 Serge 381
        mov     eax, [esi+block_size]
382
        add     [heap_free], eax
170 serge 383
 
3908 Serge 384
        mov     edi, [esi+block_next]
385
        cmp     [edi+block_flags], FREE_BLOCK
386
        jne     .prev
164 serge 387
 
3908 Serge 388
        list_del edi
164 serge 389
 
3908 Serge 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
164 serge 395
 
3908 Serge 396
        calc_index ecx
2138 serge 397
 
3908 Serge 398
        lea     edx, [mem_block_list+ecx*8]
399
        cmp     edx, [edx]
400
        jne     @F
401
        btr     [mem_block_mask], ecx
2138 serge 402
@@:
3908 Serge 403
        mov     eax, edi
404
        call    free_mem_block
164 serge 405
.prev:
3908 Serge 406
        mov     edi, [esi+block_prev]
407
        cmp     [edi+block_flags], FREE_BLOCK
408
        jne     .insert
164 serge 409
 
3908 Serge 410
        mov     edx, [esi+block_next]
411
        mov     [edi+block_next], edx
412
        mov     [edx+block_prev], edi
2138 serge 413
 
3908 Serge 414
        mov     eax, esi
415
        call    free_mem_block
164 serge 416
 
3908 Serge 417
        mov     ecx, [edi+block_size]
418
        mov     eax, [esi+block_size]
419
        add     eax, ecx
420
        mov     [edi+block_size], eax
164 serge 421
 
3908 Serge 422
        calc_index eax                     ;new index
423
        calc_index ecx                     ;old index
424
        cmp     eax, ecx
425
        je      .m_eq
164 serge 426
 
3908 Serge 427
        push    ecx
428
        list_del edi
429
        pop     ecx
164 serge 430
 
3908 Serge 431
        lea     edx, [mem_block_list+ecx*8]
432
        cmp     edx, [edx]
433
        jne     .add_block
434
        btr     [mem_block_mask], ecx
3500 Serge 435
 
2138 serge 436
.add_block:
3908 Serge 437
        bts     [mem_block_mask], eax
438
        lea     edx, [mem_block_list+eax*8]
439
        list_add edi, edx
164 serge 440
.m_eq:
4423 Serge 441
        spin_unlock_irqrestore heap_mutex
3908 Serge 442
        xor     eax, eax
443
        not     eax
444
        ret
164 serge 445
.insert:
3908 Serge 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
164 serge 451
 
452
.fail:
4423 Serge 453
        spin_unlock_irqrestore heap_mutex
3908 Serge 454
        xor     eax, eax
455
        ret
164 serge 456
endp
457
 
458
align 4
459
proc kernel_alloc stdcall, size:dword
3908 Serge 460
        locals
461
          lin_addr    dd ?
462
          pages_count dd ?
463
        endl
164 serge 464
 
3908 Serge 465
        push    ebx
466
        push    edi
662 serge 467
 
3908 Serge 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
164 serge 477
 
3908 Serge 478
        stdcall alloc_kernel_space, eax
5201 serge 479
        mov     [lin_addr], eax
480
        mov     ebx, [pages_count]
3908 Serge 481
        test    eax, eax
482
        jz      .err
164 serge 483
 
3908 Serge 484
        mov     edx, eax
164 serge 485
 
5201 serge 486
        shr     ebx, 3
487
        jz      .tail
164 serge 488
 
5201 serge 489
        shl     ebx, 3
3908 Serge 490
        stdcall alloc_pages, ebx
5201 serge 491
        test    eax, eax
3908 Serge 492
        jz      .err
164 serge 493
 
5201 serge 494
        mov     ecx, ebx
5565 serge 495
        or      eax, PG_GLOBAL+PG_SWR
5201 serge 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
3908 Serge 503
        jz      .end
357 serge 504
@@:
3908 Serge 505
        call    alloc_page
506
        test    eax, eax
507
        jz      .err
164 serge 508
 
5565 serge 509
        stdcall map_page, edx, eax, dword (PG_GLOBAL+PG_SWR)
3908 Serge 510
        add     edx, 0x1000
5201 serge 511
        dec     ebx
3908 Serge 512
        jnz     @B
164 serge 513
.end:
3908 Serge 514
        mov     eax, [lin_addr]
515
        pop     edi
516
        pop     ebx
517
        ret
357 serge 518
.err:
3908 Serge 519
        xor     eax, eax
520
        pop     edi
521
        pop     ebx
522
        ret
164 serge 523
endp
524
 
525
align 4
526
proc kernel_free stdcall, base:dword
2156 serge 527
 
3908 Serge 528
        push    ebx esi
164 serge 529
 
4423 Serge 530
        spin_lock_irqsave heap_mutex
279 serge 531
 
3908 Serge 532
        mov     eax, [base]
533
        call    md.find_used
164 serge 534
 
3908 Serge 535
        cmp     [esi+block_flags], USED_BLOCK
536
        jne     .fail
164 serge 537
 
4423 Serge 538
        spin_unlock_irqrestore heap_mutex
279 serge 539
 
3908 Serge 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
164 serge 547
.fail:
4423 Serge 548
        spin_unlock_irqrestore heap_mutex
3908 Serge 549
        xor     eax, eax
550
        pop     esi ebx
551
        ret
164 serge 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
 
5201 serge 561
;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
164 serge 562
 
2434 Serge 563
HEAP_TOP  equ 0x80000000
188 serge 564
 
164 serge 565
align 4
188 serge 566
proc init_heap
164 serge 567
 
5201 serge 568
        mov     ebx, [current_process]
569
        mov     eax, [ebx+PROC.heap_top]
3908 Serge 570
        test    eax, eax
571
        jz      @F
5201 serge 572
        sub     eax, [ebx+PROC.heap_base]
573
        sub     eax, PAGE_SIZE
3908 Serge 574
        ret
172 serge 575
@@:
5201 serge 576
        lea     ecx, [ebx+PROC.heap_lock]
577
        call    mutex_init
578
 
579
        mov     esi, [ebx+PROC.mem_used]
3908 Serge 580
        add     esi, 4095
581
        and     esi, not 4095
5201 serge 582
        mov     [ebx+PROC.mem_used], esi
3908 Serge 583
        mov     eax, HEAP_TOP
5201 serge 584
        mov     [ebx+PROC.heap_base], esi
585
        mov     [ebx+PROC.heap_top], eax
164 serge 586
 
3908 Serge 587
        sub     eax, esi
588
        shr     esi, 10
589
        mov     ecx, eax
5201 serge 590
        sub     eax, PAGE_SIZE
3908 Serge 591
        or      ecx, FREE_BLOCK
592
        mov     [page_tabs+esi], ecx
593
        ret
164 serge 594
endp
595
 
596
align 4
597
proc user_alloc stdcall, alloc_size:dword
598
 
3908 Serge 599
        push    ebx
600
        push    esi
601
        push    edi
662 serge 602
 
5201 serge 603
        mov     ebx, [current_process]
604
        lea     ecx, [ebx+PROC.heap_lock]
605
        call    mutex_lock
606
 
3908 Serge 607
        mov     ecx, [alloc_size]
5201 serge 608
        add     ecx, (4095+PAGE_SIZE)
3908 Serge 609
        and     ecx, not 4095
164 serge 610
 
5201 serge 611
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
612
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
613
.scan:
3908 Serge 614
        cmp     esi, edi
5201 serge 615
        jae     .m_exit
164 serge 616
 
3908 Serge 617
        mov     ebx, esi
618
        shr     ebx, 12
619
        mov     eax, [page_tabs+ebx*4]
620
        test    al, FREE_BLOCK
5201 serge 621
        jz      .test_used
3908 Serge 622
        and     eax, 0xFFFFF000
623
        cmp     eax, ecx   ;alloc_size
5201 serge 624
        jb      .m_next
3908 Serge 625
        jz      @f
164 serge 626
 
3908 Serge 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
294 diamond 632
@@:
3908 Serge 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
164 serge 639
@@:
3908 Serge 640
        mov     dword [page_tabs+ebx*4], 2
641
        inc     ebx
642
        dec     ecx
643
        jnz     @B
620 diamond 644
.no:
164 serge 645
 
5201 serge 646
        mov     edx, [current_process]
3908 Serge 647
        mov     ebx, [alloc_size]
648
        add     ebx, 0xFFF
649
        and     ebx, not 0xFFF
5201 serge 650
        add     [edx+PROC.mem_used], ebx
294 diamond 651
 
5201 serge 652
        lea     ecx, [edx+PROC.heap_lock]
653
        call    mutex_unlock
654
 
3908 Serge 655
        lea     eax, [esi+4096]
662 serge 656
 
3908 Serge 657
        pop     edi
658
        pop     esi
659
        pop     ebx
660
        ret
5201 serge 661
.test_used:
3908 Serge 662
        test    al, USED_BLOCK
5201 serge 663
        jz      .m_exit
164 serge 664
 
3908 Serge 665
        and     eax, 0xFFFFF000
5201 serge 666
.m_next:
3908 Serge 667
        add     esi, eax
5201 serge 668
        jmp     .scan
669
.m_exit:
670
        mov     ecx, [current_process]
671
        lea     ecx, [ecx+PROC.heap_lock]
672
        call    mutex_unlock
673
 
3908 Serge 674
        xor     eax, eax
675
        pop     edi
676
        pop     esi
677
        pop     ebx
678
        ret
164 serge 679
endp
680
 
681
align 4
1289 diamond 682
proc user_alloc_at stdcall, address:dword, alloc_size:dword
683
 
3908 Serge 684
        push    ebx
685
        push    esi
686
        push    edi
1289 diamond 687
 
5201 serge 688
        mov     ebx, [current_process]
689
        lea     ecx, [ebx+PROC.heap_lock]
690
        call    mutex_lock
691
 
3908 Serge 692
        mov     edx, [address]
693
        and     edx, not 0xFFF
694
        mov     [address], edx
695
        sub     edx, 0x1000
696
        jb      .error
5201 serge 697
        mov     esi, [ebx+PROC.heap_base]
698
        mov     edi, [ebx+PROC.heap_top]
3908 Serge 699
        cmp     edx, esi
700
        jb      .error
1289 diamond 701
.scan:
3908 Serge 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
1289 diamond 714
.error:
5201 serge 715
        mov     ecx, [current_process]
716
        lea     ecx, [ecx+PROC.heap_lock]
717
        call    mutex_unlock
718
 
3908 Serge 719
        xor     eax, eax
720
        pop     edi
721
        pop     esi
722
        pop     ebx
723
        ret
1289 diamond 724
.found:
3908 Serge 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
1289 diamond 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.
3908 Serge 739
        mov     eax, edx
740
        sub     eax, esi
741
        jz      .nofirst
742
        or      al, FREE_BLOCK
743
        mov     [page_tabs+ebx*4], eax
1289 diamond 744
.nofirst:
3908 Serge 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
1289 diamond 757
.fill:
3908 Serge 758
        mov     dword [page_tabs+ebx*4], 2
759
        inc     ebx
760
        dec     eax
761
        jnz     .fill
3500 Serge 762
 
1289 diamond 763
.second_nofill:
3908 Serge 764
        sub     ecx, edx
765
        jz      .nothird
766
        or      cl, FREE_BLOCK
767
        mov     [page_tabs+ebx*4], ecx
3500 Serge 768
 
1289 diamond 769
.nothird:
5201 serge 770
        mov     edx, [current_process]
3908 Serge 771
        mov     ebx, [alloc_size]
772
        add     ebx, 0xFFF
773
        and     ebx, not 0xFFF
5201 serge 774
        add     [edx+PROC.mem_used], ebx
1289 diamond 775
 
5201 serge 776
        lea     ecx, [edx+PROC.heap_lock]
777
        call    mutex_unlock
778
 
3908 Serge 779
        mov     eax, [address]
1289 diamond 780
 
3908 Serge 781
        pop     edi
782
        pop     esi
783
        pop     ebx
784
        ret
1289 diamond 785
endp
786
 
787
align 4
164 serge 788
proc user_free stdcall, base:dword
789
 
3908 Serge 790
        push    esi
662 serge 791
 
3908 Serge 792
        mov     esi, [base]
793
        test    esi, esi
5201 serge 794
        jz      .fail
164 serge 795
 
3908 Serge 796
        push    ebx
662 serge 797
 
5201 serge 798
        mov     ebx, [current_process]
799
        lea     ecx, [ebx+PROC.heap_lock]
800
        call    mutex_lock
801
 
3908 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
164 serge 809
 
3908 Serge 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
164 serge 818
.release:
3908 Serge 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]
188 serge 829
@@:
3908 Serge 830
        inc     esi
831
        dec     ecx
832
        jnz     .release
3500 Serge 833
 
620 diamond 834
.released:
3908 Serge 835
        push    edi
662 serge 836
 
5201 serge 837
        mov     edx, [current_process]
838
        lea     ecx, [edx+PROC.heap_lock]
839
        mov     esi, dword [edx+PROC.heap_base]
840
        mov     edi, dword [edx+PROC.heap_top]
841
        sub     ebx, [edx+PROC.mem_used]
3908 Serge 842
        neg     ebx
5201 serge 843
        mov     [edx+PROC.mem_used], ebx
3908 Serge 844
        call    user_normalize
845
        pop     edi
448 diamond 846
.exit:
5201 serge 847
        call    mutex_unlock
848
 
3908 Serge 849
        xor     eax, eax
850
        inc     eax
5201 serge 851
        pop     ebx
3908 Serge 852
        pop     esi
853
        ret
5201 serge 854
 
546 diamond 855
.cantfree:
5201 serge 856
        mov     ecx, [current_process]
857
        lea     ecx, [ecx+PROC.heap_lock]
858
        jmp     .exit
859
.fail:
3908 Serge 860
        xor     eax, eax
861
        pop     esi
862
        ret
448 diamond 863
endp
864
 
2434 Serge 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 ?
3908 Serge 903
        add     ebx, [base]
2434 Serge 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
3908 Serge 911
        mov     [edx], dword 2
2434 Serge 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
448 diamond 931
user_normalize:
932
; in: esi=heap_base, edi=heap_top
933
; out: eax=0 <=> OK
934
; destroys: ebx,edx,esi,edi
3908 Serge 935
        shr     esi, 12
936
        shr     edi, 12
164 serge 937
@@:
3908 Serge 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
164 serge 944
.test_free:
3908 Serge 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
164 serge 952
 
3908 Serge 953
        mov     ebx, [page_tabs+edx*4]
954
        test    bl, USED_BLOCK
955
        jz      .next_free
164 serge 956
 
3908 Serge 957
        shr     ebx, 12
958
        add     edx, ebx
959
        mov     esi, edx
960
        jmp     @B
164 serge 961
.next_free:
3908 Serge 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
164 serge 970
.exit:
3908 Serge 971
        xor     eax, eax
972
        inc     eax
973
        ret
164 serge 974
.err:
3908 Serge 975
        xor     eax, eax
976
        ret
164 serge 977
 
448 diamond 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
5201 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
 
465 serge 996
        lea     ecx, [eax - 0x1000]
448 diamond 997
        shr     ecx, 12
998
        mov     edx, [page_tabs+ecx*4]
620 diamond 999
        test    dl, USED_BLOCK
448 diamond 1000
        jnz     @f
1001
; attempt to realloc invalid pointer
1002
.ret0:
5201 serge 1003
        mov     ecx, [current_process]
1004
        lea     ecx, [ecx+PROC.heap_lock]
1005
        call    mutex_unlock
1006
 
448 diamond 1007
        pop     edx ecx
1008
        xor     eax, eax
1009
        ret
1010
@@:
620 diamond 1011
        test    dl, DONT_FREE_BLOCK
546 diamond 1012
        jnz     .ret0
448 diamond 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
5201 serge 1041
        mov     edx, [current_process]
1042
        mov     ebx, [edx+PROC.mem_used]
448 diamond 1043
        sub     ebx, eax
1044
        add     ebx, 0x1000
1045
        or      al, FREE_BLOCK
1046
        mov     [page_tabs+ecx*4], eax
1047
        push    esi edi
5201 serge 1048
        mov     esi, [edx+PROC.heap_base]
1049
        mov     edi, [edx+PROC.heap_top]
1050
        mov     [edx+PROC.mem_used], ebx
448 diamond 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
5201 serge 1062
        mov     edx, [current_process]
448 diamond 1063
        shl     ebx, 12
5201 serge 1064
        sub     ebx, [edx+PROC.mem_used]
448 diamond 1065
        neg     ebx
5201 serge 1066
        mov     [edx+PROC.mem_used], ebx
448 diamond 1067
        pop     edx ecx ebx
465 serge 1068
        lea     eax, [ecx+1]
448 diamond 1069
        shl     eax, 12
1070
        push    eax
823 diamond 1071
        add     ecx, edx
1072
        lea     edx, [ecx+ebx]
448 diamond 1073
        shl     ebx, 12
1074
        jz      .ret
1075
        push    esi
5201 serge 1076
        mov     esi, [current_process]
1077
        mov     esi, [esi+PROC.heap_top]
448 diamond 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
823 diamond 1084
        jnz     .merge_done
448 diamond 1085
        and     dword [page_tabs+edx*4], 0
823 diamond 1086
        shr     eax, 12
1087
        add     edx, eax
1088
        shl     eax, 12
448 diamond 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:
5201 serge 1096
        mov     ecx, [current_process]
1097
        lea     ecx, [ecx+PROC.heap_lock]
1098
        call    mutex_unlock
448 diamond 1099
        pop     eax edx ecx
1100
        ret
5201 serge 1101
 
448 diamond 1102
.realloc_add:
1103
; get some additional memory
5201 serge 1104
        mov     eax, [current_process]
1105
        mov     eax, [eax+PROC.heap_top]
448 diamond 1106
        shr     eax, 12
1107
        cmp     edx, eax
1108
        jae     .cant_inplace
1109
        mov     eax, [page_tabs+edx*4]
620 diamond 1110
        test    al, FREE_BLOCK
1111
        jz      .cant_inplace
448 diamond 1112
        shr     eax, 12
1113
        add     eax, edx
620 diamond 1114
        sub     eax, ebx
448 diamond 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
465 serge 1126
        lea     eax, [ecx+1]
448 diamond 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
3908 Serge 1135
        rep stosd
448 diamond 1136
        pop     edi
5201 serge 1137
        mov     edx, [current_process]
448 diamond 1138
        shl     ebx, 12
5201 serge 1139
        add     [edx+PROC.mem_used], ebx
1140
 
1141
        mov     ecx, [current_process]
1142
        lea     ecx, [ecx+PROC.heap_lock]
1143
        call    mutex_unlock
448 diamond 1144
        pop     eax edx ecx
1145
        ret
5201 serge 1146
 
448 diamond 1147
.cant_inplace:
1148
        push    esi edi
5201 serge 1149
        mov     eax, [current_process]
1150
        mov     esi, [eax+PROC.heap_base]
1151
        mov     edi, [eax+PROC.heap_top]
448 diamond 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
620 diamond 1177
        add     esi, ebx
448 diamond 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
620 diamond 1197
        dec     ebx
1198
        dec     edx
1199
        jz      .no
448 diamond 1200
@@:
1201
        xor     eax, eax
1202
        xchg    eax, [page_tabs+ecx*4]
1203
        mov     [page_tabs+esi*4], eax
940 serge 1204
        mov     eax, ecx
1205
        shl     eax, 12
1206
        invlpg  [eax]
620 diamond 1207
        inc     esi
448 diamond 1208
        inc     ecx
1209
        dec     ebx
1210
        dec     edx
1211
        jnz     @b
620 diamond 1212
.no:
448 diamond 1213
        push    ebx
5201 serge 1214
        mov     edx, [current_process]
448 diamond 1215
        shl     ebx, 12
5201 serge 1216
        add     [edx+PROC.mem_used], ebx
448 diamond 1217
        pop     ebx
1218
@@:
1219
        mov     dword [page_tabs+esi*4], 2
1220
        inc     esi
1221
        dec     ebx
1222
        jnz     @b
5201 serge 1223
 
1224
        mov     ecx, [current_process]
1225
        lea     ecx, [ecx+PROC.heap_lock]
1226
        call    mutex_unlock
448 diamond 1227
        pop     eax edi esi edx ecx
1228
        ret
1229
 
164 serge 1230
 
278 serge 1231
 
5201 serge 1232
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
940 serge 1233
 
1234
 
1235
; param
1236
;  eax= shm_map object
1237
 
1238
align 4
1239
destroy_smap:
1240
 
3908 Serge 1241
        pushfd
1242
        cli
940 serge 1243
 
3908 Serge 1244
        push    esi
1245
        push    edi
940 serge 1246
 
3908 Serge 1247
        mov     edi, eax
1248
        mov     esi, [eax+SMAP.parent]
1249
        test    esi, esi
1250
        jz      .done
940 serge 1251
 
3908 Serge 1252
        lock dec [esi+SMEM.refcount]
1253
        jnz     .done
940 serge 1254
 
3908 Serge 1255
        mov     ecx, [esi+SMEM.bk]
1256
        mov     edx, [esi+SMEM.fd]
945 serge 1257
 
3908 Serge 1258
        mov     [ecx+SMEM.fd], edx
1259
        mov     [edx+SMEM.bk], ecx
945 serge 1260
 
3908 Serge 1261
        stdcall kernel_free, [esi+SMEM.base]
1262
        mov     eax, esi
1263
        call    free
945 serge 1264
.done:
3908 Serge 1265
        mov     eax, edi
1266
        call    destroy_kernel_object
940 serge 1267
 
3908 Serge 1268
        pop     edi
1269
        pop     esi
1270
        popfd
940 serge 1271
 
3908 Serge 1272
        ret
940 serge 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
3908 Serge 1292
        locals
1293
           action         dd ?
1294
           owner_access   dd ?
1295
           mapped         dd ?
1296
        endl
940 serge 1297
 
3908 Serge 1298
        push    ebx
1299
        push    esi
1300
        push    edi
940 serge 1301
 
3908 Serge 1302
        mov     [mapped], 0
1303
        mov     [owner_access], 0
940 serge 1304
 
3908 Serge 1305
        pushfd                         ;mutex required
1306
        cli
940 serge 1307
 
3908 Serge 1308
        mov     eax, [access]
1309
        and     eax, SHM_OPEN_MASK
1310
        mov     [action], eax
940 serge 1311
 
3908 Serge 1312
        mov     ebx, [name]
1313
        test    ebx, ebx
1314
        mov     edx, E_PARAM
1315
        jz      .fail
940 serge 1316
 
3908 Serge 1317
        mov     esi, [shmem_list.fd]
940 serge 1318
align 4
1319
@@:
3908 Serge 1320
        cmp     esi, shmem_list
1321
        je      .not_found
940 serge 1322
 
2434 Serge 1323
        lea     edx, [esi+SMEM.name]; link , base, size
3908 Serge 1324
        stdcall strncmp, edx, ebx, 32
1325
        test    eax, eax
1326
        je      .found
940 serge 1327
 
3908 Serge 1328
        mov     esi, [esi+SMEM.fd]
1329
        jmp     @B
940 serge 1330
 
1331
.not_found:
3908 Serge 1332
        mov     eax, [action]
940 serge 1333
 
3908 Serge 1334
        cmp     eax, SHM_OPEN
1335
        mov     edx, E_NOTFOUND
1336
        je      .fail
940 serge 1337
 
3908 Serge 1338
        cmp     eax, SHM_CREATE
1339
        mov     edx, E_PARAM
1340
        je      .create_shm
940 serge 1341
 
3908 Serge 1342
        cmp     eax, SHM_OPEN_ALWAYS
1343
        jne     .fail
940 serge 1344
 
1345
.create_shm:
1346
 
3908 Serge 1347
        mov     ecx, [size]
1348
        test    ecx, ecx
1349
        jz      .fail
940 serge 1350
 
3908 Serge 1351
        add     ecx, 4095
1352
        and     ecx, -4096
1353
        mov     [size], ecx
940 serge 1354
 
2434 Serge 1355
        mov     eax, sizeof.SMEM
3908 Serge 1356
        call    malloc
1357
        test    eax, eax
1358
        mov     esi, eax
1359
        mov     edx, E_NOMEM
1360
        jz      .fail
940 serge 1361
 
3908 Serge 1362
        stdcall kernel_alloc, [size]
1363
        test    eax, eax
1364
        mov     [mapped], eax
1365
        mov     edx, E_NOMEM
1366
        jz      .cleanup
940 serge 1367
 
3908 Serge 1368
        mov     ecx, [size]
1369
        mov     edx, [access]
1370
        and     edx, SHM_ACCESS_MASK
940 serge 1371
 
3908 Serge 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
940 serge 1377
 
3908 Serge 1378
        lea     eax, [esi+SMEM.name]
1379
        stdcall strncpy, eax, [name], 31
940 serge 1380
 
3908 Serge 1381
        mov     eax, [shmem_list.fd]
1382
        mov     [esi+SMEM.bk], shmem_list
1383
        mov     [esi+SMEM.fd], eax
940 serge 1384
 
3908 Serge 1385
        mov     [eax+SMEM.bk], esi
1386
        mov     [shmem_list.fd], esi
940 serge 1387
 
3908 Serge 1388
        mov     [action], SHM_OPEN
1389
        mov     [owner_access], SHM_WRITE
940 serge 1390
 
1391
.found:
3908 Serge 1392
        mov     eax, [action]
940 serge 1393
 
3908 Serge 1394
        cmp     eax, SHM_CREATE
1395
        mov     edx, E_ACCESS
1396
        je      .exit
940 serge 1397
 
3908 Serge 1398
        cmp     eax, SHM_OPEN
1399
        mov     edx, E_PARAM
1400
        je      .create_map
940 serge 1401
 
3908 Serge 1402
        cmp     eax, SHM_OPEN_ALWAYS
1403
        jne     .fail
940 serge 1404
 
1405
.create_map:
1406
 
3908 Serge 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
940 serge 1413
 
3908 Serge 1414
        mov     ebx, [CURRENT_TASK]
1415
        shl     ebx, 5
1416
        mov     ebx, [CURRENT_TASK+ebx+4]
2434 Serge 1417
        mov     eax, sizeof.SMAP
940 serge 1418
 
3908 Serge 1419
        call    create_kernel_object
1420
        test    eax, eax
1421
        mov     edi, eax
1422
        mov     edx, E_NOMEM
1423
        jz      .fail
940 serge 1424
 
3908 Serge 1425
        inc     [esi+SMEM.refcount]
1213 serge 1426
 
3908 Serge 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
940 serge 1431
 
3908 Serge 1432
        stdcall user_alloc, [esi+SMEM.size]
1433
        test    eax, eax
1434
        mov     [mapped], eax
1435
        mov     edx, E_NOMEM
1436
        jz      .cleanup2
940 serge 1437
 
3908 Serge 1438
        mov     [edi+SMAP.base], eax
940 serge 1439
 
3908 Serge 1440
        mov     ecx, [esi+SMEM.size]
1441
        mov     [size], ecx
940 serge 1442
 
3908 Serge 1443
        shr     ecx, 12
1444
        shr     eax, 10
940 serge 1445
 
3908 Serge 1446
        mov     esi, [esi+SMEM.base]
1447
        shr     esi, 10
1448
        lea     edi, [page_tabs+eax]
1449
        add     esi, page_tabs
940 serge 1450
 
3908 Serge 1451
        mov     edx, [access]
1452
        or      edx, [owner_access]
1453
        shl     edx, 1
5565 serge 1454
        or      edx, PG_SHARED+PG_UR
940 serge 1455
@@:
3908 Serge 1456
        lodsd
1457
        and     eax, 0xFFFFF000
1458
        or      eax, edx
1459
        stosd
1460
        loop    @B
940 serge 1461
 
3908 Serge 1462
        xor     edx, edx
940 serge 1463
 
3908 Serge 1464
        cmp     [owner_access], 0
1465
        jne     .fail
1213 serge 1466
.exit:
3908 Serge 1467
        mov     edx, [size]
1213 serge 1468
.fail:
3908 Serge 1469
        mov     eax, [mapped]
940 serge 1470
 
3908 Serge 1471
        popfd
1472
        pop     edi
1473
        pop     esi
1474
        pop     ebx
1475
        ret
940 serge 1476
.cleanup:
3908 Serge 1477
        mov     [size], edx
1478
        mov     eax, esi
1479
        call    free
1480
        jmp     .exit
940 serge 1481
 
1482
.cleanup2:
3908 Serge 1483
        mov     [size], edx
1484
        mov     eax, edi
1485
        call    destroy_smap
1486
        jmp     .exit
940 serge 1487
endp
943 serge 1488
 
1489
align 4
1490
proc shmem_close stdcall, name:dword
1491
 
3908 Serge 1492
        mov     eax, [name]
1493
        test    eax, eax
1494
        jz      .fail
943 serge 1495
 
3908 Serge 1496
        push    esi
1497
        push    edi
1498
        pushfd
1499
        cli
943 serge 1500
 
3908 Serge 1501
        mov     esi, [current_slot]
1502
        add     esi, APP_OBJ_OFFSET
943 serge 1503
.next:
3908 Serge 1504
        mov     eax, [esi+APPOBJ.fd]
1505
        test    eax, eax
1506
        jz      @F
943 serge 1507
 
3908 Serge 1508
        cmp     eax, esi
1509
        mov     esi, eax
1510
        je      @F
943 serge 1511
 
3908 Serge 1512
        cmp     [eax+SMAP.magic], 'SMAP'
1513
        jne     .next
943 serge 1514
 
3908 Serge 1515
        mov     edi, [eax+SMAP.parent]
1516
        test    edi, edi
1517
        jz      .next
943 serge 1518
 
3908 Serge 1519
        lea     edi, [edi+SMEM.name]
1520
        stdcall strncmp, [name], edi, 32
1521
        test    eax, eax
1522
        jne     .next
943 serge 1523
 
3908 Serge 1524
        stdcall user_free, [esi+SMAP.base]
945 serge 1525
 
2434 Serge 1526
        mov     eax, esi
3908 Serge 1527
        call    [esi+APPOBJ.destroy]
943 serge 1528
@@:
3908 Serge 1529
        popfd
1530
        pop     edi
1531
        pop     esi
943 serge 1532
.fail:
3908 Serge 1533
        ret
943 serge 1534
endp