Subversion Repositories Kolibri OS

Rev

Rev 9047 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
7965 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 9048 $
9
 
10
 
2384 hidnplayr 11
struct  MEM_BLOCK
12
        list            LHEAD
13
        next_block      dd ? ;+8
14
        prev_block      dd ? ;+4
15
        base            dd ? ;+16
16
        size            dd ? ;+20
17
        flags           dd ? ;+24
18
        handle          dd ? ;+28
19
ends
2288 clevermous 20
 
7965 hidnplayr 21
MEM_BLOCK_RESERVED  = 0x02      ; Will be allocated on first access (lazy allocation)
22
MEM_BLOCK_FREE      = 0x04
23
MEM_BLOCK_USED      = 0x08
24
MEM_BLOCK_DONT_FREE = 0x10
2288 clevermous 25
 
9048 Boppan 26
LAZY_ALLOC_PAGE = 2
27
LAZY_ALLOC_UNREADABLE = 20h
28
LAZY_ALLOC_UNWRITABLE = 40h
29
 
2288 clevermous 30
macro calc_index op
9048 Boppan 31
{
32
        shr     op, 12
2288 clevermous 33
        dec     op
34
        cmp     op, 63
35
        jna     @f
36
        mov     op, 63
37
@@:
38
}
39
 
40
align 4
41
md:
42
.add_to_used:
7965 hidnplayr 43
        mov     eax, [esi + MEM_BLOCK.base]
44
        mov     ebx, [esi + MEM_BLOCK.base]
2288 clevermous 45
        shr     ebx, 6
46
        add     eax, ebx
47
        shr     ebx, 6
48
        add     eax, ebx
49
        shr     eax, 12
50
        and     eax, 63
7965 hidnplayr 51
        inc     [mem_hash_cnt + eax*4]
2288 clevermous 52
 
7965 hidnplayr 53
        lea     ecx, [mem_used_list + eax*8]
3246 Serge 54
        list_add esi, ecx
7965 hidnplayr 55
        mov     [esi + MEM_BLOCK.flags], MEM_BLOCK_USED
56
        mov     eax, [esi + MEM_BLOCK.size]
2288 clevermous 57
        sub     [heap_free], eax
58
        ret
59
align 4
60
.find_used:
61
        mov     ecx, eax
62
        mov     ebx, eax
63
        shr     ebx, 6
64
        add     ecx, ebx
65
        shr     ebx, 6
66
        add     ecx, ebx
67
        shr     ecx, 12
68
        and     ecx, 63
69
 
7965 hidnplayr 70
        lea     ebx, [mem_used_list + ecx*8]
2288 clevermous 71
        mov     esi, ebx
72
.next:
7965 hidnplayr 73
        mov     esi, [esi + MEM_BLOCK.list.next]
2288 clevermous 74
        cmp     esi, ebx
75
        je      .fail
76
 
7965 hidnplayr 77
        cmp     eax, [esi + MEM_BLOCK.base]
2288 clevermous 78
        jne     .next
79
 
80
        ret
81
.fail:
82
        xor     esi, esi
83
        ret
84
 
85
align 4
86
.del_from_used:
87
        call    .find_used
88
        test    esi, esi
89
        jz      .done
90
 
7965 hidnplayr 91
        cmp     [esi + MEM_BLOCK.flags], MEM_BLOCK_USED
2288 clevermous 92
        jne     .fatal
93
 
7965 hidnplayr 94
        dec     [mem_hash_cnt + ecx*4]
3246 Serge 95
        list_del esi
2288 clevermous 96
.done:
97
        ret
98
.fatal:                            ;FIXME panic here
99
        xor     esi, esi
100
        ret
101
 
102
;Initial heap state
103
;
7965 hidnplayr 104
; + heap_size               terminator        MEM_BLOCK_USED
105
; + 4096*MEM_BLOCK.sizeof   free space        MEM_BLOCK_FREE
106
;HEAP_BASE                heap_descriptors  MEM_BLOCK_USED
2288 clevermous 107
;
108
 
109
align 4
110
proc init_kernel_heap
111
 
112
        mov     ecx, 64
113
        mov     edi, mem_block_list
7965 hidnplayr 114
  @@:
2288 clevermous 115
        mov     eax, edi
116
        stosd
117
        stosd
118
        loop    @B
119
 
120
        mov     ecx, 64
121
        mov     edi, mem_used_list
7965 hidnplayr 122
  @@:
2288 clevermous 123
        mov     eax, edi
124
        stosd
125
        stosd
126
        loop    @B
127
 
128
        stdcall alloc_pages, dword 32
4424 Serge 129
 
5356 serge 130
        or      eax, PG_SWR
4424 Serge 131
        mov     ebx, HEAP_BASE
2288 clevermous 132
        mov     ecx, 32
4424 Serge 133
        call    commit_pages
2288 clevermous 134
 
135
        mov     edi, HEAP_BASE                     ;descriptors
7965 hidnplayr 136
        mov     ebx, HEAP_BASE + sizeof.MEM_BLOCK      ;free space
137
        mov     ecx, HEAP_BASE + sizeof.MEM_BLOCK*2    ;terminator
2288 clevermous 138
 
139
        xor     eax, eax
7965 hidnplayr 140
        mov     [edi + MEM_BLOCK.next_block], ebx
141
        mov     [edi + MEM_BLOCK.prev_block], eax
142
        mov     [edi + MEM_BLOCK.list.next], eax
143
        mov     [edi + MEM_BLOCK.list.prev], eax
144
        mov     [edi + MEM_BLOCK.base], HEAP_BASE
145
        mov     [edi + MEM_BLOCK.size], 4096*sizeof.MEM_BLOCK
146
        mov     [edi + MEM_BLOCK.flags], MEM_BLOCK_USED
2288 clevermous 147
 
7965 hidnplayr 148
        mov     [ecx + MEM_BLOCK.next_block], eax
149
        mov     [ecx + MEM_BLOCK.prev_block], ebx
150
        mov     [ecx + MEM_BLOCK.list.next], eax
151
        mov     [ecx + MEM_BLOCK.list.prev], eax
152
        mov     [ecx + MEM_BLOCK.base], eax
153
        mov     [ecx + MEM_BLOCK.size], eax
154
        mov     [ecx + MEM_BLOCK.flags], MEM_BLOCK_USED
2288 clevermous 155
 
7965 hidnplayr 156
        mov     [ebx + MEM_BLOCK.next_block], ecx
157
        mov     [ebx + MEM_BLOCK.prev_block], edi
158
        mov     [ebx + MEM_BLOCK.base], HEAP_BASE + 4096*sizeof.MEM_BLOCK
2288 clevermous 159
 
160
        mov     ecx, [pg_data.kernel_pages]
161
        shl     ecx, 12
7965 hidnplayr 162
        sub     ecx, HEAP_BASE-OS_BASE + 4096*sizeof.MEM_BLOCK
2288 clevermous 163
        mov     [heap_size], ecx
164
        mov     [heap_free], ecx
7965 hidnplayr 165
        mov     [ebx + MEM_BLOCK.size], ecx
166
        mov     [ebx + MEM_BLOCK.flags], MEM_BLOCK_FREE
2288 clevermous 167
 
168
        mov     [mem_block_mask], eax
7965 hidnplayr 169
        mov     [mem_block_mask + 4], 0x80000000
2288 clevermous 170
 
7965 hidnplayr 171
        mov     ecx, mem_block_list + 63*8
3246 Serge 172
        list_add ebx, ecx
2288 clevermous 173
 
174
        mov     ecx, 4096-3-1
7965 hidnplayr 175
        mov     eax, HEAP_BASE + sizeof.MEM_BLOCK*4
2288 clevermous 176
 
7965 hidnplayr 177
        mov     [next_memblock], HEAP_BASE + sizeof.MEM_BLOCK *3
178
 @@:
2384 hidnplayr 179
        mov     [eax-sizeof.MEM_BLOCK], eax
180
        add     eax, sizeof.MEM_BLOCK
2288 clevermous 181
        loop    @B
182
 
7965 hidnplayr 183
        mov     dword[eax-sizeof.MEM_BLOCK], 0
2288 clevermous 184
 
185
        mov     ecx, heap_mutex
186
        call    mutex_init
187
        mov     [heap_blocks], 4094
188
        mov     [free_blocks], 4093
