Subversion Repositories Kolibri OS

Rev

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

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