Subversion Repositories Kolibri OS

Rev

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