189
        ret
190
endp
191
 
192
; param
193
;  eax= required size
194
;
195
; retval
196
;  edi= memory block descriptor
197
;  ebx= descriptor index
198
 
199
align 4
200
get_small_block:
201
        mov     ecx, eax
202
        shr     ecx, 12
203
        dec     ecx
204
        cmp     ecx, 63
205
        jle     .get_index
206
        mov     ecx, 63
7965 hidnplayr 207
  .get_index:
2288 clevermous 208
        lea     esi, [mem_block_mask]
209
        xor     ebx, ebx
210
        or      edx, -1
211
 
212
        cmp     ecx, 32
213
        jb      .bit_test
214
 
215
        sub     ecx, 32
216
        add     ebx, 32
217
        add     esi, 4
7965 hidnplayr 218
  .bit_test:
2288 clevermous 219
        shl     edx, cl
220
        and     edx, [esi]
7965 hidnplayr 221
  .find:
2288 clevermous 222
        bsf     edi, edx
223
        jz      .high_mask
224
        add     ebx, edi
7965 hidnplayr 225
        lea     ecx, [mem_block_list + ebx*8]
2288 clevermous 226
        mov     edi, ecx
7965 hidnplayr 227
  .next:
228
        mov     edi, [edi + MEM_BLOCK.list.next]
2288 clevermous 229
        cmp     edi, ecx
230
        je      .err
7965 hidnplayr 231
        cmp     eax, [edi + MEM_BLOCK.size]
2288 clevermous 232
        ja      .next
233
        ret
7965 hidnplayr 234
  .err:
2288 clevermous 235
        xor     edi, edi
236
        ret
237
 
7965 hidnplayr 238
  .high_mask:
2288 clevermous 239
        add     esi, 4
7965 hidnplayr 240
        cmp     esi, mem_block_mask + 8
2288 clevermous 241
        jae     .err
242
        add     ebx, 32
243
        mov     edx, [esi]
244
        jmp     .find
245
 
246
 
247
align 4
248
free_mem_block:
7965 hidnplayr 249
 
2288 clevermous 250
        mov     ebx, [next_memblock]
251
        mov     [eax], ebx
252
        mov     [next_memblock], eax
7965 hidnplayr 253
 
2288 clevermous 254
        xor     ebx, ebx
7965 hidnplayr 255
        mov     dword[eax + 4], ebx
256
        mov     dword[eax + 8], ebx
257
        mov     dword[eax + 12], ebx
258
        mov     dword[eax + 16], ebx
259
;           mov dword[eax + 20], 0     ;don't clear block size
260
        mov     dword[eax + 24], ebx
261
        mov     dword[eax + 28], ebx
2288 clevermous 262
 
263
        inc     [free_blocks]
7965 hidnplayr 264
 
2288 clevermous 265
        ret
266
 
267
align 4
268
proc alloc_kernel_space stdcall, size:dword
269
           local block_ind:DWORD
270
 
271
        push    ebx
272
        push    esi
273
        push    edi
274
 
275
        mov     eax, [size]
276
        add     eax, 4095
277
        and     eax, not 4095
278
        mov     [size], eax
279
 
280
        cmp     eax, [heap_free]
281
        ja      .error
282
 
4391 clevermous 283
        spin_lock_irqsave heap_mutex
2288 clevermous 284
 
285
        mov     eax, [size]
286
 
287
        call    get_small_block ; eax
288
        test    edi, edi
289
        jz      .error_unlock
290
 
7965 hidnplayr 291
        cmp     [edi + MEM_BLOCK.flags], MEM_BLOCK_FREE
2288 clevermous 292
        jne     .error_unlock
293
 
294
        mov     [block_ind], ebx  ;index of allocated block
295
 
7965 hidnplayr 296
        mov     eax, [edi + MEM_BLOCK.size]
2288 clevermous 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
 
7965 hidnplayr 308
        mov     [esi + MEM_BLOCK.next_block], edi
309
        mov     eax, [edi + MEM_BLOCK.prev_block]
310
        mov     [esi + MEM_BLOCK.prev_block], eax
311
        mov     [edi + MEM_BLOCK.prev_block], esi
312
        mov     [esi + MEM_BLOCK.list.next], 0
313
        mov     [esi + MEM_BLOCK.list.prev], 0
314
        mov     [eax + MEM_BLOCK.next_block], esi
2288 clevermous 315
 
7965 hidnplayr 316
        mov     ebx, [edi + MEM_BLOCK.base]
317
        mov     [esi + MEM_BLOCK.base], ebx
2288 clevermous 318
        mov     edx, [size]
7965 hidnplayr 319
        mov     [esi + MEM_BLOCK.size], edx
320
        add     [edi + MEM_BLOCK.base], edx
321
        sub     [edi + MEM_BLOCK.size], edx
2288 clevermous 322
 
7965 hidnplayr 323
        mov     eax, [edi + MEM_BLOCK.size]
4391 clevermous 324
        calc_index eax
2288 clevermous 325
        cmp     eax, [block_ind]
326
        je      .add_used
327
 
4391 clevermous 328
        list_del edi
2288 clevermous 329
 
330
        mov     ecx, [block_ind]
7965 hidnplayr 331
        lea     edx, [mem_block_list + ecx*8]
2288 clevermous 332
        cmp     edx, [edx]
333
        jnz     @f
334
        btr     [mem_block_mask], ecx
335
@@:
336
        bts     [mem_block_mask], eax
7965 hidnplayr 337
        lea     edx, [mem_block_list + eax*8]  ;edx= list head
4391 clevermous 338
        list_add edi, edx
2288 clevermous 339
.add_used:
340
 
341
        call    md.add_to_used
342
 
4391 clevermous 343
        spin_unlock_irqrestore heap_mutex
7965 hidnplayr 344
        mov     eax, [esi + MEM_BLOCK.base]
2288 clevermous 345
        pop     edi
346
        pop     esi
347
        pop     ebx
348
        ret
349
 
350
.m_eq_size:
4391 clevermous 351
        list_del edi
7965 hidnplayr 352
        lea     edx, [mem_block_list + ebx*8]
2288 clevermous 353
        cmp     edx, [edx]
354
        jnz     @f
355
        btr     [mem_block_mask], ebx
356
@@:
357
        mov     esi, edi
358
        jmp     .add_used
359
 
360
.error_unlock:
4391 clevermous 361
        spin_unlock_irqrestore heap_mutex
2288 clevermous 362
.error:
363
        xor     eax, eax
364
        pop     edi
365
        pop     esi
366
        pop     ebx
367
        ret
368
endp
369
 
370
align 4
371
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
372
 
4391 clevermous 373
        spin_lock_irqsave heap_mutex
2288 clevermous 374
 
375
        mov     eax, [base]
376
 
377
        call    md.del_from_used
378
        test    esi, esi
379
        jz      .fail
380
 
7965 hidnplayr 381
        mov     eax, [esi + MEM_BLOCK.size]
2288 clevermous 382
        add     [heap_free], eax
383
 
7965 hidnplayr 384
        mov     edi, [esi + MEM_BLOCK.next_block]
385
        cmp     [edi + MEM_BLOCK.flags], MEM_BLOCK_FREE
2288 clevermous 386
        jne     .prev
387
 
3246 Serge 388
        list_del edi
2288 clevermous 389
 
7965 hidnplayr 390
        mov     edx, [edi + MEM_BLOCK.next_block]
391
        mov     [esi + MEM_BLOCK.next_block], edx
392
        mov     [edx + MEM_BLOCK.prev_block], esi
393
        mov     ecx, [edi + MEM_BLOCK.size]
394
        add     [esi + MEM_BLOCK.size], ecx
2288 clevermous 395
 
3246 Serge 396
        calc_index ecx
2288 clevermous 397
 
7965 hidnplayr 398
        lea     edx, [mem_block_list + ecx*8]
2288 clevermous 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:
7965 hidnplayr 406
        mov     edi, [esi + MEM_BLOCK.prev_block]
407
        cmp     [edi + MEM_BLOCK.flags], MEM_BLOCK_FREE
2288 clevermous 408
        jne     .insert
409
 
7965 hidnplayr 410
        mov     edx, [esi + MEM_BLOCK.next_block]
411
        mov     [edi + MEM_BLOCK.next_block], edx
