Leaked source code of windows server 2003
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.

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