Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1573 lines
65 KiB

  1. TITLE GCOMPACT - Global memory compactor
  2. .sall
  3. .xlist
  4. include kernel.inc
  5. .list
  6. WM_COMPACTING = 041h
  7. .386p
  8. include protect.inc
  9. DataBegin
  10. externB Kernel_Flags
  11. externW WinFlags
  12. externW Win386_Blocks
  13. externW PagingFlags
  14. externD gcompact_start
  15. externD gcompact_timer
  16. externD pPostMessage
  17. externD NextCandidate
  18. fSwitchStacks DB 0
  19. fUpDown DB 0
  20. DataEnd
  21. externFP GlobalCompact
  22. ifdef WOW
  23. externFP VirtualFree
  24. endif
  25. sBegin CODE
  26. assumes CS,CODE
  27. assumes fs, nothing
  28. externNP glrudel
  29. externNP gmarkfree
  30. externNP gcheckfree
  31. externNP gdel_free
  32. externNP gsplice
  33. externNP gnotify
  34. externNP genter
  35. externNP gleave
  36. externNP Enter_gmove_stack
  37. externNP Leave_gmove_stack
  38. if KDEBUG
  39. externFP ValidateFreeSpaces
  40. endif
  41. externNP set_selector_address32
  42. ifndef WOW_x86
  43. externNP get_rover_232
  44. endif
  45. externNP AssociateSelector32
  46. externNP alloc_arena_header
  47. externNP free_arena_header
  48. externNP mark_sel_NP
  49. externNP PreAllocArena
  50. externNP DPMIProc
  51. externNP get_physical_address
  52. if KDEBUG
  53. externNP CheckGlobalHeap
  54. endif
  55. ;-----------------------------------------------------------------------;
  56. ; gcompact ;
  57. ; ;
  58. ; Compacts the global heap. ;
  59. ; ;
  60. ; Arguments: ;
  61. ; DX = minimum #contiguous bytes needed ;
  62. ; DS:DI = address of global heap information ;
  63. ; ;
  64. ; Returns: ;
  65. ; AX = size of largest contiguous free block ;
  66. ; ES:DI = arena header of largest contiguous free block ;
  67. ; DX = minimum #contiguous bytes needed ;
  68. ; ;
  69. ; Error Returns: ;
  70. ; ;
  71. ; Registers Preserved: ;
  72. ; SI ;
  73. ; ;
  74. ; Registers Destroyed: ;
  75. ; CX ;
  76. ; ;
  77. ; Calls: ;
  78. ; gcmpheap ;
  79. ; gcheckfree ;
  80. ; gdiscard ;
  81. ; ;
  82. ; History: ;
  83. ; ;
  84. ; Thu Sep 25, 1986 05:34:32p -by- David N. Weise [davidw] ;
  85. ; Added this nifty comment block. ;
  86. ;-----------------------------------------------------------------------;
  87. assumes ds, nothing
  88. assumes es, nothing
  89. cProc gcompact,<PUBLIC,NEAR>
  90. cBegin nogen
  91. CheckKernelDS fs
  92. ReSetKernelDS fs
  93. push esi
  94. smov es,40h
  95. mov ax,es:[6Ch] ; get the BIOS ticker count
  96. sub gcompact_timer.lo,ax
  97. or Kernel_Flags[1],kf1_MEMORYMOVED
  98. mov si, [di].gi_cmpflags
  99. push si
  100. push si
  101. test WinFlags[1], WF1_PAGING
  102. jz short @F
  103. ; First time:
  104. or [di].gi_cmpflags, GA_NOCOMPACT ; No movement
  105. @@:
  106. gcompactl:
  107. if KDEBUG
  108. call ValidateFreeSpaces
  109. endif
  110. push edx ; Save requested size
  111. ife ROM
  112. cmp [di].gi_reserve,edi ; Is there a reserve swap area?
  113. je short gcompact1 ; No, then dont compact lower heap
  114. endif
  115. mov esi,[di].phi_first ; Yes, compact lower heap
  116. mov ebx,pga_next
  117. call gcmpheap
  118. gcompact1:
  119. mov esi,[di].phi_last ; Compact upper heap
  120. mov ebx,pga_prev
  121. call gcmpheap
  122. pop edx ; Get requested size
  123. mov esi,eax ; ES points to largest free block
  124. or eax,eax ; Did we find a free block?
  125. jz short gcompact2 ; No, try discarding
  126. call gcheckfree ; Yes, see if block big enough
  127. jae short gcompactxx ; Yes, all done
  128. gcompact2: ; Discarding allowed?
  129. cmp [di].hi_freeze,di ; Heap frozen?
  130. jne short gcompactxx ; Yes, return
  131. test [di].gi_cmpflags,GA_NODISCARD
  132. jnz short gcompactx ; No, return
  133. test WinFlags[1], WF1_PAGING
  134. jnz short @F
  135. test [di].gi_cmpflags, GA_NOCOMPACT ; Ignore flag if paging
  136. jnz short gcompactx
  137. @@:
  138. push esi
  139. call gdiscard ; No, try discarding
  140. pop ecx ; Saved ESI may be bogus if gdiscard
  141. ; discarded anything...
  142. jnz short gcompactl ; Compact again if anything discarded
  143. mov esi, ecx ; Nothing discarded so ES OK.
  144. gcompactx:
  145. test WinFlags[1], WF1_PAGING
  146. jz short gcompactxx
  147. pop si ; Original flags
  148. mov [di].gi_cmpflags, si
  149. or si, GA_NOCOMPACT+GA_NODISCARD
  150. push si ; Abort next time
  151. test [di].gi_cmpflags, GA_NOCOMPACT
  152. jz short gcompactl
  153. gcompactxx:
  154. add sp,2 ; Toss working flags
  155. push ax
  156. push dx
  157. push es
  158. mov ax,40h
  159. mov es,ax
  160. mov ax,es:[6Ch]
  161. mov si,ax
  162. cmp pPostMessage.sel,0 ; is there a USER around yet?
  163. jz short tock
  164. add gcompact_timer.lo,ax
  165. sub ax,gcompact_start.lo
  166. cmp ax,546 ; 30 secs X 18.2 tics/second
  167. jb short tock
  168. cmp ax,1092 ; 60 secs
  169. ja short tick
  170. mov cx,gcompact_timer.lo ; poor resolution of timer!
  171. jcxz short tick
  172. xchg ax,cx
  173. xor dx,dx
  174. xchg ah,al ; shl 8 DX:AX
  175. xchg dl,al
  176. div cx
  177. cmp ax,32 ; < 12.5% ?
  178. jb short tick
  179. mov ah,al
  180. mov bx,-1 ; broadcast
  181. mov cx,WM_COMPACTING
  182. xor dx,dx
  183. cCall pPostMessage,<bx, cx, ax, dx, dx>
  184. tick: mov gcompact_start.lo,si
  185. mov gcompact_timer.lo,0
  186. tock: pop es
  187. pop dx
  188. pop ax
  189. pop [di].gi_cmpflags
  190. pop esi ; Restore SI
  191. ret
  192. UnSetKernelDS fs
  193. cEnd nogen
  194. ;-----------------------------------------------------------------------;
  195. ; gcmpheap ;
  196. ; ;
  197. ; ;
  198. ; Arguments: ;
  199. ; EBX = pga_prev or pga_next ;
  200. ; EDX = minimum #contiguous bytes needed ;
  201. ; DS:DI = address of global heap information ;
  202. ; FS = Kernel DATA ;
  203. ; ;
  204. ; Returns: ;
  205. ; EAX = largest free block ;
  206. ; ;
  207. ; Error Returns: ;
  208. ; ;
  209. ; Registers Preserved: ;
  210. ; ;
  211. ; Registers Destroyed: ;
  212. ; AX,CX ;
  213. ; ;
  214. ; Calls: ;
  215. ; gslide ;
  216. ; gbestfit ;
  217. ; ;
  218. ; History: ;
  219. ; ;
  220. ; Thu Sep 25, 1986 05:38:16p -by- David N. Weise [davidw] ;
  221. ; Added this nifty comment block. ;
  222. ;-----------------------------------------------------------------------;
  223. assumes ds,nothing
  224. assumes es,nothing
  225. cProc gcmpheap,<PUBLIC,NEAR>
  226. cBegin nogen
  227. CheckKernelDS fs
  228. ReSetKernelDS fs
  229. mov NextCandidate, -1
  230. xor eax,eax ; Nothing found yet
  231. push eax ; Save largest free block so far
  232. gchloop:
  233. cmp ds:[esi].pga_owner,di
  234. je short gchfreefnd
  235. cmp ds:[esi].pga_owner, GA_NOT_THERE
  236. jne short gchnext
  237. mov NextCandidate, -1
  238. gchnext:
  239. mov esi, ds:[esi+ebx]
  240. cmp esi, ds:[esi+ebx] ; Sentinel?
  241. jne short gchloop ; no, continue
  242. gchexit:
  243. pop eax ; Return largest free block in AX
  244. ret
  245. gchfreefnd:
  246. test [di].gi_cmpflags,GA_NOCOMPACT
  247. jnz short gchmaxfree ; No, just compute max free.
  248. cmp [di].hi_freeze,di ; Heap frozen?
  249. jne short gchmaxfree ; Yes, just compute max free.
  250. push esi
  251. test [di].gi_cmpflags,COMPACT_ALLOC
  252. jz short no_hack
  253. call gcheckfree ; Allocating, this big enough?
  254. jb short no_hack ; yes, STOP NOW!
  255. cmp bl,pga_prev ; Compacting upper heap?
  256. jnz short no_hack
  257. test [di].gi_cmpflags,GA_DISCCODE
  258. jz short no_hack
  259. cmp edx,ds:[esi].pga_size
  260. ja short no_hack
  261. mov esi,ds:[esi].pga_next
  262. test ds:[esi].pga_flags,GA_DISCCODE
  263. jnz short hack
  264. cmp ds:[esi].pga_owner,GA_SENTINAL
  265. jz short hack
  266. cmp ds:[esi].pga_owner,GA_NOT_THERE
  267. jnz short no_hack
  268. hack:
  269. pop esi
  270. pop eax
  271. mov eax,esi
  272. ret
  273. no_hack:
  274. pop esi
  275. test byte ptr WinFlags[1], WF1_PAGING ; Paging?
  276. jnz short best_it ; yes, don't slide
  277. call PreAllocArena
  278. jz short gchmaxfree
  279. push edx
  280. call gslide
  281. pop edx
  282. jnz short gchfreefnd
  283. best_it:
  284. push edx
  285. call gfirstfit
  286. pop edx
  287. gchmaxfree:
  288. cmp bl,pga_prev ; Compacting upper heap?
  289. jne short gchnext ; No, dont compute largest free block
  290. cmp ds:[esi].pga_owner,di ; Is current free?
  291. jne gchnext ; No, ignore it then
  292. pop eax ; Recover largest free block so far
  293. push edx
  294. cmp esi,eax ; Same as current?
  295. je short gchmf2 ; Yes, no change then
  296. push eax
  297. cmp ds:[di].gi_reserve,edi ; Is there a code reserve area?
  298. je short gchmf0 ; No, continue
  299. test ds:[di].gi_cmpflags,GA_DISCCODE ; If allocating disc
  300. jnz short gchmf0 ; code ignore the fence
  301. mov ax, [di].gi_disfence_hi
  302. shl eax, 16
  303. mov ax, [di].gi_disfence_lo
  304. mov edx, ds:[esi].pga_size ; Size of this block
  305. add edx, ds:[esi].pga_address ; End of this block
  306. sub eax, edx ; Fence above it?
  307. jae short gchmf0 ; yes, use the whole block
  308. neg eax ; Amount above the fence
  309. cmp eax, ds:[di].gi_reserve ; Above reserve?
  310. jae short gchmf0 ; yes, use all of it
  311. sub edx, eax ; Subtract off that above fence
  312. ja short gchmf00 ; Use as size of block
  313. pop eax
  314. jmps gchmf2
  315. gchmf0:
  316. mov edx, ds:[esi].pga_size ; Size of this block
  317. gchmf00:
  318. pop eax
  319. or eax,eax ; First time?
  320. jz short gchmf1 ; Yes, special case
  321. cmp edx, ds:[eax].pga_size ; Is it bigger?
  322. jb short gchmf2 ; No, do nothing
  323. gchmf1:
  324. mov eax,esi ; Yes, remember biggest free block
  325. gchmf2:
  326. pop edx
  327. push eax ; Save largest free block so far
  328. test PagingFlags, 2 ; Idle time compaction!
  329. jnz gchexit
  330. jmp gchnext ; Go process next block
  331. UnSetKernelDS fs
  332. cEnd nogen
  333. ;-----------------------------------------------------------------------;
  334. ; gslide ;
  335. ; ;
  336. ; Sees if next/previous block can slide into the passed free block. ;
  337. ; ;
  338. ; Arguments: ;
  339. ; FS:ESI = free block ;
  340. ; DS:DI = address of global heap information ;
  341. ; CX = #arena entries left to examine ;
  342. ; EBX = pga_next or pga_prev ;
  343. ; ;
  344. ; Returns: ;
  345. ; ZF = 0 if block found and moved into passed free block ;
  346. ; FS:ESI points to new free block ;
  347. ; FS:EDX points to new free block ;
  348. ; ;
  349. ; ZF = 1 if no block found ;
  350. ; FS:ESI points to original free block ;
  351. ; ;
  352. ; Error Returns: ;
  353. ; ;
  354. ; Registers Preserved: ;
  355. ; ;
  356. ; Registers Destroyed: ;
  357. ; EAX,EDX ;
  358. ; ;
  359. ; Calls: ;
  360. ; ;
  361. ; History: ;
  362. ; ;
  363. ; Thu Sep 25, 1986 05:58:25p -by- David N. Weise [davidw] ;
  364. ; Added this nifty comment block. ;
  365. ;-----------------------------------------------------------------------;
  366. assumes ds, nothing
  367. assumes es, nothing
  368. cProc gslide,<PUBLIC,NEAR>
  369. cBegin nogen
  370. push esi
  371. mov esi,ds:[ebx+esi]
  372. mov edx,esi ; Source of move in EDX
  373. call gmoveable
  374. pop esi
  375. jz short gslide_no_move
  376. call gmovebusy ; Handle exact fits etc!!
  377. call gpagingcandidate
  378. if KDEBUG
  379. cmp edx, ds:[esi+ebx] ; Are we adjacent?
  380. je short gslide_adjacent
  381. int 3
  382. int 3
  383. gslide_adjacent:
  384. endif
  385. mov esi, edx
  386. or esi, esi ; ZF = 0
  387. gslide_no_move:
  388. ret
  389. cEnd nogen
  390. ;-----------------------------------------------------------------------;
  391. ; gmove ;
  392. ; ;
  393. ; Moves a moveable block into the top part of a free block. The low ;
  394. ; order bit of the source and destination may be either set or reset. ;
  395. ; If set, then this routine does NOT move the arena header paragraph. ;
  396. ; If the bit is reset, then the arena header is moved. Only the low ;
  397. ; order bit of EDX is examined, and the low order bit of ESI is assumed ;
  398. ; to the same. ;
  399. ; ;
  400. ; Arguments: ;
  401. ; DS:DI = master object ;
  402. ; ES:0 = address of destination block ;
  403. ; FS:ESI = arena of destination block ;
  404. ; FS:EDX = arena of source block ;
  405. ; ECX = # bytes to move ;
  406. ; ;
  407. ; Returns: ;
  408. ; DS:DI = master object (it may have moved) ;
  409. ; ;
  410. ; Error Returns: ;
  411. ; ;
  412. ; Registers Preserved: ;
  413. ; AX,BX,CX,DX,DI,SI,ES ;
  414. ; ;
  415. ; Registers Destroyed: ;
  416. ; none ;
  417. ; ;
  418. ; Calls: ;
  419. ; gnotify ;
  420. ; ;
  421. ; History: ;
  422. ; ;
  423. ; Thu Sep 25, 1986 03:31:51p -by- David N. Weise [davidw] ;
  424. ; Added this nifty comment block. ;
  425. ;-----------------------------------------------------------------------;
  426. assumes ds, nothing
  427. assumes es, nothing
  428. cProc gmove,<PUBLIC,NEAR>
  429. cBegin nogen
  430. CheckKernelDS fs
  431. ReSetKernelDS fs
  432. push es
  433. pushad
  434. mov eax, edx
  435. push esi ; Save destination
  436. mov edx, ecx ; # bytes passed in in ECX
  437. mov bx, ds:[eax].pga_handle ; BX = handle of source
  438. Handle_To_Sel bl
  439. mov cx, bx ; CX = client data address of dest.
  440. push eax
  441. push edx ; Save #paragraphs
  442. mov ax, GN_MOVE
  443. push cx ; Save client data address
  444. call gnotify ; Call global notify procedure
  445. pop cx
  446. pop edx ; EDX = #paragraphs to move
  447. pop esi ; ESI = source arena
  448. pop edi ; EDI = destination arena
  449. ; Save DS value AFTER call to gnotify, as the master object might be the
  450. ; block we are moving and thus changed by the global heap notify proc.
  451. push gs
  452. smov gs, ds
  453. mov ax,ss ; Are we about to move the stack?
  454. cmp ax,cx
  455. mov cx,0 ; ...assume no
  456. jne short stack_no_move
  457. mov cx, ax ; Selector does not change!
  458. call Enter_gmove_stack ; switch to temporary stack
  459. stack_no_move:
  460. mov fSwitchStacks,cl ; Remember if we switched
  461. xor cx, cx ; Ready for result of compare
  462. mov eax, gs:[edi].pga_address
  463. cmp gs:[esi].pga_address, eax
  464. adc ch, 0
  465. mov fUpDown,ch
  466. mov ecx, edx ; # bytes to move
  467. shr ecx, 2 ; # dwords to move
  468. jecxz all_done
  469. cmp fUpDown, 0
  470. jnz short move_it_up
  471. ; MOVE IT DOWN
  472. cld
  473. xor esi, esi
  474. jmps move_it
  475. move_it_up:
  476. std
  477. mov esi, ecx
  478. dec esi
  479. shl esi,2
  480. move_it:
  481. mov ds, bx ; DS:SI = first word in source block
  482. mov edi, esi
  483. ifdef WOW_x86
  484. smov es,FLAT_SEL ; 23:EAX => pga_address or taget
  485. add edi,eax
  486. endif; WOW_x86
  487. rep movs dword ptr [edi], dword ptr [esi]
  488. ; 386 BUG, ECX, ESI, EDI ARE NOW TRASHED
  489. all_done:
  490. smov ds, gs
  491. cCall set_selector_address32,<bx,eax> ; Update source selector
  492. cmp fSwitchStacks,cl ; Switch to new stack if any
  493. je short move_exit
  494. call Leave_gmove_stack
  495. move_exit:
  496. pop gs
  497. popad
  498. pop es
  499. cld ; Protect people like MarkCl from themselves
  500. ret
  501. UnSetKernelDS fs
  502. cEnd nogen
  503. ;-----------------------------------------------------------------------;
  504. ; gbestfit ;
  505. ; ;
  506. ; Searches for the largest moveable block that will fit in the passed ;
  507. ; free block. ;
  508. ; ;
  509. ; Arguments: ;
  510. ; DS:ESI = free block ;
  511. ; DS:DI = address of global heap information ;
  512. ; CX = #arena entries left to examine ;
  513. ; EBX = pga_next or pga_prev ;
  514. ; ;
  515. ; Returns: ;
  516. ; ZF = 1 if block found & moved into free block w/ no extra room. ;
  517. ; DS:ESI = busy block before/after new busy block. ;
  518. ; ;
  519. ; ZF = 0 if DS:ESI points to a free block, either the ;
  520. ; original one or what is left over after moving a block ;
  521. ; into it. ;
  522. ; ;
  523. ; Error Returns: ;
  524. ; ;
  525. ; Registers Preserved: ;
  526. ; ;
  527. ; Registers Destroyed: ;
  528. ; DX,SI ;
  529. ; ;
  530. ; Calls: ;
  531. ; gmoveable ;
  532. ; gmovebusy ;
  533. ; ;
  534. ; History: ;
  535. ; ;
  536. ; Thu Sep 25, 1986 05:52:12p -by- David N. Weise [davidw] ;
  537. ; Added this nifty comment block. ;
  538. ;-----------------------------------------------------------------------;
  539. assumes ds,nothing
  540. assumes es,nothing
  541. cProc gfirstfit,<PUBLIC,NEAR>
  542. cBegin nogen
  543. CheckKernelDS fs
  544. ReSetKernelDS fs
  545. push ecx
  546. mov edx, esi ; Save free block
  547. gbfrestart:
  548. call PreAllocArena ; Abort if no free arenas
  549. jz short gbfabort
  550. mov eax,ds:[edx].pga_size ; Compute max size to look for
  551. jmps gbfnext
  552. gbfloop:
  553. cmp ds:[esi].pga_owner,di ; Is this block busy?
  554. je short gbfnext ; No, continue
  555. cmp ds:[esi].pga_size,eax ; Yes, is block bigger than max size?
  556. ja short gbfnext ; Yes, continue
  557. cmp ds:[esi].pga_owner,GA_NOT_THERE ; Is this even here?
  558. je short gbfnext ; No, continue
  559. call gmoveable ; Yes, is it moveable
  560. jnz short gbffound
  561. gbfnext: ; No, continue
  562. mov esi, ds:[esi+ebx] ; Skip past this block
  563. cmp esi, ds:[esi+ebx] ; Sentinel?
  564. jne gbfloop
  565. gbfabort:
  566. mov esi, edx ; Return original free block in ESI
  567. jmps gfirstfit1 ; Nothing found!
  568. gbffound:
  569. xchg edx, esi ; Source of move
  570. call gmovebusy ; Yes, move it into free block
  571. mov NextCandidate, -1
  572. call gpagingcandidate
  573. mov NextCandidate, -1
  574. xchg esi, edx ; Put free block in esi
  575. call gwin386discard
  576. xchg esi, edx
  577. cmp edx, ds:[esi+ebx] ; Blocks adjacent?
  578. je short gfirstfit1 ; Yes, may have coalesced.
  579. ; Return busy block in ESI
  580. mov esi, ds:[esi+ebx] ; Get block after busy block
  581. cmp ds:[esi].pga_owner,di ; Is this block busy?
  582. jne short gfirstfit1 ; Yes, fit was exact
  583. xchg edx, esi ; EDX is new free block
  584. jmps gbfrestart ; Start search from old busy block
  585. gfirstfit1:
  586. pop ecx
  587. ret
  588. UnSetKernelDS fs
  589. cEnd nogen
  590. ;-----------------------------------------------------------------------;
  591. ; gmovebusy ;
  592. ; ;
  593. ; Subroutine to move a busy block to a free block of the same size, ;
  594. ; preserving the appropriate arena header fields, freeing the old ;
  595. ; busy block and updating the handle table entry to point to the ;
  596. ; new location of the block. ;
  597. ; ;
  598. ; [tonyg] ;
  599. ; The above has been inaccurate for a while - the destination is NOT ;
  600. ; necessarily free, NOR is it always the same size! ;
  601. ; ;
  602. ; It will now handle everything gslidecommon used to do! ;
  603. ; ;
  604. ; Arguments: ;
  605. ; BX = ga_prev or ga_next ;
  606. ; DS:EDX = old busy block location ;
  607. ; DS:ESI = new busy block location ;
  608. ; DS:DI = address of global heap information ;
  609. ; ;
  610. ; Returns: ;
  611. ; DS:ESI = points to new busy block arena header ;
  612. ; DS:EDX = points to free block where block used to be ;
  613. ; (may be coalesced) ;
  614. ; ;
  615. ; Error Returns: ;
  616. ; ;
  617. ; Registers Preserved: ;
  618. ; EBX,ECX ;
  619. ; ;
  620. ; Registers Destroyed: ;
  621. ; EAX ;
  622. ; ;
  623. ; Calls: ;
  624. ; ;
  625. ; History: ;
  626. ; ;
  627. ; Mon Jun 22, 1987 11:39:56p -by- David N. Weise [davidw] ;
  628. ; Made it jump off to gslidecommon when appropriate. ;
  629. ; ;
  630. ; Mon Oct 27, 1986 10:17:16p -by- David N. Weise [davidw] ;
  631. ; Made the lru list be linked arenas, so we must keep the list correct ;
  632. ; here. ;
  633. ; ;
  634. ; Thu Sep 25, 1986 05:49:25p -by- David N. Weise [davidw] ;
  635. ; Added this nifty comment block. ;
  636. ;-----------------------------------------------------------------------;
  637. assumes ds, nothing
  638. assumes es, nothing
  639. cProc gmovebusy,<PUBLIC,NEAR>
  640. cBegin nogen
  641. if KDEBUG
  642. cmp ds:[esi].pga_owner, GA_NOT_THERE
  643. jne short @F
  644. AAARRRGGGHHH:
  645. int 3
  646. int 3
  647. @@:
  648. cmp ds:[edx].pga_owner, GA_NOT_THERE
  649. je AAARRRGGGHHH
  650. endif
  651. push ecx
  652. mov ecx,ds:[edx].pga_size ; ECX = size of source
  653. cmp ds:[esi].pga_owner,di ; Is destination busy?
  654. jne gmbexactfit ; Yes, then don't create extra block
  655. mov eax, ds:[esi].pga_freeprev
  656. call gdel_free ; Take off free list now!
  657. cmp ecx,ds:[esi].pga_size ; No, source and destination same size?
  658. je short gmbexactfit ; Yes, then don't create extra block
  659. jb short gmbsplice ; Destination is larger, split it
  660. if KDEBUG
  661. ; MUST BE ADJACENT IF DESTINATION
  662. cmp ds:[esi+ebx], edx ; SMALLER THAN SOURCE!!!
  663. je short gmb_adjust
  664. int 3
  665. int 3
  666. gmb_adjust:
  667. endif
  668. push ecx ; source length
  669. push ds:[esi].pga_size ; destination length
  670. cmp bl, pga_next
  671. je short gmb_down
  672. ; Moving busy block up
  673. mov eax, ds:[edx].pga_address ; Correct destination address
  674. add eax, ds:[esi].pga_size
  675. mov ds:[esi].pga_address, eax
  676. call gmb_gmove
  677. jmps gmb_adjusted
  678. gmb_down: ; Moving busy block down
  679. call gmb_gmove
  680. mov ecx, ds:[esi].pga_address ; Correct new free block address
  681. add ecx, ds:[edx].pga_size
  682. mov ds:[edx].pga_address, ecx
  683. gmb_adjusted:
  684. pop ds:[edx].pga_size ; Swap sizes
  685. pop ds:[esi].pga_size
  686. jmps gmb_moved
  687. gmbsplice:
  688. push ecx
  689. push edx
  690. mov edx, ecx ; # bytes in block to make
  691. cmp bl, pga_prev
  692. je short gmb_backward
  693. call gsplice ; Split the block
  694. jmps gmb_spliced
  695. gmb_backward:
  696. neg edx
  697. add edx, ds:[esi].pga_size ; Second block will be used
  698. call gsplice
  699. xchg esi, edx
  700. gmb_spliced:
  701. mov ds:[esi].pga_owner,1 ; Mark new block busy
  702. push esi ; New free block
  703. mov esi, edx ; Block to free
  704. mov edx, eax
  705. call gmarkfree
  706. pop esi ; New free block
  707. pop edx ; Source for copy
  708. pop ecx
  709. gmbexactfit:
  710. call gmb_gmove
  711. gmb_moved:
  712. mov eax, esi
  713. mov esi, edx
  714. xor edx, edx
  715. call gmarkfree ; Free old block
  716. mov ecx,esi ; New free block
  717. mov esi,eax ; New block
  718. or dx,dx
  719. jz short gmb1
  720. mov ds:[esi].pga_handle,dx ; Set back link to handle in new block
  721. cCall AssociateSelector32,<dx,esi> ; Associate with new arena
  722. xor dx,dx ; Set Z flag
  723. gmb1:
  724. mov edx,ecx
  725. gmbexit:
  726. pop ecx
  727. ret
  728. cEnd nogen
  729. ;
  730. ; Common code for gmovebusy
  731. ;
  732. cProc gmb_gmove,<PUBLIC,NEAR>
  733. cBegin nogen
  734. push ecx ; # bytes to move
  735. push dword ptr ds:[edx].pga_count
  736. push ds:[edx].pga_owner
  737. push ds:[edx].pga_lruprev
  738. push ds:[edx].pga_lrunext
  739. pop ds:[esi].pga_lrunext ; Copy client words to new header
  740. pop ds:[esi].pga_lruprev
  741. pop ds:[esi].pga_owner
  742. pop dword ptr ds:[esi].pga_count
  743. cmp ds:[esi].pga_lruprev,edi
  744. jz short no_link
  745. cmp [di].gi_lruchain,edx
  746. jnz short didnt_move_head
  747. mov [di].gi_lruchain,esi
  748. didnt_move_head:
  749. mov ecx,ds:[edx].pga_lruprev
  750. mov ds:[ecx].pga_lrunext,esi ; Update the lru list
  751. mov ecx,ds:[edx].pga_lrunext
  752. mov ds:[ecx].pga_lruprev,esi ; Update the lru list
  753. no_link:
  754. pop ecx
  755. ifndef WOW_x86
  756. call get_rover_232
  757. endif
  758. jmp gmove ; Move the client data
  759. cEnd nogen
  760. ;-----------------------------------------------------------------------;
  761. ; gmoveable ;
  762. ; ;
  763. ; Tests if an ojbect is moveable. Non moveable blocks are: ;
  764. ; Fixed blocks, moveable blocks that are locked, moveable blocks ;
  765. ; going up, discardable code going down. ;
  766. ; ;
  767. ; Arguments: ;
  768. ; FS:ESI = arena header of object ;
  769. ; DS:DI = address of global heap information ;
  770. ; BX = ga_next or ga_prev ;
  771. ; ;
  772. ; Returns: ;
  773. ; ZF = 0 if object moveable ;
  774. ; ZF = 1 if object not moveable ;
  775. ; ;
  776. ; Error Returns: ;
  777. ; ;
  778. ; Registers Preserved: ;
  779. ; All ;
  780. ; ;
  781. ; Registers Destroyed: ;
  782. ; ;
  783. ; Calls: ;
  784. ; nothing ;
  785. ; ;
  786. ; History: ;
  787. ; ;
  788. ; Wed Oct 15, 1986 05:04:39p -by- David N. Weise [davidw] ;
  789. ; Moved he_count to ga_count. ;
  790. ; ;
  791. ; Thu Sep 25, 1986 05:42:17p -by- David N. Weise [davidw] ;
  792. ; Added this nifty comment block. ;
  793. ;-----------------------------------------------------------------------;
  794. assumes ds, nothing
  795. assumes es, nothing
  796. cProc gmoveable,<PUBLIC,NEAR>
  797. cBegin nogen
  798. test ds:[esi].pga_handle,GA_FIXED ; If no handle then fixed
  799. jnz short gmfixed
  800. cmp ds:[esi].pga_count,bh ; If locked then fixed
  801. jne short gmfixed
  802. test ds:[esi].pga_flags,GA_DISCCODE ; If discardable code
  803. jz short gmnotcode
  804. cmp bl,pga_next ; Discardable code can only
  805. ret ; move up in memory
  806. gmnotcode:
  807. cmp [di].gi_reserve,edi ; If no reserved code area?
  808. je short gmokay ; Then anything can move up
  809. cmp bl,pga_prev ; Otherwise can only move down
  810. ret ; in memory
  811. gmfixed:
  812. or bh,bh ; Return with ZF = 1 if
  813. ret ; not moveable
  814. gmokay:
  815. or esi,esi
  816. ret
  817. cEnd nogen
  818. ;-----------------------------------------------------------------------;
  819. ; gdiscard ;
  820. ; ;
  821. ; Subroutine to walk LRU chain, discarding objects until the #paras ;
  822. ; discarded, plus the biggest free block is greater than the #paras ;
  823. ; we are looking for. ;
  824. ; ;
  825. ; Arguments: ;
  826. ; EAX = size of largest free block so far ;
  827. ; EDX = minimum #bytes needed ;
  828. ; DS:DI = address of global heap information ;
  829. ; ;
  830. ; Returns: ;
  831. ; ZF = 0 if one or more objects discarded. ;
  832. ; ZF = 1 if no objects discarded. ;
  833. ; ;
  834. ; Error Returns: ;
  835. ; ;
  836. ; Registers Preserved: ;
  837. ; AX,DX,DI ;
  838. ; ;
  839. ; Registers Destroyed: ;
  840. ; BX,CX,ES ;
  841. ; ;
  842. ; Calls: ;
  843. ; ;
  844. ; History: ;
  845. ; Mon Oct 27, 1986 09:34:45p -by- David N. Weise [davidw] ;
  846. ; The glru list was reworked to link the arenas, not using the handle ;
  847. ; table as a middle man. Because of this change glruprev was moved ;
  848. ; inline and the code shortened up again. ;
  849. ; ;
  850. ; Wed Oct 15, 1986 05:04:39p -by- David N. Weise [davidw] ;
  851. ; Moved he_count to ga_count. ;
  852. ; ;
  853. ; Thu Sep 25, 1986 05:45:31p -by- David N. Weise [davidw] ;
  854. ; Shortened it up a bit and added this nifty comment block. ;
  855. ;-----------------------------------------------------------------------;
  856. assumes ds, nothing
  857. assumes es, nothing
  858. cProc gdiscard,<PUBLIC,NEAR>
  859. cBegin nogen
  860. push eax
  861. push edx
  862. mov [di].hi_ncompact,0 ; Clear compaction flag
  863. sub edx,eax ; How much to discard before
  864. mov [di].hi_distotal,edx ; compacting again.
  865. xor ebx,ebx ; EBX = amount of DISCCODE below fence
  866. test [di].gi_cmpflags,GA_DISCCODE
  867. jnz short fence_not_in_effect0
  868. mov cx,[di].gi_lrucount
  869. jcxz fence_not_in_effect0 ; All done if LRU chain empty
  870. mov ax, [di].gi_disfence_hi
  871. shl eax, 16
  872. mov ax, [di].gi_disfence_lo
  873. push edx
  874. mov edx, eax
  875. add edx, ds:[edi].gi_reserve
  876. mov esi,[di].gi_lruchain ; ESI -> most recently used (ga_lruprev
  877. gdloop0: ; is the least recently used)
  878. mov esi,ds:[esi].pga_lruprev ; Move to next block in LRU chain
  879. test ds:[esi].pga_flags,GA_DISCCODE ; Discardable code?
  880. jz short gdloop0a ; No, ignore
  881. cmp edx, ds:[esi].pga_address
  882. jbe short gdinclude
  883. cmp eax, ds:[esi].pga_address ; Yes, is this code fenced off?
  884. jbe short gdloop0a ; No, ignore
  885. gdinclude:
  886. add ebx,ds:[esi].pga_size ; Yes, accumulate size of discardable
  887. gdloop0a: ; code below the fence
  888. loop gdloop0
  889. pop edx
  890. fence_not_in_effect0:
  891. mov esi,[di].gi_lruchain
  892. cmp [di].gi_lrucount, 0
  893. je short gdexit
  894. push ds:[esi].pga_lruprev
  895. push [di].gi_lrucount
  896. gdloop:
  897. pop cx
  898. pop eax
  899. jcxz gdexit ; No more see if we discarded anything
  900. mov esi, eax ; ES on stack may be invalid if count 0
  901. dec cx
  902. push ds:[esi].pga_lruprev ; Save next handle from LRU chain
  903. push cx
  904. cmp ds:[esi].pga_count,0 ; Is this handle locked?
  905. jne short gdloop ; Yes, ignore it then
  906. test [di].gi_cmpflags,GA_DISCCODE
  907. jnz short fence_not_in_effect
  908. test ds:[esi].pga_flags,GA_DISCCODE
  909. jz short fence_not_in_effect
  910. or ebx,ebx ; Discardable code below fence?
  911. jz short gdloop ; No, cant discard then
  912. cmp ebx,ds:[esi].pga_size ; Yes, more than size of this block?
  913. jb short gdloop ; No, cant discard then
  914. sub ebx,ds:[esi].pga_size ; Yes, reduce size of code below fence
  915. fence_not_in_effect:
  916. push ebx
  917. call DiscardCodeSegment
  918. pop ebx
  919. jnz short discarded_something
  920. test [di].hi_ncompact,10h ; did a GlobalNotify proc free enough?
  921. jz short gdloop
  922. jmps enough_discarded
  923. discarded_something:
  924. test [di].hi_ncompact,10h ; did a GlobalNotify proc free enough?
  925. jnz short enough_discarded
  926. or [di].hi_ncompact,1 ; Remember we discarded something
  927. sub [di].hi_distotal,eax ; Have we discarded enough yet?
  928. ja short gdloop ; No, look at next handle
  929. enough_discarded:
  930. pop cx ; Flush enumeration counter
  931. pop ecx ; and saved ESI
  932. gdexit:
  933. cmp [di].hi_ncompact,0 ; Return with Z flag set or clear
  934. pop edx
  935. pop eax
  936. ret
  937. cEnd nogen
  938. ;-----------------------------------------------------------------------;
  939. ; DiscardCodeSegment ;
  940. ; ;
  941. ; Discards the given segment. Calls gnotify to fix stacks, entry ;
  942. ; points, thunks, and prologs. Then glrudel removes it from the lru ;
  943. ; list and gmarkfree finally gets rid of it. ;
  944. ; ;
  945. ; Arguments: ;
  946. ; DS:DI => BurgerMaster ;
  947. ; ES = Address of segment to discard ;
  948. ; ;
  949. ; Returns: ;
  950. ; AX = size discarded ;
  951. ; ZF = 0 ok ;
  952. ; ;
  953. ; Error Returns: ;
  954. ; ;
  955. ; Registers Preserved: ;
  956. ; DI,SI,DS,ES ;
  957. ; ;
  958. ; Registers Destroyed: ;
  959. ; BX,CX,DX ;
  960. ; ;
  961. ; Calls: ;
  962. ; gnotify ;
  963. ; glrudel ;
  964. ; gmarkfree ;
  965. ; ;
  966. ; History: ;
  967. ; ;
  968. ; Fri Jun 12, 1987 -by- Bob Matthews [bobm] ;
  969. ; Made FAR. ;
  970. ; ;
  971. ; Sun Apr 19, 1987 12:05:40p -by- David N. Weise [davidw] ;
  972. ; Moved it here from InitTask, so that FirstTime could use it. ;
  973. ;-----------------------------------------------------------------------;
  974. assumes ds, nothing
  975. assumes es, nothing
  976. cProc DiscardCodeSegment,<PUBLIC,NEAR>
  977. cBegin nogen
  978. push esi
  979. mov bx,ds:[esi].pga_handle ; BX = handle
  980. mov al,GN_DISCARD ; AX = GN_DISCARD
  981. call gnotify
  982. jz short cant_discard ; Skip this handle if not discardable
  983. call glrudel ; Delete handle from LRU chain
  984. push ds:[esi].pga_owner ; Save owner field
  985. mov eax,ds:[esi].pga_size ; Save size
  986. xor edx,edx
  987. call gmarkfree ; Free the block associated with this handle
  988. mov bx,dx
  989. pop cx ; Owner
  990. cCall mark_sel_NP,<bx,cx>
  991. cant_discard:
  992. pop esi
  993. ret
  994. cEnd nogen
  995. ;-----------------------------------------------------------------------;
  996. ; ShrinkHeap ;
  997. ; ;
  998. ; Tries to return DPMI memory blocks to DPMI memory manager. ;
  999. ; ;
  1000. ; Arguments: ;
  1001. ; ;
  1002. ; Returns: ;
  1003. ; ;
  1004. ; Error Returns: ;
  1005. ; ;
  1006. ; Registers Preserved: ;
  1007. ; ;
  1008. ; Registers Destroyed: ;
  1009. ; ;
  1010. ; Calls: ;
  1011. ; InnerShrinkHeap ;
  1012. ; ;
  1013. ;-----------------------------------------------------------------------;
  1014. assumes ds, nothing
  1015. assumes es, nothing
  1016. cProc ShrinkHeap,<PUBLIC,NEAR>
  1017. cBegin nogen
  1018. push ds
  1019. GENTER32
  1020. ReSetKernelDS FS
  1021. cCall InnerShrinkHeap
  1022. jnz short sh_maybe_more
  1023. and PagingFlags, NOT 8 ; Don't call back if # win386
  1024. ; didn't change
  1025. sh_maybe_more:
  1026. GLEAVE32
  1027. UnSetKernelDS FS
  1028. pop ds
  1029. ret
  1030. cEnd nogen
  1031. ;-----------------------------------------------------------------------;
  1032. ; InnerShrinkHeap ;
  1033. ; ;
  1034. ; Checks heap to see if there are any blocks to return to Win386 ;
  1035. ; Compacts if there are Win386 blocks around AND there is more ;
  1036. ; than 512k free. ;
  1037. ; Returns any completely free Win386 block to Win386. ;
  1038. ; ;
  1039. ; Arguments: ;
  1040. ; FS = Kernel's DS ;
  1041. ; EDI = 0 ;
  1042. ; ;
  1043. ; Returns: ;
  1044. ; Z flag set if no blocks returned, Z clear if 1 or more returned.;
  1045. ; ;
  1046. ; Error Returns: ;
  1047. ; ;
  1048. ; Registers Preserved: ;
  1049. ; All ;
  1050. ; ;
  1051. ; Registers Destroyed: ;
  1052. ; ;
  1053. ; Calls: ;
  1054. ; UnlinkWin386Block ;
  1055. ; ;
  1056. ;-----------------------------------------------------------------------;
  1057. assumes ds, nothing
  1058. assumes es, nothing
  1059. cProc InnerShrinkHeap,<PUBLIC,NEAR>
  1060. cBegin nogen
  1061. CheckKernelDS FS
  1062. ReSetKernelDS FS
  1063. pushad
  1064. push Win386_Blocks
  1065. cmp Win386_Blocks, 0
  1066. je short sh_done
  1067. ; First count up free blocks
  1068. mov esi, [edi].phi_first
  1069. scan_loop:
  1070. mov esi, [esi].pga_freenext
  1071. scan_next:
  1072. cmp esi, [esi].pga_next ; Sentinel?
  1073. je short sh_done ; yes, all done
  1074. mov ebx, [esi].pga_prev
  1075. cmp [ebx].pga_owner, GA_NOT_THERE
  1076. jne short scan_loop
  1077. mov ecx, [esi].pga_next
  1078. cmp [ecx].pga_owner, GA_NOT_THERE
  1079. jne short scan_loop
  1080. mov eax, [ecx].pga_next ; Block after NOT_THERE block
  1081. cmp eax, [eax].pga_next ; Sentinel?
  1082. je short sh_done ; yes, don't try to unlink
  1083. ; Have block to return
  1084. push [esi].pga_freeprev ; Current block will be freed
  1085. cCall UnlinkWin386Block
  1086. pop esi ; Continue before block freed
  1087. jmps scan_loop
  1088. sh_done:
  1089. pop ax ; Starting value of Win386_Blocks
  1090. cmp ax, Win386_Blocks ; Set Z flag if heap didn't shrink
  1091. popad
  1092. UnSetKernelDS FS
  1093. ret
  1094. cEnd
  1095. ;-----------------------------------------------------------------------;
  1096. ; UnlinkWin386Block ;
  1097. ; ;
  1098. ; Returns a block to Win386 and unlinks it from the heap. ;
  1099. ; ;
  1100. ; Arguments: ;
  1101. ; EBX Block previous to block to be unlinked ;
  1102. ; ESI Block to be unlinked ;
  1103. ; ECX Block after to block to be unlinked ;
  1104. ; ;
  1105. ; Returns: ;
  1106. ; ESI Block previous to EBX ;
  1107. ; ;
  1108. ; Error Returns: ;
  1109. ; ;
  1110. ; Registers Preserved: ;
  1111. ; ECX, DX, EDI, DS, ES ;
  1112. ; ;
  1113. ; Registers Destroyed: ;
  1114. ; EAX, EBX, EDX ;
  1115. ; ;
  1116. ; Calls: ;
  1117. ; GlobalCompact ;
  1118. ; UnlinkWin386Block ;
  1119. ; ;
  1120. ; History: ;
  1121. ; ;
  1122. ;-----------------------------------------------------------------------;
  1123. assumes ds, nothing
  1124. assumes es, nothing
  1125. cProc UnlinkWin386Block,<PUBLIC,NEAR>
  1126. cBegin nogen
  1127. CheckKernelDS FS
  1128. ReSetKernelDS FS
  1129. push dx
  1130. mov edx, [ecx].pga_next ; Block after all this
  1131. cmp edx, [edx].pga_next ; Last sentinel?
  1132. je RSHORT dont_do_it ; Never free last block
  1133. if KDEBUG
  1134. push edx
  1135. mov eax, [esi].pga_size
  1136. mov edx, eax
  1137. shr edx, 16
  1138. krDebugOut <DEB_TRACE OR DEB_krMemMan>, "UnlinkWin386Block: releasing #dx#AX bytes"
  1139. pop edx
  1140. endif
  1141. push esi
  1142. call gdel_free ; Remove from free list
  1143. ifdef WOW
  1144. push edx
  1145. push ebx
  1146. push ecx
  1147. mov eax,MEM_RELEASE
  1148. mov edi,[esi].pga_size
  1149. cCall VirtualFree,<[ebx].pga_lrunext,edi,eax>
  1150. pop ecx
  1151. pop ebx
  1152. pop edx
  1153. else
  1154. mov esi, [ebx].pga_lrunext ; Saved WIN386 handle
  1155. mov di, si
  1156. shr esi, 16 ; Put in SI:DI
  1157. DPMICALL 0502h ; Free Memory Block
  1158. endif; WOW
  1159. xor edi, edi
  1160. pop esi
  1161. dec Win386_Blocks
  1162. mov eax, [ebx].pga_prev ; Block before all this
  1163. mov [eax].pga_next, edx ; Unlink them.
  1164. mov [edx].pga_prev, eax
  1165. cCall free_arena_header,<ebx> ; Free the arena headers
  1166. cCall free_arena_header,<esi>
  1167. cCall free_arena_header,<ecx>
  1168. mov esi, eax ; For gfreeall
  1169. sub [edi].hi_count, 3
  1170. if KDEBUG
  1171. call CheckGlobalHeap
  1172. endif
  1173. dont_do_it:
  1174. pop dx
  1175. ret
  1176. UnSetKernelDS FS
  1177. cEnd nogen
  1178. cProc gpagingcandidate,<PUBLIC,NEAR>
  1179. cBegin nogen
  1180. CheckKernelDS FS
  1181. ReSetKernelDS FS
  1182. test byte ptr WinFlags[1], WF1_PAGING ; Paging?
  1183. jz short gpc_not_paging
  1184. pushad
  1185. mov ebx, ds:[esi].pga_address
  1186. mov esi, ds:[esi].pga_size
  1187. add esi, ebx ; End of region
  1188. shr ebx, 12
  1189. shr esi, 12
  1190. cmp ebx, NextCandidate
  1191. jb short gpc_use_this_page
  1192. mov ebx, NextCandidate ; Start the region here
  1193. gpc_use_this_page:
  1194. cmp esi, ebx
  1195. jne short call_win386
  1196. mov NextCandidate, ebx
  1197. jmps gpc_done
  1198. call_win386:
  1199. mov NextCandidate, -1
  1200. sub esi, ebx ; number of pages
  1201. mov di, si
  1202. shr esi, 16
  1203. mov cx, bx
  1204. shr ebx, 16
  1205. DPMICALL 0700h ; Page Candidate
  1206. gpc_done:
  1207. popad
  1208. gpc_not_paging:
  1209. ret
  1210. UnSetKernelDS FS
  1211. cEnd nogen
  1212. assumes ds, nothing
  1213. assumes es, nothing
  1214. cProc gwin386discard,<PUBLIC,NEAR>
  1215. cBegin nogen
  1216. CheckKernelDS FS
  1217. ReSetKernelDS FS
  1218. cmp ds:[esi].pga_size, 4096
  1219. jb short not_a_chance ; Quick exit
  1220. cmp ds:[esi].pga_size, 16*1024
  1221. jb short inform_later
  1222. pushad
  1223. mov ebx, ds:[esi].pga_address
  1224. mov esi, ds:[esi].pga_size
  1225. mov di, si
  1226. shr esi, 16 ; SI:DI is # bytes to discard
  1227. mov cx, bx
  1228. shr ebx, 16 ; BX:CX is first bytes to discard
  1229. DPMICALL 0703h
  1230. popad
  1231. jmps not_a_chance
  1232. inform_later:
  1233. or PagingFlags, 1
  1234. not_a_chance:
  1235. ret
  1236. UnSetKernelDS FS
  1237. cEnd nogen
  1238. cProc DiscardFreeBlocks,<PUBLIC,NEAR>
  1239. cBegin nogen
  1240. push es
  1241. push ds
  1242. GENTER32
  1243. ReSetKernelDS FS
  1244. and PagingFlags, NOT 1
  1245. mov esi, ds:[di].phi_first
  1246. mov esi, ds:[esi].pga_freenext
  1247. dfb_next:
  1248. cmp esi, ds:[esi].pga_next ; Sentinel?
  1249. je short dfb_done ; yes, all done
  1250. push esi
  1251. push edi
  1252. cmp ds:[esi].pga_size, 4096
  1253. jb short no_win386discard ; Quick exit
  1254. mov ebx, ds:[esi].pga_address
  1255. mov esi, ds:[esi].pga_size
  1256. add esi, ebx ; First byte past block
  1257. shr esi, 12 ; Page of this byte
  1258. add ebx, 0fffh
  1259. shr ebx, 12 ; First page we can discard
  1260. sub esi, ebx ; # pages we can discard
  1261. jbe short no_win386discard ; none to discard
  1262. mov di, si
  1263. shr esi, 16 ; SI:DI is # pages to discard
  1264. mov cx, bx
  1265. shr ebx, 16 ; BX:CX is first page to discard
  1266. DPMICALL 0701h ; Say goodbye, pages
  1267. no_win386discard:
  1268. pop edi
  1269. pop esi
  1270. mov esi, ds:[esi].pga_freenext
  1271. jmps dfb_next
  1272. dfb_done:
  1273. GLEAVE32
  1274. UnSetKernelDS FS
  1275. pop ds
  1276. pop es
  1277. ret
  1278. cEnd nogen
  1279. ;---------------------------------------------------------------------------
  1280. ;
  1281. ; guc_findfree
  1282. ;
  1283. ; helper function for guncompact
  1284. ;
  1285. ; finds the next free block below the address
  1286. ; in ECX into which the block pointed to by ESI will fit.
  1287. ;
  1288. ; Entry:
  1289. ; ECX = maximum address (desired swap area)
  1290. ; DS:DI = global heap info
  1291. ; ESI = arena of block to move
  1292. ;
  1293. ; Exit:
  1294. ; Carry clear if block found, set if not
  1295. ; EDX = free block arena
  1296. ;
  1297. ; Uses:
  1298. ; EAX, EDX
  1299. ;
  1300. ; Preserves:
  1301. ; EBX, ECX, ESI, EDI
  1302. ;
  1303. ; History:
  1304. ; Fri Jun 7, 1991 9:38 -by- Craig Critchley [craigc]
  1305. ; Wrote it...
  1306. ;
  1307. ;--------------------------------------------------------------------------
  1308. cProc guc_findfree, <NEAR, PUBLIC>
  1309. cBegin nogen
  1310. mov edx, ds:[di].phi_last
  1311. mov edx, ds:[edx].pga_freeprev
  1312. gucff_check:
  1313. cmp edx, ds:[edx].pga_prev ; if at start, not found
  1314. jz short gucff_notfound
  1315. mov eax, ds:[edx].pga_address ; is it out of swap area
  1316. add eax, ds:[edx].pga_size
  1317. cmp eax, ecx
  1318. jae short gucff_nextblock
  1319. mov eax, ds:[esi].pga_size ; does it fit
  1320. cmp ds:[edx].pga_size, eax
  1321. jb short gucff_nextblock
  1322. clc ; return it in EDX
  1323. ret
  1324. gucff_nextblock:
  1325. mov edx, ds:[edx].pga_freeprev ; previous free block
  1326. jmp short gucff_check
  1327. gucff_notfound:
  1328. stc ; return error
  1329. ret
  1330. cEnd nogen
  1331. ;-----------------------------------------------------------------------------
  1332. ;
  1333. ; guncompact -
  1334. ;
  1335. ; this function moves segments that are not free or discardable code
  1336. ; out of the intended swap area. don't take the name too seriously.
  1337. ;
  1338. ; Entry:
  1339. ; ECX = size of intended swap area
  1340. ; DS:DI = global heap info
  1341. ; FS = global heap
  1342. ;
  1343. ; Exit:
  1344. ; Carry clear if space could be cleared, set if not
  1345. ;
  1346. ; Registers used:
  1347. ; EAX, EBX, ECX, EDX, ESI
  1348. ;
  1349. ; Called by:
  1350. ; greserve
  1351. ;
  1352. ; Calls:
  1353. ; gmoveable
  1354. ; gmovebusy
  1355. ;
  1356. ; History:
  1357. ; Fri Jun 7, 1991 9:38 -by- Craig Critchley [craigc]
  1358. ; Wrote it...
  1359. ;
  1360. ;-----------------------------------------------------------------------------
  1361. cProc guncompact, <NEAR, PUBLIC>
  1362. cBegin <nogen>
  1363. mov edx, [di].phi_last ; point to last block
  1364. mov ebx, pga_prev
  1365. sub ecx, ds:[edx].pga_address ; find desired code fence
  1366. neg ecx
  1367. guc_trymovingblock:
  1368. mov esi, ds:[edx+ebx] ; block under current one...
  1369. cmp ds:[esi].pga_owner, 0 ; don't move free blocks
  1370. jz short guc_skipblock
  1371. test ds:[esi].pga_flags, GA_DISCCODE ; don't move discardable code
  1372. jnz short guc_skipblock
  1373. cmp ds:[esi].pga_owner, GA_NOT_THERE ; ignore not-there's
  1374. jz short guc_skipblock
  1375. call gmoveable ; can this block be moved?
  1376. jz short guc_error ; if not, swap area toast
  1377. push edx
  1378. call guc_findfree ; find a block to move it into
  1379. pop eax
  1380. jc short guc_error ; error if didn't find one
  1381. push eax
  1382. xchg edx, esi
  1383. call gmovebusy ; move it
  1384. xchg edx, esi
  1385. pop edx
  1386. ;;; can we just fall thru the block ought to be free now...
  1387. jmp short guc_trymovingblock ; move what's there now
  1388. guc_skipblock:
  1389. mov edx, esi ; this block now first cleared
  1390. cmp ds:[edx].pga_address, ecx ; big enough?
  1391. ja short guc_trymovingblock
  1392. guc_done:
  1393. clc ; success-o-mundo!!
  1394. ret
  1395. guc_error:
  1396. stc ; if not, we could not
  1397. ret ; clear swap area
  1398. cEnd <nogen>
  1399. sEnd CODE
  1400. end