412
        mov     [edx + MEM_BLOCK.prev_block], edi
2288 clevermous 413
 
414
        mov     eax, esi
415
        call    free_mem_block
416
 
7965 hidnplayr 417
        mov     ecx, [edi + MEM_BLOCK.size]
418
        mov     eax, [esi + MEM_BLOCK.size]
2288 clevermous 419
        add     eax, ecx
7965 hidnplayr 420
        mov     [edi + MEM_BLOCK.size], eax
2288 clevermous 421
 
3246 Serge 422
        calc_index eax                     ;new index
423
        calc_index ecx                     ;old index
2288 clevermous 424
        cmp     eax, ecx
425
        je      .m_eq
426
 
427
        push    ecx
3246 Serge 428
        list_del edi
2288 clevermous 429
        pop     ecx
430
 
7965 hidnplayr 431
        lea     edx, [mem_block_list + ecx*8]
2288 clevermous 432
        cmp     edx, [edx]
433
        jne     .add_block
434
        btr     [mem_block_mask], ecx
3246 Serge 435
 
2288 clevermous 436
.add_block:
437
        bts     [mem_block_mask], eax
7965 hidnplayr 438
        lea     edx, [mem_block_list + eax*8]
3246 Serge 439
        list_add edi, edx
2288 clevermous 440
.m_eq:
4391 clevermous 441
        spin_unlock_irqrestore heap_mutex
2288 clevermous 442
        xor     eax, eax
443
        not     eax
444
        ret
445
.insert:
7965 hidnplayr 446
        mov     [esi + MEM_BLOCK.flags], MEM_BLOCK_FREE
447
        mov     eax, [esi + MEM_BLOCK.size]
3246 Serge 448
        calc_index eax
2288 clevermous 449
        mov     edi, esi
450
        jmp     .add_block
451
 
452
.fail:
4391 clevermous 453
        spin_unlock_irqrestore heap_mutex
2288 clevermous 454
        xor     eax, eax
455
        ret
456
endp
457
 
458
align 4
459
proc kernel_alloc stdcall, size:dword
3246 Serge 460
        locals
461
          lin_addr    dd ?
462
          pages_count dd ?
463
        endl
2288 clevermous 464
 
465
        push    ebx
466
        push    edi
467
 
468
        mov     eax, [size]
469
        add     eax, 4095
470
        and     eax, not 4095;
471
        mov     [size], eax
472
        and     eax, eax
473
        jz      .err
474
        mov     ebx, eax
475
        shr     ebx, 12
476
        mov     [pages_count], ebx
477
 
478
        stdcall alloc_kernel_space, eax
4424 Serge 479
        mov     [lin_addr], eax
480
        mov     ebx, [pages_count]
2288 clevermous 481
        test    eax, eax
482
        jz      .err
483
 
484
        mov     edx, eax
485
 
4424 Serge 486
        shr     ebx, 3
487
        jz      .tail
2288 clevermous 488
 
4424 Serge 489
        shl     ebx, 3
2288 clevermous 490
        stdcall alloc_pages, ebx
4424 Serge 491
        test    eax, eax
2288 clevermous 492
        jz      .err
493
 
4424 Serge 494
        mov     ecx, ebx
7965 hidnplayr 495
        or      eax, PG_GLOBAL + PG_SWR
4424 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
2288 clevermous 503
        jz      .end
504
@@:
505
        call    alloc_page
506
        test    eax, eax
507
        jz      .err
508
 
7965 hidnplayr 509
        stdcall map_page, edx, eax, dword (PG_GLOBAL + PG_SWR)
2288 clevermous 510
        add     edx, 0x1000
4424 Serge 511
        dec     ebx
2288 clevermous 512
        jnz     @B
513
.end:
514
        mov     eax, [lin_addr]
515
        pop     edi
516
        pop     ebx
517
        ret
518
.err:
519
        xor     eax, eax
520
        pop     edi
521
        pop     ebx
522
        ret
523
endp
524
 
525
align 4
526
proc kernel_free stdcall, base:dword
527
 
528
        push    ebx esi
529
 
4391 clevermous 530
        spin_lock_irqsave heap_mutex
2288 clevermous 531
 
532
        mov     eax, [base]
533
        call    md.find_used
534
 
7965 hidnplayr 535
        cmp     [esi + MEM_BLOCK.flags], MEM_BLOCK_USED
2288 clevermous 536
        jne     .fail
537
 
4391 clevermous 538
        spin_unlock_irqrestore heap_mutex
2288 clevermous 539
 
7965 hidnplayr 540
        mov     eax, [esi + MEM_BLOCK.base]
541
        mov     ecx, [esi + MEM_BLOCK.size]
2288 clevermous 542
        shr     ecx, 12
543
        call    release_pages   ;eax, ecx
544
        stdcall free_kernel_space, [base]
545
        pop     esi ebx
546
        ret
547
.fail:
4391 clevermous 548
        spin_unlock_irqrestore heap_mutex
2288 clevermous 549
        xor     eax, eax
550
        pop     esi ebx
551
        ret
552
endp
553
 
5130 serge 554
;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
2288 clevermous 555
 
7136 dunkaist 556
HEAP_TOP  = 0x80000000
2288 clevermous 557
 
558
align 4
559
proc init_heap
560
 
5130 serge 561
        mov     ebx, [current_process]
7965 hidnplayr 562
        mov     eax, [ebx + PROC.heap_top]
2288 clevermous 563
        test    eax, eax
564
        jz      @F
7965 hidnplayr 565
        sub     eax, [ebx + PROC.heap_base]
5130 serge 566
        sub     eax, PAGE_SIZE
2288 clevermous 567
        ret
568
@@:
5130 serge 569
 
9048 Boppan 570
        mov     edx, [ebx+PROC.mem_used]
571
        add     edx, 4095
572
        and     edx, not 4095
573
        mov     [ebx+PROC.mem_used], edx
2288 clevermous 574
        mov     eax, HEAP_TOP
9048 Boppan 575
        mov     [ebx+PROC.heap_base], edx
576
        mov     [ebx+PROC.heap_top], eax
2288 clevermous 577
 
9048 Boppan 578
        sub     eax, edx
579
        shr     edx, 10
2288 clevermous 580
        mov     ecx, eax
5130 serge 581
        sub     eax, PAGE_SIZE
7965 hidnplayr 582
        or      ecx, MEM_BLOCK_FREE
9048 Boppan 583
        mov     [page_tabs + edx], ecx
2288 clevermous 584
        ret
585
endp
586
 
587
align 4
9048 Boppan 588
proc user_alloc ;stdcall, alloc_size:dword
589
        mov     ecx, [current_process]
590
        add     ecx, PROC.heap_lock
591
        call    mutex_lock
592
        stdcall user_alloc_nolock, [esp+4]
593
        push    eax
594
        mov     ecx, [current_process]
595
        add     ecx, PROC.heap_lock
596
        call    mutex_unlock
597
        pop     eax
598
        ret     4
599
endp
7965 hidnplayr 600
 
9048 Boppan 601
proc user_alloc_nolock stdcall, alloc_size:dword
6893 pathoswith 602
        push    ebx esi edi
7965 hidnplayr 603
 
6974 0CodErr 604
        mov     ebx, [current_process]
2288 clevermous 605
        mov     ecx, [alloc_size]
7965 hidnplayr 606
        add     ecx, (4095 + PAGE_SIZE)
2288 clevermous 607
        and     ecx, not 4095
7965 hidnplayr 608
        mov     esi, [ebx + PROC.heap_base]
609
        mov     edi, [ebx + PROC.heap_top]
610
  .scan:
2288 clevermous 611
        cmp     esi, edi
5130 serge 612
        jae     .m_exit
2288 clevermous 613
 
614
        mov     ebx, esi
615
        shr     ebx, 12
7965 hidnplayr 616
        mov     eax, [page_tabs + ebx*4]
617
        test    al, MEM_BLOCK_FREE
5130 serge 618
        jz      .test_used
2288 clevermous 619
        and     eax, 0xFFFFF000
620
        cmp     eax, ecx   ;alloc_size
5130 serge 621
        jb      .m_next
2288 clevermous 622
        jz      @f
623
 
7965 hidnplayr 624
        lea     edx, [esi + ecx]
2288 clevermous 625
        sub     eax, ecx
7965 hidnplayr 626
        or      al, MEM_BLOCK_FREE
2288 clevermous 627
        shr     edx, 12
7965 hidnplayr 628
        mov     [page_tabs + edx*4], eax
629
  @@:
630
        or      ecx, MEM_BLOCK_USED
631
        mov     [page_tabs + ebx*4], ecx
2288 clevermous 632
        shr     ecx, 12
633
        inc     ebx
634
        dec     ecx
635
        jz      .no
7965 hidnplayr 636
  @@:
637
        mov     dword [page_tabs + ebx*4], MEM_BLOCK_RESERVED
2288 clevermous 638
        inc     ebx
639
        dec     ecx
640
        jnz     @B
7965 hidnplayr 641
  .no:
2288 clevermous 642
 
7965 hidnplayr 643
        lea     eax, [esi + 4096]
2288 clevermous 644
 
645
        pop     edi
646
        pop     esi
647
        pop     ebx
648
        ret
5130 serge 649
.test_used:
7965 hidnplayr 650
        test    al, MEM_BLOCK_USED
5130 serge 651
        jz      .m_exit
2288 clevermous 652
 
7965 hidnplayr 653
        and     eax, 0xFFFFF000 ; not PAGESIZE
5130 serge 654
.m_next:
2288 clevermous 655
        add     esi, eax
5130 serge 656
        jmp     .scan
657
.m_exit:
658
 
2288 clevermous 659
        xor     eax, eax
660
        pop     edi
661
        pop     esi
662
        pop     ebx
663
        ret
664
endp
665
 
666
align 4
9048 Boppan 667
proc user_alloc_at ;stdcall, address:dword, alloc_size:dword
668
        mov     ecx, [current_process]
669
        add     ecx, PROC.heap_lock
670
        call    mutex_lock
671
        stdcall user_alloc_at_nolock, [esp+8], [esp+8]
672
        push    eax
673
        mov     ecx, [current_process]
674
        add     ecx, PROC.heap_lock
675
        call    mutex_unlock
676
        pop     eax
677
        ret     8
678
endp
2288 clevermous 679
 
9048 Boppan 680
proc user_alloc_at_nolock stdcall, address:dword, alloc_size:dword
2288 clevermous 681
        push    ebx
682
        push    esi
683
        push    edi
684
 
5130 serge 685
        mov     ebx, [current_process]
686
 
2288 clevermous 687
        mov     edx, [address]
688
        and     edx, not 0xFFF
689
        mov     [address], edx
690
        sub     edx, 0x1000
691
        jb      .error
7965 hidnplayr 692
        mov     esi, [ebx + PROC.heap_base]
693
        mov     edi, [ebx + PROC.heap_top]
2288 clevermous 694
        cmp     edx, esi
695
        jb      .error
696
.scan:
697
        cmp     esi, edi
698
        jae     .error
699
        mov     ebx, esi
700
        shr     ebx, 12
7965 hidnplayr 701
        mov     eax, [page_tabs + ebx*4]
2288 clevermous 702
        mov     ecx, eax
703
        and     ecx, 0xFFFFF000
704
        add     ecx, esi
705
        cmp     edx, ecx
706
        jb      .found
707
        mov     esi, ecx
708
        jmp     .scan
709
.error:
5130 serge 710
 
2288 clevermous 711
        xor     eax, eax
712
        pop     edi
713
        pop     esi
714
        pop     ebx
715
        ret
716
.found:
7965 hidnplayr 717
        test    al, MEM_BLOCK_FREE
2288 clevermous 718
        jz      .error
719
        mov     eax, ecx
720
        sub     eax, edx
721
        sub     eax, 0x1000
722
        cmp     eax, [alloc_size]
723
        jb      .error
724
 
725
; Here we have 1 big free block which includes requested area.
726
; In general, 3 other blocks must be created instead:
727
; free at [esi, edx);
7965 hidnplayr 728
; busy at [edx, edx + 0x1000 + ALIGN_UP(alloc_size,0x1000));
729
; free at [edx + 0x1000 + ALIGN_UP(alloc_size,0x1000), ecx)
2288 clevermous 730
; First or third block (or both) may be absent.
731
        mov     eax, edx
732
        sub     eax, esi
733
        jz      .nofirst
7965 hidnplayr 734
        or      al, MEM_BLOCK_FREE
735
        mov     [page_tabs + ebx*4], eax
736
  .nofirst:
2288 clevermous 737
        mov     eax, [alloc_size]
738
        add     eax, 0x1FFF
739
        and     eax, not 0xFFF
740
        mov     ebx, edx
741
        add     edx, eax
742
        shr     ebx, 12
7965 hidnplayr 743
        or      al, MEM_BLOCK_USED
744
        mov     [page_tabs + ebx*4], eax
2288 clevermous 745
        shr     eax, 12
746
        dec     eax
747
        jz      .second_nofill
748
        inc     ebx
7965 hidnplayr 749
  .fill:
750
        mov     dword [page_tabs + ebx*4], MEM_BLOCK_RESERVED
2288 clevermous 751
        inc     ebx
752
        dec     eax
753
        jnz     .fill
3246 Serge 754
 
7965 hidnplayr 755
  .second_nofill:
2288 clevermous 756
        sub     ecx, edx
757
        jz      .nothird
7965 hidnplayr 758
        or      cl, MEM_BLOCK_FREE
759
        mov     [page_tabs + ebx*4], ecx
3246 Serge 760
 
9048 Boppan 761
.nothird:
2288 clevermous 762
        mov     eax, [address]
763
 
764
        pop     edi
765
        pop     esi
766
        pop     ebx
767
        ret
768
endp
769
 
770
align 4
771
proc user_free stdcall, base:dword
772
 
773
        push    esi
774
 
775
        mov     esi, [base]
776
 
777
        push    ebx
778
 
5130 serge 779
        mov     ebx, [current_process]
7965 hidnplayr 780
        lea     ecx, [ebx + PROC.heap_lock]
5130 serge 781
        call    mutex_lock
782
 
2288 clevermous 783
        xor     ebx, ebx
784
        shr     esi, 12
9048 Boppan 785
        jz      .cantfree
7965 hidnplayr 786
        mov     eax, [page_tabs + (esi-1)*4]
787
        test    al, MEM_BLOCK_USED
2288 clevermous 788
        jz      .cantfree
7965 hidnplayr 789
        test    al, MEM_BLOCK_DONT_FREE
2288 clevermous 790
        jnz     .cantfree
791
 
9048 Boppan 792
        push    0
793
virtual at esp
794
.num_released_pages dd ?
795
end virtual
796
 
2288 clevermous 797
        and     eax, not 4095
798
        mov     ecx, eax
7965 hidnplayr 799
        or      al, MEM_BLOCK_FREE
800
        mov     [page_tabs + (esi-1)*4], eax
2288 clevermous 801
        sub     ecx, 4096
802
        mov     ebx, ecx
803
        shr     ecx, 12
804
        jz      .released
9048 Boppan 805
.release:
806
        mov     edx, [page_tabs+esi*4]
807
        mov     dword [page_tabs+esi*4], 0
2288 clevermous 808
        mov     eax, esi
809
        shl     eax, 12
810
        invlpg  [eax]
9048 Boppan 811
        test    dl, 1
812
        jz      @F
813
        inc     [.num_released_pages]
814
        test    edx, PG_SHARED
815
        jnz     @f
816
        mov     eax, edx
817
        call    free_page
818
@@:
2288 clevermous 819
        inc     esi
820
        dec     ecx
821
        jnz     .release
3246 Serge 822
 
9048 Boppan 823
.released:
2288 clevermous 824
 
9048 Boppan 825
        pop     eax ; .num_released_pages
826
        shl     eax, 12
5130 serge 827
        mov     edx, [current_process]
7965 hidnplayr 828
        lea     ecx, [edx + PROC.heap_lock]
9048 Boppan 829
        sub     [edx + PROC.mem_used], eax
2288 clevermous 830
        call    user_normalize
9048 Boppan 831
.exit:
5130 serge 832
        call    mutex_unlock
833
 
2288 clevermous 834
        xor     eax, eax
835
        inc     eax
5130 serge 836
        pop     ebx
2288 clevermous 837
        pop     esi
838
        ret
5130 serge 839
 
7965 hidnplayr 840
  .cantfree:
5130 serge 841
        mov     ecx, [current_process]
7965 hidnplayr 842
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 843
        jmp     .exit
7965 hidnplayr 844
  .fail:
2288 clevermous 845
        xor     eax, eax
846
        pop     esi
847
        ret
848
endp
849
 
2400 Serge 850
 
851
align 4
852
proc user_unmap stdcall, base:dword, offset:dword, size:dword
9048 Boppan 853
        mov     ecx, [current_process]
854
        add     ecx, PROC.heap_lock
855
        call    mutex_lock
2400 Serge 856
 
857
        push    ebx
858
 
859
        mov     ebx, [base]             ; must be valid pointer
860
 
861
        mov     edx, [offset]           ; check offset
862
        add     edx, ebx                ; must be below 2Gb app limit
9048 Boppan 863
        jc      .error
2400 Serge 864
        js      .error
865
 
866
        shr     ebx, 12                 ; chek block attributes
9048 Boppan 867
        jz      .error
7965 hidnplayr 868
        lea     ebx, [page_tabs + ebx*4]
2400 Serge 869
        mov     eax, [ebx-4]            ; block attributes
7965 hidnplayr 870
        test    al, MEM_BLOCK_USED
2400 Serge 871
        jz      .error
7965 hidnplayr 872
        test    al, MEM_BLOCK_DONT_FREE
2400 Serge 873
        jnz     .error
874
 
875
        shr     edx, 12
7965 hidnplayr 876
        lea     edx, [page_tabs + edx*4]  ; unmap offset
2400 Serge 877
 
878
        mov     ecx, [size]
879
        add     ecx, 4095
880
        shr     ecx, 12                 ; unmap size in pages
881
 
7965 hidnplayr 882
        shr     eax, 12                 ; block size  +  1 page
883
        lea     ebx, [ebx + eax*4-4]      ; block end ptr
884
        lea     eax, [edx + ecx*4]        ; unmap end ptr
2400 Serge 885
 
886
        cmp     eax, ebx                ; check for overflow
887
        ja      .error
888
 
889
        mov     ebx, [offset]
890
        and     ebx, not 4095           ; is it required ?
3798 Serge 891
        add     ebx, [base]
2400 Serge 892
 
9048 Boppan 893
        push    0
894
virtual at esp
895
.num_released_pages dd ?
896
end virtual
897
 
898
.unmap:
2400 Serge 899
        mov     eax, [edx]              ; get page addres
900
        test    al, 1                   ; page mapped ?
9048 Boppan 901
        jz      .next
2400 Serge 902
        test    eax, PG_SHARED          ; page shared ?
9048 Boppan 903
        jnz     .next
904
        inc     [.num_released_pages]
905
        mov     dword [edx], LAZY_ALLOC_PAGE
2400 Serge 906
                                        ; mark page as reserved
9048 Boppan 907
        test    eax, PG_READ
908
        jnz     @f
909
        or      dword [edx], LAZY_ALLOC_UNREADABLE
910
@@:
911
        test    eax, PG_WRITE
912
        jnz     @f
913
        or      dword [edx], LAZY_ALLOC_UNWRITABLE
914
@@:
2400 Serge 915
        invlpg  [ebx]                   ; when we start using
916
        call    free_page               ; empty c-o-w page instead this ?
9048 Boppan 917
.next:
918
        add     ebx, 4096
2400 Serge 919
        add     edx, 4
920
        dec     ecx
921
        jnz     .unmap
922
 
9048 Boppan 923
        pop     eax ; .num_released_pages
2400 Serge 924
        pop     ebx
9048 Boppan 925
        shl     eax, 12
926
        mov     ecx, [current_process]
927
        sub     [ecx+PROC.mem_used], eax
928
        push    eax
929
        add     ecx, PROC.heap_lock
930
        call    mutex_unlock
931
        pop     eax                     ; return number of released bytes
2400 Serge 932
        ret
933
.error:
934
        pop     ebx
9048 Boppan 935
        mov     ecx, [current_process]
936
        add     ecx, PROC.heap_lock
937
        call    mutex_unlock
2400 Serge 938
        xor     eax, eax                ; something wrong
9048 Boppan 939
        dec     eax
2400 Serge 940
        ret
941
endp
942
 
943
align 4
9048 Boppan 944
proc user_normalize uses esi edi
945
; in: edx->PROC
2288 clevermous 946
; out: eax=0 <=> OK
9048 Boppan 947
; destroys: ebx,edx
948
        mov     esi, dword [edx+PROC.heap_base]
949
        mov     edi, dword [edx+PROC.heap_top]
2288 clevermous 950
        shr     esi, 12
951
        shr     edi, 12
952
@@:
7965 hidnplayr 953
        mov     eax, [page_tabs + esi*4]
954
        test    al, MEM_BLOCK_USED
2288 clevermous 955
        jz      .test_free
956
        shr     eax, 12
957
        add     esi, eax
958
        jmp     @B
959
.test_free:
7965 hidnplayr 960
        test    al, MEM_BLOCK_FREE
2288 clevermous 961
        jz      .err
962
        mov     edx, eax
963
        shr     edx, 12
964
        add     edx, esi
965
        cmp     edx, edi
966
        jae     .exit
967
 
7965 hidnplayr 968
        mov     ebx, [page_tabs + edx*4]
969
        test    bl, MEM_BLOCK_USED
2288 clevermous 970
        jz      .next_free
971
 
972
        shr     ebx, 12
973
        add     edx, ebx
974
        mov     esi, edx
975
        jmp     @B
976
.next_free:
7965 hidnplayr 977
        test    bl, MEM_BLOCK_FREE
2288 clevermous 978
        jz      .err
7965 hidnplayr 979
        and     dword[page_tabs + edx*4], 0
2288 clevermous 980
        add     eax, ebx
7965 hidnplayr 981
        and     eax, not 4095           ; not (PAGESIZE - 1)    ?
982
        or      eax, MEM_BLOCK_FREE
983
        mov     [page_tabs + esi*4], eax
2288 clevermous 984
        jmp     @B
985
.exit:
986
        xor     eax, eax
987
        inc     eax
988
        ret
989
.err:
990
        xor     eax, eax
991
        ret
9048 Boppan 992
endp
2288 clevermous 993
 
994
user_realloc:
995
; in: eax = pointer, ebx = new size
996
; out: eax = new pointer or NULL
997
        test    eax, eax
998
        jnz     @f
999
; realloc(NULL,sz) - same as malloc(sz)
1000
        push    ebx
1001
        call    user_alloc
1002
        ret
1003
@@:
1004
        push    ecx edx
5130 serge 1005
 
1006
        push    eax
1007
        mov     ecx, [current_process]
7965 hidnplayr 1008
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 1009
        call    mutex_lock
1010
        pop     eax
1011
 
2288 clevermous 1012
        lea     ecx, [eax - 0x1000]
1013
        shr     ecx, 12
7965 hidnplayr 1014
        mov     edx, [page_tabs + ecx*4]
1015
        test    dl, MEM_BLOCK_USED
2288 clevermous 1016
        jnz     @f
1017
; attempt to realloc invalid pointer
1018
.ret0:
5130 serge 1019
        mov     ecx, [current_process]
7965 hidnplayr 1020
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 1021
        call    mutex_unlock
1022
 
2288 clevermous 1023
        pop     edx ecx
1024
        xor     eax, eax
1025
        ret
1026
@@:
7965 hidnplayr 1027
        test    dl, MEM_BLOCK_DONT_FREE
2288 clevermous 1028
        jnz     .ret0
1029
        add     ebx, 0x1FFF
1030
        shr     edx, 12
1031
        shr     ebx, 12
1032
; edx = allocated size, ebx = new size
1033
        add     edx, ecx
1034
        add     ebx, ecx
1035
        cmp     edx, ebx
1036
        jb      .realloc_add
1037
; release part of allocated memory
9048 Boppan 1038
        push    edx
1039
        push    0
1040
virtual at esp
1041
.num_released_pages dd ?
1042
end virtual
2288 clevermous 1043
.loop:
1044
        cmp     edx, ebx
1045
        jz      .release_done
1046
        dec     edx
9048 Boppan 1047
        push    dword [page_tabs + edx*4]
1048
        mov     dword [page_tabs + edx*4], 0
1049
        mov     eax, edx
1050
        shl     eax, 12
1051
        invlpg  [eax]
1052
        pop     eax
2288 clevermous 1053
        test    al, 1
1054
        jz      .loop
9048 Boppan 1055
        inc     [.num_released_pages]
1056
        test    eax, PG_SHARED
1057
        jnz     .loop
2288 clevermous 1058
        call    free_page
1059
        jmp     .loop
1060
.release_done:
9048 Boppan 1061
        pop     eax ; .num_released_pages
1062
        mov     edx, [current_process]
1063
        shl     eax, 12
1064
        sub     [edx+PROC.mem_used], eax
1065
        pop     edx
2288 clevermous 1066
        sub     ebx, ecx
1067
        cmp     ebx, 1
1068
        jnz     .nofreeall
7965 hidnplayr 1069
        mov     eax, [page_tabs + ecx*4]
2288 clevermous 1070
        and     eax, not 0xFFF
7965 hidnplayr 1071
        or      al, MEM_BLOCK_FREE
1072
        mov     [page_tabs + ecx*4], eax
9048 Boppan 1073
        mov     edx, [current_process]
2288 clevermous 1074
        call    user_normalize
1075
        jmp     .ret0   ; all freed
1076
.nofreeall:
1077
        sub     edx, ecx
1078
        shl     ebx, 12
7965 hidnplayr 1079
        or      ebx, MEM_BLOCK_USED
1080
        xchg    [page_tabs + ecx*4], ebx
2288 clevermous 1081
        shr     ebx, 12
1082
        sub     ebx, edx
7965 hidnplayr 1083
        lea     eax, [ecx + 1]
2288 clevermous 1084
        shl     eax, 12
1085
        push    eax
1086
        add     ecx, edx
7965 hidnplayr 1087
        lea     edx, [ecx + ebx]
2288 clevermous 1088
        shl     ebx, 12
1089
        jz      .ret
1090
        push    esi
5130 serge 1091
        mov     esi, [current_process]
7965 hidnplayr 1092
        mov     esi, [esi + PROC.heap_top]
2288 clevermous 1093
        shr     esi, 12
1094
@@:
1095
        cmp     edx, esi
1096
        jae     .merge_done
7965 hidnplayr 1097
        mov     eax, [page_tabs + edx*4]
1098
        test    al, MEM_BLOCK_USED
2288 clevermous 1099
        jnz     .merge_done
7965 hidnplayr 1100
        and     dword [page_tabs + edx*4], 0
2288 clevermous 1101
        shr     eax, 12
1102
        add     edx, eax
1103
        shl     eax, 12
1104
        add     ebx, eax
1105
        jmp     @b
1106
.merge_done:
1107
        pop     esi
7965 hidnplayr 1108
        or      ebx, MEM_BLOCK_FREE
1109
        mov     [page_tabs + ecx*4], ebx
2288 clevermous 1110
.ret:
5130 serge 1111
        mov     ecx, [current_process]
7965 hidnplayr 1112
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 1113
        call    mutex_unlock
2288 clevermous 1114
        pop     eax edx ecx
1115
        ret
5130 serge 1116
 
2288 clevermous 1117
.realloc_add:
1118
; get some additional memory
5130 serge 1119
        mov     eax, [current_process]
7965 hidnplayr 1120
        mov     eax, [eax + PROC.heap_top]
2288 clevermous 1121
        shr     eax, 12
1122
        cmp     edx, eax
1123
        jae     .cant_inplace
7965 hidnplayr 1124
        mov     eax, [page_tabs + edx*4]
1125
        test    al, MEM_BLOCK_FREE
2288 clevermous 1126
        jz      .cant_inplace
1127
        shr     eax, 12
1128
        add     eax, edx
1129
        sub     eax, ebx
1130
        jb      .cant_inplace
1131
        jz      @f
1132
        shl     eax, 12
7965 hidnplayr 1133
        or      al, MEM_BLOCK_FREE
1134
        mov     [page_tabs + ebx*4], eax
2288 clevermous 1135
@@:
1136
        mov     eax, ebx
1137
        sub     eax, ecx
1138
        shl     eax, 12
7965 hidnplayr 1139
        or      al, MEM_BLOCK_USED
1140
        mov     [page_tabs + ecx*4], eax
1141
        lea     eax, [ecx + 1]
2288 clevermous 1142
        shl     eax, 12
1143
        push    eax
1144
        push    edi
7965 hidnplayr 1145
        lea     edi, [page_tabs + edx*4]
2288 clevermous 1146
        mov     eax, 2
1147
        sub     ebx, edx
1148
        mov     ecx, ebx
1149
        cld
1150
        rep stosd
1151
        pop     edi
5130 serge 1152
 
1153
        mov     ecx, [current_process]
7965 hidnplayr 1154
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 1155
        call    mutex_unlock
2288 clevermous 1156
        pop     eax edx ecx
1157
        ret
5130 serge 1158
 
2288 clevermous 1159
.cant_inplace:
1160
        push    esi edi
5130 serge 1161
        mov     eax, [current_process]
7965 hidnplayr 1162
        mov     esi, [eax + PROC.heap_base]
1163
        mov     edi, [eax + PROC.heap_top]
2288 clevermous 1164
        shr     esi, 12
1165
        shr     edi, 12
1166
        sub     ebx, ecx
1167
.find_place:
1168
        cmp     esi, edi
1169
        jae     .place_not_found
7965 hidnplayr 1170
        mov     eax, [page_tabs + esi*4]
1171
        test    al, MEM_BLOCK_FREE
2288 clevermous 1172
        jz      .next_place
1173
        shr     eax, 12
1174
        cmp     eax, ebx
1175
        jae     .place_found
1176
        add     esi, eax
1177
        jmp     .find_place
1178
.next_place:
1179
        shr     eax, 12
1180
        add     esi, eax
1181
        jmp     .find_place
1182
.place_not_found:
1183
        pop     edi esi
1184
        jmp     .ret0
1185
.place_found:
1186
        sub     eax, ebx
1187
        jz      @f
1188
        push    esi
1189
        add     esi, ebx
1190
        shl     eax, 12
7965 hidnplayr 1191
        or      al, MEM_BLOCK_FREE
1192
        mov     [page_tabs + esi*4], eax
2288 clevermous 1193
        pop     esi
1194
@@:
1195
        mov     eax, ebx
1196
        shl     eax, 12
7965 hidnplayr 1197
        or      al, MEM_BLOCK_USED
1198
        mov     [page_tabs + esi*4], eax
2288 clevermous 1199
        inc     esi
1200
        mov     eax, esi
1201
        shl     eax, 12
1202
        push    eax
7965 hidnplayr 1203
        mov     eax, [page_tabs + ecx*4]
2288 clevermous 1204
        and     eax, not 0xFFF
7965 hidnplayr 1205
        or      al, MEM_BLOCK_FREE
2288 clevermous 1206
        sub     edx, ecx
7965 hidnplayr 1207
        mov     [page_tabs + ecx*4], eax
2288 clevermous 1208
        inc     ecx
1209
        dec     ebx
1210
        dec     edx
1211
        jz      .no
1212
@@:
1213
        xor     eax, eax
7965 hidnplayr 1214
        xchg    eax, [page_tabs + ecx*4]
1215
        mov     [page_tabs + esi*4], eax
2288 clevermous 1216
        mov     eax, ecx
1217
        shl     eax, 12
1218
        invlpg  [eax]
1219
        inc     esi
1220
        inc     ecx
1221
        dec     ebx
1222
        dec     edx
1223
        jnz     @b
1224
.no:
1225
@@:
7965 hidnplayr 1226
        mov     dword [page_tabs + esi*4], MEM_BLOCK_RESERVED
2288 clevermous 1227
        inc     esi
1228
        dec     ebx
1229
        jnz     @b
5130 serge 1230
 
1231
        mov     ecx, [current_process]
7965 hidnplayr 1232
        lea     ecx, [ecx + PROC.heap_lock]
5130 serge 1233
        call    mutex_unlock
2288 clevermous 1234
        pop     eax edi esi edx ecx
1235
        ret
1236
 
1237
 
1238
 
5130 serge 1239
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
2288 clevermous 1240
 
1241
 
1242
; param
9048 Boppan 1243
;  edi= shm_map object
1244
;  [esp+4] = process
2288 clevermous 1245
 
9048 Boppan 1246
proc destroy_smap ;stdcall, process:dword
2288 clevermous 1247
        push    esi
9048 Boppan 1248
        mov     esi, [edi+SMAP.parent]
1249
        cmp     [edi+SMAP.type], SMAP_TYPE_SMEM
1250
        jz      .smem
1251
        mov     ecx, [esp+8]
1252
        add     ecx, PROC.heap_lock
1253
        call    mutex_lock
1254
        stdcall release_pemap, [esp+8]
1255
        mov     ecx, [esp+8]
1256
        add     ecx, PROC.heap_lock
1257
        call    mutex_unlock
1258
        sub     ecx, PROC.heap_lock
1259
        cmp     ecx, [current_process]
1260
        jnz     @f
1261
        stdcall user_free, [edi+SMAP.base]
1262
@@:
1263
        call    dereference_pe
1264
        jmp     .common
1265
.smem:
1266
        mov     eax, [current_process]
1267
        cmp     [esp+8], eax
1268
        jnz     @f
1269
        stdcall user_free, [edi+SMAP.base]
1270
@@:
1271
        call    dereference_smem
1272
.common:
1273
        mov     eax, edi
1274
        call    free
1275
        pop     esi
1276
        ret     4
1277
endp
2288 clevermous 1278
 
9048 Boppan 1279
proc dereference_smem
1280
        mov     ecx, shmem_list_mutex
1281
        call    mutex_lock
1282
        dec     [esi+SMEM.refcount]
1283
        jnz     mutex_unlock
2288 clevermous 1284
 
7965 hidnplayr 1285
        mov     ecx, [esi + SMEM.bk]
1286
        mov     edx, [esi + SMEM.fd]
2288 clevermous 1287
 
7965 hidnplayr 1288
        mov     [ecx + SMEM.fd], edx
1289
        mov     [edx + SMEM.bk], ecx
2288 clevermous 1290
 
9048 Boppan 1291
        mov     ecx, shmem_list_mutex
1292
        call    mutex_unlock
1293
 
7965 hidnplayr 1294
        stdcall kernel_free, [esi + SMEM.base]
2288 clevermous 1295
        mov     eax, esi
1296
        call    free
1297
        ret
9048 Boppan 1298
endp
2288 clevermous 1299
 
7136 dunkaist 1300
E_NOTFOUND      =  5
1301
E_ACCESS        = 10
1302
E_NOMEM         = 30
1303
E_PARAM         = 33
2288 clevermous 1304
 
7136 dunkaist 1305
SHM_READ        = 0
1306
SHM_WRITE       = 1
2288 clevermous 1307
 
7136 dunkaist 1308
SHM_ACCESS_MASK = 3
2288 clevermous 1309
 
7136 dunkaist 1310
SHM_OPEN        = 0 shl 2
1311
SHM_OPEN_ALWAYS = 1 shl 2
1312
SHM_CREATE      = 2 shl 2
2288 clevermous 1313
 
7136 dunkaist 1314
SHM_OPEN_MASK   = 3 shl 2
2288 clevermous 1315
 
1316
align 4
9048 Boppan 1317
proc shmem_open stdcall uses ebx esi edi, name:dword, size:dword, access:dword
3246 Serge 1318
        locals
1319
           action         dd ?
1320
           owner_access   dd ?
1321
           mapped         dd ?
9048 Boppan 1322
           edx_ret        dd ?
3246 Serge 1323
        endl
2288 clevermous 1324
 
1325
        mov     [mapped], 0
1326
        mov     [owner_access], 0
1327
 
1328
        mov     eax, [access]
1329
        and     eax, SHM_OPEN_MASK
1330
        mov     [action], eax
1331
 
1332
        mov     ebx, [name]
1333
        test    ebx, ebx
9048 Boppan 1334
        mov     [edx_ret], E_PARAM
1335
        jz      .exit
2288 clevermous 1336
 
9048 Boppan 1337
        mov     ecx, shmem_list_mutex
1338
        call    mutex_lock
1339
 
2288 clevermous 1340
        mov     esi, [shmem_list.fd]
1341
align 4
1342
@@:
1343
        cmp     esi, shmem_list
1344
        je      .not_found
1345
 
7965 hidnplayr 1346
        lea     edx, [esi + SMEM.name]; link , base, size
2288 clevermous 1347
        stdcall strncmp, edx, ebx, 32
1348
        test    eax, eax
1349
        je      .found
1350
 
7965 hidnplayr 1351
        mov     esi, [esi + SMEM.fd]
2288 clevermous 1352
        jmp     @B
1353
 
1354
.not_found:
1355
        mov     eax, [action]
1356
 
9048 Boppan 1357
        mov     [edx_ret], E_NOTFOUND
2288 clevermous 1358
        cmp     eax, SHM_OPEN
9048 Boppan 1359
        je      .exit_unlock
2288 clevermous 1360
 
9048 Boppan 1361
        mov     [edx_ret], E_PARAM
2288 clevermous 1362
        cmp     eax, SHM_CREATE
1363
        je      .create_shm
1364
 
1365
        cmp     eax, SHM_OPEN_ALWAYS
9048 Boppan 1366
        jne     .exit_unlock
2288 clevermous 1367
 
1368
.create_shm:
1369
 
1370
        mov     ecx, [size]
1371
        test    ecx, ecx
9048 Boppan 1372
        jz      .exit_unlock
2288 clevermous 1373
 
1374
        add     ecx, 4095
1375
        and     ecx, -4096
1376
        mov     [size], ecx
1377
 
2384 hidnplayr 1378
        mov     eax, sizeof.SMEM
2288 clevermous 1379
        call    malloc
1380
        test    eax, eax
1381
        mov     esi, eax
9048 Boppan 1382
        mov     [edx_ret], E_NOMEM
1383
        jz      .exit_unlock
2288 clevermous 1384
 
1385
        stdcall kernel_alloc, [size]
1386
        test    eax, eax
1387
        jz      .cleanup
1388
 
1389
        mov     ecx, [size]
1390
        mov     edx, [access]
1391
        and     edx, SHM_ACCESS_MASK
1392
 
7965 hidnplayr 1393
        mov     [esi + SMEM.base], eax
1394
        mov     [esi + SMEM.size], ecx
1395
        mov     [esi + SMEM.access], edx
1396
        mov     [esi + SMEM.refcount], 0
1397
        mov     [esi + SMEM.name + 28], 0
2288 clevermous 1398
 
7965 hidnplayr 1399
        lea     eax, [esi + SMEM.name]
2288 clevermous 1400
        stdcall strncpy, eax, [name], 31
1401
 
1402
        mov     eax, [shmem_list.fd]
7965 hidnplayr 1403
        mov     [esi + SMEM.bk], shmem_list
1404
        mov     [esi + SMEM.fd], eax
2288 clevermous 1405
 
7965 hidnplayr 1406
        mov     [eax + SMEM.bk], esi
2288 clevermous 1407
        mov     [shmem_list.fd], esi
1408
 
1409
        mov     [action], SHM_OPEN
1410
        mov     [owner_access], SHM_WRITE
1411
 
1412
.found:
1413
        mov     eax, [action]
1414
 
9048 Boppan 1415
        mov     [edx_ret], E_ACCESS
2288 clevermous 1416
        cmp     eax, SHM_CREATE
9048 Boppan 1417
        je      .exit_unlock
2288 clevermous 1418
 
9048 Boppan 1419
        mov     [edx_ret], E_PARAM
2288 clevermous 1420
        cmp     eax, SHM_OPEN
1421
        je      .create_map
1422
 
1423
        cmp     eax, SHM_OPEN_ALWAYS
9048 Boppan 1424
        jne     .exit_unlock
2288 clevermous 1425
 
1426
.create_map:
1427
 
1428
        mov     eax, [access]
1429
        and     eax, SHM_ACCESS_MASK
7965 hidnplayr 1430
        cmp     eax, [esi + SMEM.access]
2288 clevermous 1431
        mov     [access], eax
9048 Boppan 1432
        mov     [edx_ret], E_ACCESS
1433
        ja      .exit_unlock
2288 clevermous 1434
 
9048 Boppan 1435
        inc     [esi+SMEM.refcount]
1436
        mov     ecx, shmem_list_mutex
1437
        call    mutex_unlock
1438
 
2384 hidnplayr 1439
        mov     eax, sizeof.SMAP
9048 Boppan 1440
        call    malloc
2288 clevermous 1441
        test    eax, eax
1442
        mov     edi, eax
9048 Boppan 1443
        mov     [edx_ret], E_NOMEM
1444
        jz      .cleanup2
2288 clevermous 1445
 
9048 Boppan 1446
        mov     [edi+SMAP.type], SMAP_TYPE_SMEM
7965 hidnplayr 1447
        mov     [edi + SMAP.parent], esi
9048 Boppan 1448
        mov     ecx, [current_process]
1449
        add     ecx, PROC.heap_lock
1450
        call    mutex_lock
2288 clevermous 1451
 
9048 Boppan 1452
        stdcall user_alloc_nolock, [esi+SMEM.size]
2288 clevermous 1453
        test    eax, eax
1454
        mov     [mapped], eax
9048 Boppan 1455
        jz      .cleanup3
2288 clevermous 1456
 
7965 hidnplayr 1457
        mov     [edi + SMAP.base], eax
9048 Boppan 1458
        mov     ecx, [current_process]
1459
        mov     edx, [ecx+PROC.smap_list+SMAP.bk]
1460
        add     ecx, PROC.smap_list
1461
        mov     [edi+SMAP.fd], ecx
1462
        mov     [edi+SMAP.bk], edx
1463
        mov     [ecx+SMAP.bk], edi
1464
        mov     [edx+SMAP.fd], edi
2288 clevermous 1465
 
7965 hidnplayr 1466
        mov     ecx, [esi + SMEM.size]
9048 Boppan 1467
        mov     [edi + SMAP.size], ecx
1468
        mov     [edx_ret], ecx
2288 clevermous 1469
 
1470
        shr     ecx, 12
1471
        shr     eax, 10
1472
 
7965 hidnplayr 1473
        mov     esi, [esi + SMEM.base]
2288 clevermous 1474
        shr     esi, 10
1475
 
9048 Boppan 1476
        xor     ebx, ebx
2288 clevermous 1477
        mov     edx, [access]
1478
        or      edx, [owner_access]
1479
        shl     edx, 1
7965 hidnplayr 1480
        or      edx, PG_SHARED + PG_UR
2288 clevermous 1481
@@:
9048 Boppan 1482
        mov     edi, [page_tabs+esi+ebx*4]
1483
        and     edi, 0xFFFFF000
1484
        or      edi, edx
1485
        mov     [page_tabs+eax+ebx*4], edi
1486
        inc     ebx
1487
        dec     ecx
1488
        jnz     @B
2288 clevermous 1489
 
9048 Boppan 1490
        mov     ecx, [current_process]
1491
        shl     ebx, 12
1492
        add     [ecx+PROC.mem_used], ebx
1493
        add     ecx, PROC.heap_lock
1494
        call    mutex_unlock
2288 clevermous 1495
 
1496
        cmp     [owner_access], 0
9048 Boppan 1497
        jz      .exit
1498
        mov     [edx_ret], 0
1499
 
2288 clevermous 1500
.exit:
1501
        mov     eax, [mapped]
9048 Boppan 1502
        mov     edx, [edx_ret]
2288 clevermous 1503
        ret
1504
.cleanup:
1505
        mov     eax, esi
1506
        call    free
9048 Boppan 1507
.exit_unlock:
1508
        mov     ecx, shmem_list_mutex
1509
        call    mutex_unlock
2288 clevermous 1510
        jmp     .exit
1511
 
9048 Boppan 1512
.cleanup3:
1513
        mov     ecx, [current_process]
1514
        add     ecx, PROC.heap_lock
1515
        call    mutex_unlock
1516
        mov     eax, edi
1517
        call    free
2288 clevermous 1518
.cleanup2:
9048 Boppan 1519
        call    dereference_smem
2288 clevermous 1520
        jmp     .exit
1521
endp
1522
 
1523
align 4
1524
proc shmem_close stdcall, name:dword
1525
 
9048 Boppan 1526
        cmp     [name], 0
2288 clevermous 1527
        jz      .fail
1528
 
1529
        push    esi
1530
        push    edi
1531
 
9048 Boppan 1532
        mov     ecx, [current_process]
1533
        lea     edi, [ecx+PROC.smap_list]
1534
        add     ecx, PROC.heap_lock
1535
        call    mutex_lock
1536
        mov     esi, edi
1537
 
2288 clevermous 1538
.next:
9048 Boppan 1539
        mov     edi, [edi+SMAP.fd]
1540
        cmp     edi, esi
1541
        je      .notfound
2288 clevermous 1542
 
9048 Boppan 1543
        cmp     [edi + SMAP.type], SMAP_TYPE_SMEM
2288 clevermous 1544
        jne     .next
1545
 
9048 Boppan 1546
        mov     eax, [edi + SMAP.parent]
1547
        add     eax, SMEM.name
2288 clevermous 1548
 
9048 Boppan 1549
        stdcall strncmp, [name], eax, 32
2288 clevermous 1550
        test    eax, eax
1551
        jne     .next
1552
 
9048 Boppan 1553
        mov     eax, [edi+SMAP.fd]
1554
        mov     edx, [edi+SMAP.bk]
1555
        mov     [eax+SMAP.bk], edx
1556
        mov     [edx+SMAP.fd], eax
2288 clevermous 1557
 
9048 Boppan 1558
        mov     ecx, [current_process]
1559
        add     ecx, PROC.heap_lock
1560
        call    mutex_unlock
1561
 
1562
        stdcall destroy_smap, [current_process]
1563
 
1564
.exit:
2288 clevermous 1565
        pop     edi
1566
        pop     esi
1567
.fail:
1568
        ret
9048 Boppan 1569
.notfound:
1570
        mov     ecx, [current_process]
1571
        add     ecx, PROC.heap_lock
1572
        call    mutex_unlock
1573
        jmp     .exit
2288 clevermous 1574
endp
7965 hidnplayr 1575
 
7967 hidnplayr 1576
 
1577
 
1578
proc    user_ring stdcall, size:dword
1579
 
1580
locals
1581
        virt_ptr        dd ?
1582
        phys_ptr        dd ?
1583
        num_pages       dd ?
1584
endl
1585
 
1586
; Size must be an exact multiple of pagesize
7968 hidnplayr 1587
        mov     eax, [size]
7967 hidnplayr 1588
        test    eax, PAGE_SIZE-1
1589
        jnz     .exit
1590
 
1591
; We must have at least one complete page
1592
        shr     eax, 12
1593
        jz      .exit
1594
        mov     [num_pages], eax
1595
 
1596
; Allocate double the virtual memory
1597
        mov     eax, [size]
1598
        shl     eax, 1
1599
        jz      .exit
1600
        stdcall user_alloc, eax
1601
        test    eax, eax
1602
        jz      .exit
1603
        mov     [virt_ptr], eax
1604
 
1605
; Now allocate physical memory
1606
        stdcall alloc_pages, [num_pages]
1607
        test    eax, eax
1608
        jz      .exit_free_virt
1609
        mov     [phys_ptr], eax
1610
 
1611
; Map first half of virtual memory to physical memory
1612
        push    ecx esi edi
1613
        mov     ecx, [num_pages]
1614
        mov     esi, [virt_ptr]
1615
        mov     edi, [phys_ptr]
1616
  .loop1:
1617
        stdcall map_page, esi, edi, PG_UWR
1618
        add     esi, PAGE_SIZE
1619
        add     edi, PAGE_SIZE
1620
        dec     ecx
1621
        jnz     .loop1
1622
 
1623
; Map second half of virtual memory to same physical memory
7968 hidnplayr 1624
        mov     ecx, [num_pages]
7967 hidnplayr 1625
        mov     edi, [phys_ptr]
1626
  .loop2:
1627
        stdcall map_page, esi, edi, PG_UWR
1628
        add     esi, PAGE_SIZE
1629
        add     edi, PAGE_SIZE
1630
        dec     ecx
1631
        jnz     .loop2
1632
        pop     edi esi ecx
1633
 
1634
        mov     eax, [virt_ptr]
1635
        ret
1636
 
1637
  .exit_free_virt:
1638
        stdcall user_free, [virt_ptr]
1639
 
1640
  .exit:
1641
        xor     eax, eax
1642
        ret
1643
 
9048 Boppan 1644
endp